diff --git a/.appveyor.yml b/.appveyor.yml index 3cb5d9a9399..7ca7d58c4ce 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,6 +1,6 @@ clone_depth: 1 version: "{build}" -image: Visual Studio 2015 +image: Visual Studio 2017 platform: - x86 - x64 @@ -16,8 +16,12 @@ build_script: - cd build - ps: $env:CMAKE_PLATFORM="$(if ($env:PLATFORM -eq 'x64') { 'x64' } else { '' })" - ps: $env:QT_SUFFIX="$(if ($env:PLATFORM -eq 'x64') { '_64' } else { '' })" - - cmake -DUSE_COMPILE_CACHE=ON -DCACHE_TOOL=%APPVEYOR_BUILD_FOLDER%/clcache.4.1.0/clcache-4.1.0/clcache.exe -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=c:/Qt/5.9/msvc2015%QT_SUFFIX%;c:/tools/vcpkg/installed/%PLATFORM%-windows -DCMAKE_GENERATOR_PLATFORM="%CMAKE_PLATFORM%" .. + - cmake -DUSE_COMPILE_CACHE=ON -DCACHE_TOOL=%APPVEYOR_BUILD_FOLDER%/clcache.4.1.0/clcache-4.1.0/clcache.exe -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=c:/Qt/5.12/msvc2017%QT_SUFFIX%;c:/tools/vcpkg/installed/%PLATFORM%-windows -DCMAKE_GENERATOR_PLATFORM="%CMAKE_PLATFORM%" .. - cmake --build . -- /maxcpucount:4 - cmake --build . --target tests + - cmake --build . --target package +artifacts: + - path: 'build\lmms-*.exe' + name: Installer cache: - c:/tools/vcpkg/installed diff --git a/.circleci/config.yml b/.circleci/config.yml index 4174ba1effb..f7f509d7e90 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,6 +12,18 @@ shared: key: ccache-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }}-{{ .BuildNum }} paths: - ~/.ccache + restore_homebrew_cache: &restore_homebrew_cache + restore_cache: + keys: + - homebrew-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }} + - homebrew-{{ arch }}-{{ .Environment.CIRCLE_JOB }} + - homebrew-{{ arch }} + save_homebrew_cache: &save_homebrew_cache + save_cache: + key: homebrew-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }}-{{ .BuildNum }} + paths: + - ~/Library/Caches/Homebrew + - /usr/local/Homebrew ccache_stats: &ccache_stats run: @@ -30,6 +42,14 @@ shared: mkdir -p /tmp/artifacts # Workaround for failing submodule fetching git config --global --unset url."ssh://git@github.com".insteadOf || true + if [[ -n "${CIRCLE_PR_NUMBER}" ]] + then + echo "Fetching out merged pull request" + git fetch -u origin refs/pull/${CIRCLE_PR_NUMBER}/merge:pr/merge + git checkout pr/merge + else + echo "Not a pull request" + fi # Commmon environment variables common_environment: &common_environment @@ -59,6 +79,15 @@ jobs: - run: name: Build tests command: cd build && make tests + - run: + name: Build installer + command: | + cd build + make package + cp ./lmms-*.exe /tmp/artifacts/ + - store_artifacts: + path: /tmp/artifacts/ + destination: / - *ccache_stats - *save_cache mingw64: @@ -79,11 +108,20 @@ jobs: - run: name: Build tests command: cd build && make tests + - run: + name: Build installer + command: | + cd build + make package + cp ./lmms-*.exe /tmp/artifacts/ + - store_artifacts: + path: /tmp/artifacts/ + destination: / - *ccache_stats - *save_cache linux.gcc: docker: - - image: lmmsci/linux.gcc:18.04 + - image: lmmsci/linux.gcc:16.04 environment: <<: *common_environment steps: @@ -92,7 +130,10 @@ jobs: - *restore_cache - run: name: Configure - command: mkdir build && cd build && cmake .. $CMAKE_OPTS -DCMAKE_INSTALL_PREFIX=./install + command: | + source /opt/qt5*/bin/qt5*-env.sh || true + mkdir build && cd build + cmake .. $CMAKE_OPTS -DCMAKE_INSTALL_PREFIX=./install - run: name: Build command: cd build && make @@ -125,10 +166,56 @@ jobs: - run: name: Shellcheck command: shellcheck $(find "./cmake/" -type f -name '*.sh' -o -name "*.sh.in") + macos: + environment: + <<: *common_environment + macos: + xcode: "9.3.1" + steps: + - checkout + - *init + - *restore_homebrew_cache + - *restore_cache + - run: + name: Install Homebrew dependencies + command: | + # unlink Homebrew's python 2 to prevent an node-gyp error + brew unlink python@2 || true + brew update && brew install ccache fftw cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk fluid-synth portaudio fltk qt5 carla + - run: + name: Install nodejs dependencies + command: npm install -g appdmg + - run: + name: Building + command: | + mkdir build && cd build + cmake .. -DCMAKE_INSTALL_PREFIX="../target" -DCMAKE_PREFIX_PATH="$(brew --prefix qt5)" $CMAKE_OPTS -DUSE_WERROR=OFF + make + - run: + name: Build tests + command: cd build && make tests + - run: + name: Run tests + command: build/tests/tests + - run: + name: Build DMG + command: | + cd build + make install + make dmg + cp ./lmms-*.dmg /tmp/artifacts/ + - store_artifacts: + path: /tmp/artifacts/ + destination: / + - *save_cache + - *save_homebrew_cache + + workflows: version: 2 build-and-test: jobs: + - macos - mingw32 - mingw64 - linux.gcc diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..2d4a9f97563 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[*] +indent_style = tab +tab_width = 4 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000000..8a8b03635cb --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +custom: https://lmms.io/get-involved/#donate diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000..fcc87560172 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,36 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +# Please search the issue tracker for existing bug reports before submitting your own. Delete this line to confirm no similar report has been posted yet. + +### Bug Summary + +#### Steps to reproduce + +#### Expected behavior + +#### Actual behavior + +#### Screenshot + +#### Affected LMMS versions + + + +#### Logs +
+ Click to expand +
+
+
+
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000000..2c51f276e3d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,4 @@ +contact_links: +- name: Get help on Discord + url: https://lmms.io/chat/ + about: Need help? Have a question? Reach out to other LMMS users on our Discord server! diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000000..f9a0ae1928c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,18 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +# Please search the issue tracker for existing feature requests before submitting your own. Delete this line to confirm no similar request has been posted yet. + +### Enhancement Summary + +#### Justification + +#### Mockup + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..b22a35ef110 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,11 @@ +## 목적 + + +## 변경 사항 + + +## TODO (Optional) + + +## Followers (Optional) +- 해당 PR을 인지하고 있어야 할 팀원을 태그해주세요. \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 28d6c5d46de..8a9871b7a7b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,3 +34,9 @@ [submodule "doc/wiki"] path = doc/wiki url = https://github.com/lmms/lmms.wiki.git +[submodule "src/3rdparty/ringbuffer"] + path = src/3rdparty/ringbuffer + url = https://github.com/JohannesLorenz/ringbuffer.git +[submodule "plugins/carlabase/carla"] + path = plugins/carlabase/carla + url = https://github.com/falktx/carla diff --git a/.mailmap b/.mailmap index 71b6697c8b7..14d4754ce87 100644 --- a/.mailmap +++ b/.mailmap @@ -29,3 +29,5 @@ grejppi Johannes Lorenz Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com> Noah Brecht +Olivier Humbert +Hussam al-Homsi Hussam Eddin Alhomsi diff --git a/.travis.yml b/.travis.yml index b3cb8aa7c8e..765fdb14cdd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: cpp compiler: gcc -dist: trusty +dist: xenial sudo: required cache: directories: @@ -11,8 +11,6 @@ matrix: include: - env: TYPE=style - os: linux - - env: TARGET_OS=win32 - - env: TARGET_OS=win64 - env: TARGET_OS=debian-sid TARGET_DEPLOY=True git: depth: false @@ -24,7 +22,7 @@ matrix: git: depth: false - os: osx - osx_image: xcode8.3 + osx_image: xcode9.4 before_install: # appdmg doesn't work with old Node.js - if [ "$TRAVIS_OS_NAME" = osx ]; then nvm install 10; fi @@ -33,17 +31,3 @@ script: ${TRAVIS_BUILD_DIR}/.travis/script.sh after_script: ${TRAVIS_BUILD_DIR}/.travis/after_script.sh before_deploy: - if [ "$TARGET_OS" != debian-sid ]; then make package; fi -deploy: - provider: releases - api_key: - secure: d4a+x4Gugpss7JK2DcHjyBZDmEFFh4iVfKDfITSD50T6Mc6At4LMgojvEu+6qT6IyOY2vm3UVT6fhyeuWDTRDwW9tfFlaHVA0h8aTRD+eAXOA7pQ8rEMwQO3+WCKuKTfEqUkpL4wxhww8dpkv54tqeIs0S4TBqz9tk8UhzU7XbE= - file_glob: true - file: - - lmms-${TRAVIS_TAG:1}-$TARGET_OS.exe - - /var/cache/pbuilder/result/lmms_*.tar.xz - skip_cleanup: true - on: - tags: true - all_branches: true - condition: '"$TARGET_DEPLOY" = True' - repo: LMMS/lmms diff --git a/.travis/linux..before_install.sh b/.travis/linux..before_install.sh index c2e578b5422..9bf8aac01da 100755 --- a/.travis/linux..before_install.sh +++ b/.travis/linux..before_install.sh @@ -2,10 +2,7 @@ set -e -sudo add-apt-repository ppa:beineri/opt-qt592-trusty -y -sudo add-apt-repository ppa:andrewrk/libgroove -y -sudo sed -e "s/trusty/precise/" -i \ - /etc/apt/sources.list.d/andrewrk-libgroove-trusty.list +sudo add-apt-repository ppa:beineri/opt-qt592-xenial -y sudo dpkg --add-architecture i386 sudo apt-get update -qq || true diff --git a/.travis/linux..install.sh b/.travis/linux..install.sh index 2f1262d071b..d56645603a1 100755 --- a/.travis/linux..install.sh +++ b/.travis/linux..install.sh @@ -4,7 +4,7 @@ set -e PACKAGES="cmake libsndfile-dev fftw3-dev libvorbis-dev libogg-dev libmp3lame-dev libasound2-dev libjack-jackd2-dev libsdl-dev libsamplerate0-dev libstk0-dev stk - libfluidsynth-dev portaudio19-dev g++-multilib libfltk1.3-dev + libfluidsynth-dev portaudio19-dev g++-multilib libfltk1.3-dev fluid libgig-dev libsoundio-dev qt59base qt59translations qt59tools" # swh build dependencies @@ -13,14 +13,11 @@ SWH_PACKAGES="perl libxml2-utils libxml-perl liblist-moreutils-perl" # VST dependencies VST_PACKAGES="wine-dev qt59x11extras qtbase5-private-dev libxcb-util0-dev libxcb-keysyms1-dev" +# LV2 dependencies; libsuil-dev is not required +LV2_PACKAGES="lv2-dev liblilv-dev" + # Help with unmet dependencies -PACKAGES="$PACKAGES $SWH_PACKAGES $VST_PACKAGES libjack-jackd2-0" +PACKAGES="$PACKAGES $SWH_PACKAGES $VST_PACKAGES $LV2_PACKAGES libjack-jackd2-0" # shellcheck disable=SC2086 sudo apt-get install -y $PACKAGES - -# kxstudio repo offers Carla; avoid package conflicts (wine, etc) by running last -sudo add-apt-repository -y ppa:kxstudio-debian/libs -sudo add-apt-repository -y ppa:kxstudio-debian/apps -sudo apt-get update -sudo apt-get install -y carla diff --git a/.travis/osx..before_install.sh b/.travis/osx..before_install.sh index b59920a5eef..61f25af66ff 100755 --- a/.travis/osx..before_install.sh +++ b/.travis/osx..before_install.sh @@ -3,3 +3,5 @@ set -e brew update +# Python 2 may cause conflicts on dependency installation +brew unlink python@2 || true diff --git a/.travis/osx..install.sh b/.travis/osx..install.sh index e3dd670bfb2..93d478c40f4 100755 --- a/.travis/osx..install.sh +++ b/.travis/osx..install.sh @@ -2,7 +2,7 @@ set -e -PACKAGES="cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk fluid-synth portaudio node fltk qt5 carla" +PACKAGES="cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk fluid-synth portaudio node fltk qt carla" if "${TRAVIS}"; then PACKAGES="$PACKAGES ccache" diff --git a/.travis/script.sh b/.travis/script.sh index 70391a76261..21d27b08025 100755 --- a/.travis/script.sh +++ b/.travis/script.sh @@ -13,7 +13,7 @@ if [ "$TYPE" = 'style' ]; then else - export CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=RelWithDebInfo" + export CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUNDLE_QT_TRANSLATIONS=ON" if [ -z "$TRAVIS_TAG" ]; then export CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_CCACHE=ON" @@ -22,7 +22,7 @@ else "$TRAVIS_BUILD_DIR/.travis/$TRAVIS_OS_NAME.$TARGET_OS.script.sh" # Package and upload non-tagged builds - if [ ! -z "$TRAVIS_TAG" ]; then + if [ -n "$TRAVIS_TAG" ]; then # Skip, handled by travis deploy instead exit 0 elif [[ $TARGET_OS == win* ]]; then @@ -42,5 +42,7 @@ else fi echo "Uploading $PACKAGE to transfer.sh..." - curl --upload-file "$PACKAGE" "https://transfer.sh/$PACKAGE" || true + # Limit the connection time to 3 minutes and total upload time to 5 minutes + # Otherwise the build may hang + curl --connect-timeout 180 --max-time 300 --upload-file "$PACKAGE" "https://transfer.sh/$PACKAGE" || true fi diff --git a/CMakeLists.txt b/CMakeLists.txt index bd9d376e286..d320bf9e0f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.3) PROJECT(lmms) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules" ${CMAKE_MODULE_PATH}) +SET(LMMS_BINARY_DIR ${CMAKE_BINARY_DIR}) +SET(LMMS_SOURCE_DIR ${CMAKE_SOURCE_DIR}) IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0005 NEW) @@ -13,8 +15,10 @@ IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0050 OLD) ENDIF() CMAKE_POLICY(SET CMP0020 NEW) + CMAKE_POLICY(SET CMP0057 NEW) ENDIF(COMMAND CMAKE_POLICY) +INCLUDE(PluginList) INCLUDE(CheckSubmodules) INCLUDE(AddFileDependencies) INCLUDE(CheckIncludeFiles) @@ -23,7 +27,7 @@ INCLUDE(GenerateExportHeader) STRING(TOUPPER "${CMAKE_PROJECT_NAME}" PROJECT_NAME_UCASE) -SET(PROJECT_YEAR 2019) +SET(PROJECT_YEAR 2020) SET(PROJECT_AUTHOR "LMMS Developers") SET(PROJECT_URL "https://lmms.io") @@ -32,7 +36,7 @@ SET(PROJECT_DESCRIPTION "${PROJECT_NAME_UCASE} - Free music production software" SET(PROJECT_COPYRIGHT "2008-${PROJECT_YEAR} ${PROJECT_AUTHOR}") SET(VERSION_MAJOR "1") SET(VERSION_MINOR "2") -SET(VERSION_RELEASE "0") +SET(VERSION_RELEASE "2") SET(VERSION_STAGE "") SET(VERSION_BUILD "0") SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}") @@ -54,6 +58,8 @@ OPTION(WANT_CARLA "Include Carla plugin" ON) OPTION(WANT_CMT "Include Computer Music Toolkit LADSPA plugins" ON) OPTION(WANT_JACK "Include JACK (Jack Audio Connection Kit) support" ON) OPTION(WANT_WEAKJACK "Loosely link JACK libraries" ON) +OPTION(WANT_LV2 "Include Lv2 plugins" ON) +OPTION(WANT_SUIL "Include SUIL for LV2 plugin UIs" ON) OPTION(WANT_MP3LAME "Include MP3/Lame support" ON) OPTION(WANT_OGGVORBIS "Include OGG/Vorbis support" ON) OPTION(WANT_PULSEAUDIO "Include PulseAudio support" ON) @@ -71,6 +77,7 @@ OPTION(WANT_VST_32 "Include 32-bit VST support" ON) OPTION(WANT_VST_64 "Include 64-bit VST support" ON) OPTION(WANT_WINMM "Include WinMM MIDI support" OFF) OPTION(WANT_DEBUG_FPE "Debug floating point exceptions" OFF) +OPTION(BUNDLE_QT_TRANSLATIONS "Install Qt translation files for LMMS" OFF) IF(LMMS_BUILD_APPLE) @@ -95,6 +102,7 @@ IF(LMMS_BUILD_WIN32) SET(WANT_SNDIO OFF) SET(WANT_SOUNDIO OFF) SET(WANT_WINMM ON) + SET(BUNDLE_QT_TRANSLATIONS ON) SET(LMMS_HAVE_WINMM TRUE) SET(STATUS_ALSA "") SET(STATUS_JACK "") @@ -124,8 +132,11 @@ CHECK_INCLUDE_FILES(pthread.h LMMS_HAVE_PTHREAD_H) CHECK_INCLUDE_FILES(semaphore.h LMMS_HAVE_SEMAPHORE_H) CHECK_INCLUDE_FILES(unistd.h LMMS_HAVE_UNISTD_H) CHECK_INCLUDE_FILES(sys/types.h LMMS_HAVE_SYS_TYPES_H) +CHECK_INCLUDE_FILES(sys/socket.h LMMS_HAVE_SYS_SOCKET_H) +CHECK_INCLUDE_FILES(sys/un.h LMMS_HAVE_SYS_UN_H) CHECK_INCLUDE_FILES(sys/ipc.h LMMS_HAVE_SYS_IPC_H) CHECK_INCLUDE_FILES(sys/shm.h LMMS_HAVE_SYS_SHM_H) +CHECK_INCLUDE_FILES(sys/mman.h LMMS_HAVE_SYS_SHM_H) CHECK_INCLUDE_FILES(sys/time.h LMMS_HAVE_SYS_TIME_H) CHECK_INCLUDE_FILES(sys/times.h LMMS_HAVE_SYS_TIMES_H) CHECK_INCLUDE_FILES(sched.h LMMS_HAVE_SCHED_H) @@ -140,7 +151,7 @@ CHECK_INCLUDE_FILES(locale.h LMMS_HAVE_LOCALE_H) LIST(APPEND CMAKE_PREFIX_PATH "${CMAKE_INSTALL_PREFIX}") -FIND_PACKAGE(Qt5 COMPONENTS Core Gui Widgets Xml REQUIRED) +FIND_PACKAGE(Qt5 5.6.0 COMPONENTS Core Gui Widgets Xml REQUIRED) FIND_PACKAGE(Qt5 COMPONENTS LinguistTools QUIET) INCLUDE_DIRECTORIES( @@ -165,6 +176,17 @@ ENDIF() # Resolve Qt5::qmake to full path for use in packaging scripts GET_TARGET_PROPERTY(QT_QMAKE_EXECUTABLE "${Qt5Core_QMAKE_EXECUTABLE}" IMPORTED_LOCATION) +# Find the location of Qt translation files +execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} -query QT_INSTALL_TRANSLATIONS + OUTPUT_VARIABLE QT_TRANSLATIONS_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) +IF(EXISTS "${QT_TRANSLATIONS_DIR}") + MESSAGE("-- Found Qt translations in ${QT_TRANSLATIONS_DIR}") + ADD_DEFINITIONS(-D'QT_TRANSLATIONS_DIR="${QT_TRANSLATIONS_DIR}"') +ENDIF() + FIND_PACKAGE(Qt5Test) SET(QT_QTTEST_LIBRARY Qt5::Test) @@ -178,6 +200,39 @@ IF(NOT SNDFILE_VERSION VERSION_LESS 1.0.26) SET(LMMS_HAVE_SF_COMPLEVEL TRUE) ENDIF() +IF(WANT_LV2) + IF(PKG_CONFIG_FOUND) + PKG_CHECK_MODULES(LV2 lv2) + PKG_CHECK_MODULES(LILV lilv-0) + IF(LV2_FOUND AND LILV_FOUND) + SET(LMMS_HAVE_LV2 TRUE) + SET(STATUS_LV2 "OK") + ELSE() + SET(STATUS_LV2 "not found, install it or set PKG_CONFIG_PATH appropriately") + ENDIF() + ELSE() + SET(STATUS_LV2 "not found, requires pkg-config") + ENDIF() +ELSE(WANT_LV2) + SET(STATUS_LV2 "not built as requested") +ENDIF(WANT_LV2) + +IF(WANT_SUIL) + IF(PKG_CONFIG_FOUND) + PKG_CHECK_MODULES(SUIL suil-0) + IF(SUIL_FOUND) + SET(LMMS_HAVE_SUIL TRUE) + SET(STATUS_SUIL "OK") + ELSE() + SET(STATUS_SUIL "not found, install it or set PKG_CONFIG_PATH appropriately") + ENDIF() + ELSE() + SET(STATUS_SUIL "not found, requires pkg-config") + ENDIF() +ELSE(WANT_SUIL) + SET(STATUS_SUIL "not built as requested") +ENDIF(WANT_SUIL) + IF(WANT_CALF) SET(LMMS_HAVE_CALF TRUE) SET(STATUS_CALF "OK") @@ -225,7 +280,8 @@ IF(WANT_CARLA) SET(LMMS_HAVE_CARLA TRUE) SET(STATUS_CARLA "OK") ELSE(CARLA_FOUND) - SET(STATUS_CARLA "not found, please install the latest carla") + SET(LMMS_HAVE_WEAKCARLA TRUE) + SET(STATUS_CARLA "OK (weak linking enabled)") ENDIF(CARLA_FOUND) ENDIF(WANT_CARLA) @@ -434,9 +490,9 @@ If(WANT_GIG) ENDIF(WANT_GIG) # check for pthreads -IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD) +IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD OR LMMS_BUILD_FREEBSD) FIND_PACKAGE(Threads) -ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD) +ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD OR LMMS_BUILD_FREEBSD) # check for sndio (roaraudio won't work yet) IF(WANT_SNDIO) @@ -495,7 +551,7 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") # Due to a regression in gcc-4.8.X, we need to disable array-bounds check IF (CMAKE_COMPILER_IS_GNUCXX AND ((CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "4.8.0") OR (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.8.0") OR LMMS_BUILD_WIN32)) - SET(WERROR_FLAGS "${WERROR_FLAGS} -Wno-array-bounds") + SET(WERROR_FLAGS "${WERROR_FLAGS} -Wno-array-bounds -Wno-attributes") ENDIF() ELSEIF(MSVC) # Remove any existing /W flags @@ -565,18 +621,23 @@ ADD_SUBDIRECTORY(tests) ADD_SUBDIRECTORY(data) ADD_SUBDIRECTORY(doc) -# post-install tasks -ADD_SUBDIRECTORY(cmake/postinstall) +# install tasks +ADD_SUBDIRECTORY(cmake/install) -ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_BINARY_DIR}/lmms.1.gz" - COMMAND gzip -c ${CMAKE_SOURCE_DIR}/doc/lmms.1 > ${CMAKE_BINARY_DIR}/lmms.1.gz - DEPENDS "${CMAKE_SOURCE_DIR}/doc/lmms.1" - COMMENT "Generating lmms.1.gz" - VERBATIM) +FIND_PACKAGE(UnixCommands) +IF(GZIP) + ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_BINARY_DIR}/lmms.1.gz" + COMMAND ${GZIP} -c ${CMAKE_SOURCE_DIR}/doc/lmms.1 > ${CMAKE_BINARY_DIR}/lmms.1.gz + DEPENDS "${CMAKE_SOURCE_DIR}/doc/lmms.1" + COMMENT "Generating lmms.1.gz" + VERBATIM) -ADD_CUSTOM_TARGET(manpage ALL - DEPENDS "${CMAKE_BINARY_DIR}/lmms.1.gz") + ADD_CUSTOM_TARGET(manpage ALL + DEPENDS "${CMAKE_BINARY_DIR}/lmms.1.gz") +ELSEIF(UNIX) + MESSAGE(FATAL_ERROR "Can't find gzip required for generating lmms.1.gz") +ENDIF() # install headers @@ -676,6 +737,8 @@ MESSAGE( MESSAGE( "Optional plugins\n" "----------------\n" +"* Lv2 plugins : ${STATUS_LV2}\n" +"* SUIL for plugin UIs : ${STATUS_SUIL}\n" "* ZynAddSubFX instrument : ${STATUS_ZYN}\n" "* Carla Patchbay & Rack : ${STATUS_CARLA}\n" "* SoundFont2 player : ${STATUS_FLUIDSYNTH}\n" @@ -706,4 +769,9 @@ MESSAGE( "\n\n") SET(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION "${BIN_DIR}") +if(MSVC) + # We can't set this on the install time according to the configuration + SET(CMAKE_INSTALL_DEBUG_LIBRARIES TRUE) + SET(CMAKE_INSTALL_UCRT_LIBRARIES TRUE) +endif() INCLUDE(InstallRequiredSystemLibraries) diff --git a/cmake/install/CMakeLists.txt b/cmake/install/CMakeLists.txt new file mode 100644 index 00000000000..cd4100c9bf7 --- /dev/null +++ b/cmake/install/CMakeLists.txt @@ -0,0 +1,42 @@ +SET(PLUGIN_FILES "") +IF(LMMS_BUILD_WIN32) + INSTALL(FILES $ DESTINATION platforms) +ENDIF() + +IF(LMMS_BUILD_WIN32 OR LMMS_INSTALL_DEPENDENCIES) + include(InstallTargetDependencies) + + # Collect directories to search for DLLs + GET_FILENAME_COMPONENT(QTBIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH) + set(LIB_DIRS "${QTBIN_DIR}") + + GET_PROPERTY(PLUGINS_BUILT GLOBAL PROPERTY PLUGINS_BUILT) + + IF(LMMS_BUILD_WIN32) + SET(LMMS_DEP_DESTINATION ${BIN_DIR}) + SET(PLUGIN_DEP_DESTINATION ${BIN_DIR}) + ELSE() + SET(LMMS_DEP_DESTINATION ${LIB_DIR}) + SET(PLUGIN_DEP_DESTINATION ${LIB_DIR}) + ENDIF() + + INSTALL_TARGET_DEPENDENCIES( + NAME "main_binary" + TARGETS lmms + DESTINATION "${LMMS_DEP_DESTINATION}" + LIB_DIRS ${LIB_DIRS} + ) + + INSTALL_TARGET_DEPENDENCIES( + NAME "plugins" + TARGETS ${PLUGINS_BUILT} + DESTINATION ${PLUGIN_DEP_DESTINATION} + LIB_DIRS ${LIB_DIRS} "${PLUGIN_DIR}" "${PLUGIN_DIR}/optional" + SEARCH_PATHS "${PLUGIN_DIR}" "${PLUGIN_DIR}/optional" + ) +ENDIF() + +IF(LMMS_BUILD_APPLE) + INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x ${CMAKE_BINARY_DIR}/install_apple.sh)") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_BINARY_DIR}/install_apple.sh)") +ENDIF() diff --git a/cmake/install/excludelist-win b/cmake/install/excludelist-win new file mode 100644 index 00000000000..17793a113d9 --- /dev/null +++ b/cmake/install/excludelist-win @@ -0,0 +1,23 @@ +# List of DLLs considered to be system libraries. +# This is needed when cross-compiling for Windows. +ADVAPI32.dll +COMCTL32.dll +comdlg32.dll +dwmapi.dll +GDI32.dll +IMM32.dll +KERNEL32.dll +MPR.DLL +msvcrt.dll +ole32.dll +OLEAUT32.dll +OPENGL32.DLL +SHELL32.dll +USER32.dll +UxTheme.dll +VERSION.dll +WINMM.DLL +WS2_32.dll +RPCRT4.dll +dsound.dll +SETUPAPI.dll diff --git a/cmake/linux/launch_lmms.sh b/cmake/linux/launch_lmms.sh new file mode 100644 index 00000000000..198b5711a53 --- /dev/null +++ b/cmake/linux/launch_lmms.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +export PATH="$PATH:/sbin" +if command -v carla > /dev/null 2>&1; then + CARLAPATH="$(command -v carla)" + CARLAPREFIX="${CARLAPATH%/bin*}" + echo "Carla appears to be installed on this system at $CARLAPREFIX/lib[64]/carla so we'll use it." + export LD_LIBRARY_PATH=$CARLAPREFIX/lib/carla:$CARLAPREFIX/lib64/carla:$LD_LIBRARY_PATH +else + echo "Carla does not appear to be installed. That's OK, please ignore any related library errors." +fi +export LD_LIBRARY_PATH=$DIR/usr/lib/:$DIR/usr/lib/lmms:$LD_LIBRARY_PATH +# Prevent segfault on VirualBox +if lsmod |grep vboxguest > /dev/null 2>&1; then + echo "VirtualBox detected. Forcing libgl software rendering." + export LIBGL_ALWAYS_SOFTWARE=1; +fi +if ldconfig -p | grep libjack.so.0 > /dev/null 2>&1; then + echo "Jack appears to be installed on this system, so we'll use it." +else + echo "Jack does not appear to be installed. That's OK, we'll use a dummy version instead." + export LD_LIBRARY_PATH=$DIR/usr/lib/lmms/optional:$LD_LIBRARY_PATH +fi +QT_X11_NO_NATIVE_MENUBAR=1 "$DIR"/usr/bin/lmms.real "$@" diff --git a/cmake/linux/lmms.desktop b/cmake/linux/lmms.desktop index 72a82da1724..d6a05d15f52 100644 --- a/cmake/linux/lmms.desktop +++ b/cmake/linux/lmms.desktop @@ -3,11 +3,11 @@ Name=LMMS GenericName=Music production suite GenericName[ca]=Programari de producció musical GenericName[de]=Software zur Musik-Produktion -GenericName[fr]=Ensemble pour la production musicale +GenericName[fr]=Suite de production musicale GenericName[pl]=Narzędzia do produkcji muzyki Comment=Music sequencer and synthesizer Comment[ca]=Producció fàcil de música per a tothom! -Comment[fr]=Production facile de musique pour tout le monde ! +Comment[fr]=Séquenceur et synthétiseur de musique Comment[pl]=Prosta produkcja muzyki dla każdego! Icon=lmms Exec=lmms %f diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index 0dec715f480..a1f9ff8658f 100644 --- a/cmake/linux/package_linux.sh.in +++ b/cmake/linux/package_linux.sh.in @@ -99,33 +99,8 @@ cp -R /usr/share/stk/rawwaves/ "${APPDIR}usr/share/stk/" # Create a wrapper script which calls the lmms executable mv "${APPDIR}usr/bin/lmms" "${APPDIR}usr/bin/lmms.real" -# shellcheck disable=SC1083 -cat >"${APPDIR}usr/bin/lmms" < /dev/null 2>&1; then - CARLAPATH="\$(which carla)" - CARLAPREFIX="\${CARLAPATH%/bin*}" - echo "Carla appears to be installed on this system at \$CARLAPREFIX/lib[64]/carla so we'll use it." - export LD_LIBRARY_PATH=\$CARLAPREFIX/lib/carla:\$CARLAPREFIX/lib64/carla:\$LD_LIBRARY_PATH -else - echo "Carla does not appear to be installed. That's OK, please ignore any related library errors." -fi -export LD_LIBRARY_PATH=\$DIR/usr/lib/:\$DIR/usr/lib/lmms:\$LD_LIBRARY_PATH -# Prevent segfault on VirualBox -if lsmod |grep vboxguest > /dev/null 2>&1; then - echo "VirtualBox detected. Forcing libgl software rendering." - export LIBGL_ALWAYS_SOFTWARE=1; -fi -if ldconfig -p | grep libjack.so.0 > /dev/null 2>&1; then - echo "Jack appears to be installed on this system, so we'll use it." -else - echo "Jack does not appear to be installed. That's OK, we'll use a dummy version instead." - export LD_LIBRARY_PATH=\$DIR/usr/lib/lmms/optional:\$LD_LIBRARY_PATH -fi -QT_X11_NO_NATIVE_MENUBAR=1 \$DIR/usr/bin/lmms.real "\$@" -EOL + +cp "@CMAKE_CURRENT_SOURCE_DIR@/launch_lmms.sh" "${APPDIR}usr/bin/lmms" chmod +x "${APPDIR}usr/bin/lmms" @@ -133,15 +108,7 @@ chmod +x "${APPDIR}usr/bin/lmms" unset LD_LIBRARY_PATH # Ensure linuxdeployqt can find shared objects -export LD_LIBRARY_PATH="${APPDIR}usr/lib/lmms/":$LD_LIBRARY_PATH - -# Handle wine linking -if [ -d "@WINE_32_LIBRARY_DIR@" ]; then - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:@WINE_32_LIBRARY_DIRS@ -fi -if [ -d "@WINE_64_LIBRARY_DIR@" ]; then - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:@WINE_64_LIBRARY_DIRS@ -fi +export LD_LIBRARY_PATH="${APPDIR}"usr/lib/lmms/:"${APPDIR}"usr/lib/lmms/optional:"$LD_LIBRARY_PATH" # Move executables so linuxdeployqt can find them ZYNLIB="${APPDIR}usr/lib/lmms/RemoteZynAddSubFx" @@ -153,8 +120,18 @@ VSTBIN32="${APPDIR}usr/bin/RemoteVstPlugin32.exe.so" VSTBIN64="${APPDIR}usr/bin/RemoteVstPlugin64.exe.so" mv "$ZYNLIB" "$ZYNBIN" -mv "$VSTLIB32" "$VSTBIN32" -mv "$VSTLIB64" "$VSTBIN64" +mv "$VSTLIB32" "$VSTBIN32" || true +mv "$VSTLIB64" "$VSTBIN64" || true + +# Handle wine linking +if [ -d "@WINE_32_LIBRARY_DIR@" ] && \ + ldd "$VSTBIN32" | grep "libwine\.so" | grep "not found"; then + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"@WINE_32_LIBRARY_DIRS@" +fi +if [ -d "@WINE_64_LIBRARY_DIR@" ] && \ + ldd "$VSTBIN64" | grep "libwine\.so" | grep "not found"; then + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"@WINE_64_LIBRARY_DIRS@" +fi # Patch the desktop file sed -i 's/.*Exec=.*/Exec=lmms.real/' "$DESKTOPFILE" @@ -175,22 +152,22 @@ executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale # Bundle both qt and non-qt dependencies into appimage format echo -e "\nBundling and relinking system dependencies..." echo -e ">>>>> linuxdeployqt" > "$LOGFILE" -# FIXME: -unsupported-allow-new-glibc may result in an AppImage which is unusable on old systems. # shellcheck disable=SC2086 -"$LINUXDEPLOYQT" "$DESKTOPFILE" $executables -unsupported-allow-new-glibc -bundle-non-qt-libs -verbose=$VERBOSITY $STRIP >> "$LOGFILE" 2>&1 +"$LINUXDEPLOYQT" "$DESKTOPFILE" $executables -bundle-non-qt-libs -verbose=$VERBOSITY $STRIP >> "$LOGFILE" 2>&1 success "Bundled and relinked dependencies" # Link to original location so lmms can find them ln -sr "$ZYNBIN" "$ZYNLIB" -ln -sr "$VSTBIN32" "$VSTLIB32" -ln -sr "$VSTBIN64" "$VSTLIB64" +ln -sr "$VSTBIN32" "$VSTLIB32" || true +ln -sr "$VSTBIN64" "$VSTLIB64" || true # Remove wine library conflict rm -f "${APPDIR}/usr/lib/libwine.so.1" # Use system-provided carla rm -f "${APPDIR}usr/lib/"libcarla*.so +rm -f "${APPDIR}usr/lib/lmms/optional/"libcarla*.so # Remove bundled jack in LD_LIBRARY_PATH if exists if [ -e "${APPDIR}/usr/lib/libjack.so.0" ]; then diff --git a/cmake/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake index efa3e5b468e..675433e631b 100644 --- a/cmake/modules/BuildPlugin.cmake +++ b/cmake/modules/BuildPlugin.cmake @@ -62,7 +62,10 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) TARGET_LINK_LIBRARIES(${PLUGIN_NAME} lmms) ENDIF(LMMS_BUILD_WIN32) - INSTALL(TARGETS ${PLUGIN_NAME} DESTINATION "${PLUGIN_DIR}") + INSTALL(TARGETS ${PLUGIN_NAME} + LIBRARY DESTINATION "${PLUGIN_DIR}" + RUNTIME DESTINATION "${PLUGIN_DIR}" + ) IF(LMMS_BUILD_APPLE) IF ("${PLUGIN_LINK}" STREQUAL "SHARED") @@ -72,9 +75,11 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) ENDIF() ADD_DEPENDENCIES(${PLUGIN_NAME} lmms) ENDIF(LMMS_BUILD_APPLE) - IF(LMMS_BUILD_WIN32 AND STRIP) + IF(LMMS_BUILD_WIN32) + IF(STRIP) + ADD_CUSTOM_COMMAND(TARGET ${PLUGIN_NAME} POST_BUILD COMMAND ${STRIP} "$") + ENDIF() SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES PREFIX "") - ADD_CUSTOM_COMMAND(TARGET ${PLUGIN_NAME} POST_BUILD COMMAND ${STRIP} "$") ENDIF() SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${RCC_OUT} ${plugin_MOC_out}") @@ -89,5 +94,8 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) TARGET_INCLUDE_DIRECTORIES(${PLUGIN_NAME} PUBLIC $ ) + + SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT ${PLUGIN_NAME}) + GET_PROPERTY(PLUGINS_BUILT GLOBAL PROPERTY PLUGINS_BUILT) ENDMACRO(BUILD_PLUGIN) diff --git a/cmake/modules/CheckSubmodules.cmake b/cmake/modules/CheckSubmodules.cmake index 65e5be08bf9..f45885cc6fb 100644 --- a/cmake/modules/CheckSubmodules.cmake +++ b/cmake/modules/CheckSubmodules.cmake @@ -7,12 +7,12 @@ # INCLUDE(CheckSubmodules) # # Options: -# SET(SKIP_SUBMODULES "foo;bar") +# SET(PLUGIN_LIST "zynaddsubfx;...") # skips submodules for plugins not explicitely listed # # Or via command line: -# cmake -DSKIP_SUBMODULES=foo;bar +# cmake -PLUGIN_LIST=foo;bar # -# Copyright (c) 2017, Tres Finocchiaro, +# Copyright (c) 2019, Tres Finocchiaro, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. @@ -20,13 +20,15 @@ # Files which confirm a successful clone SET(VALID_CRUMBS "CMakeLists.txt;Makefile;Makefile.in;Makefile.am;configure.ac;configure.py;autogen.sh;.gitignore;LICENSE;Home.md") +OPTION(NO_SHALLOW_CLONE "Disable shallow cloning of submodules" OFF) + # Try and use the specified shallow clone on submodules, if supported SET(DEPTH_VALUE 100) # Number of times git commands will retry before failing SET(MAX_ATTEMPTS 2) -MESSAGE("\nValidating submodules...") +MESSAGE("\nChecking submodules...") IF(NOT EXISTS "${CMAKE_SOURCE_DIR}/.gitmodules") MESSAGE("Skipping the check because .gitmodules not detected." "Please make sure you have all submodules in the source tree!" @@ -41,74 +43,106 @@ SET(LANG_BACKUP "$ENV{LANG}") SET(ENV{LC_ALL} "C") SET(ENV{LANG} "en_US") -# Assume alpha-numeric paths -STRING(REGEX MATCHALL "path = [-0-9A-Za-z/]+" SUBMODULE_LIST ${SUBMODULE_DATA}) -STRING(REGEX MATCHALL "url = [.:%-0-9A-Za-z/]+" SUBMODULE_URL_LIST ${SUBMODULE_DATA}) +# Submodule list pairs, unparsed (WARNING: Assumes alpha-numeric paths) +STRING(REGEX MATCHALL "path = [-0-9A-Za-z/]+" SUBMODULE_LIST_RAW ${SUBMODULE_DATA}) +STRING(REGEX MATCHALL "url = [.:%-0-9A-Za-z/]+" SUBMODULE_URL_RAW ${SUBMODULE_DATA}) + +# Submodule list pairs, parsed +SET(SUBMODULE_LIST "") +SET(SUBMODULE_URL "") -FOREACH(_part ${SUBMODULE_LIST}) - STRING(REPLACE "path = " "" SUBMODULE_PATH ${_part}) +FOREACH(_path ${SUBMODULE_LIST_RAW}) + # Parse SUBMODULE_PATH + STRING(REPLACE "path = " "" SUBMODULE_PATH "${_path}") - LIST(FIND SUBMODULE_LIST ${_part} SUBMODULE_INDEX) - LIST(GET SUBMODULE_URL_LIST ${SUBMODULE_INDEX} _url) - STRING(REPLACE "url = " "" SUBMODULE_URL ${_url}) + # Grab index for matching SUBMODULE_URL + LIST(FIND SUBMODULE_LIST_RAW "${_path}" SUBMODULE_INDEX) + LIST(GET SUBMODULE_URL_RAW ${SUBMODULE_INDEX} _url) + + # Parse SUBMODULE_URL + STRING(REPLACE "url = " "" SUBMODULE_URL "${_url}") - # Remove submodules from validation as specified in -DSKIP_SUBMODULES=foo;bar SET(SKIP false) + + # Loop over skipped plugins, add to SKIP_SUBMODULES (e.g. -DPLUGIN_LIST=foo;bar) + IF(${SUBMODULE_PATH} MATCHES "^plugins/") + SET(REMOVE_PLUGIN true) + FOREACH(_plugin ${PLUGIN_LIST}) + IF(_plugin STREQUAL "") + CONTINUE() + ENDIF() + IF(${SUBMODULE_PATH} MATCHES "${_plugin}") + SET(REMOVE_PLUGIN false) + ENDIF() + ENDFOREACH() + + IF(REMOVE_PLUGIN) + LIST(APPEND SKIP_SUBMODULES "${SUBMODULE_PATH}") + ENDIF() + ENDIF() + + # Finally, loop and mark "SKIP" on match IF(SKIP_SUBMODULES) FOREACH(_skip ${SKIP_SUBMODULES}) - IF(${SUBMODULE_PATH} MATCHES ${_skip}) - MESSAGE("-- Skipping ${SUBMODULE_PATH} matches \"${_skip}\"") + IF("${SUBMODULE_PATH}" MATCHES "${_skip}") + MESSAGE("-- Skipping ${SUBMODULE_PATH} matches \"${_skip}\" (absent in PLUGIN_LIST)") SET(SKIP true) + BREAK() ENDIF() ENDFOREACH() ENDIF() + IF(NOT SKIP) - LIST(INSERT SUBMODULE_LIST ${SUBMODULE_INDEX} ${SUBMODULE_PATH}) - LIST(INSERT SUBMODULE_URL_LIST ${SUBMODULE_INDEX} ${SUBMODULE_URL}) + LIST(APPEND SUBMODULE_LIST "${SUBMODULE_PATH}") + LIST(APPEND SUBMODULE_URL "${SUBMODULE_URL}") ENDIF() - LIST(REMOVE_ITEM SUBMODULE_LIST ${_part}) - LIST(REMOVE_ITEM SUBMODULE_URL_LIST ${_url}) ENDFOREACH() - # Once called, status is stored in GIT_RESULT respectively. # Note: Git likes to write to stderr. Don't assume stderr is error; Check GIT_RESULT instead. -MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT FORCE_REMOTE) +MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT FORCE_REMOTE NO_DEPTH) FIND_PACKAGE(Git REQUIRED) # Handle missing commits SET(FORCE_REMOTE_FLAG "${FORCE_REMOTE}") + SET(NO_DEPTH_FLAG "${NO_DEPTH}") IF(FORCE_REMOTE_FLAG) MESSAGE("-- Adding remote submodulefix to ${SUBMODULE_PATH}") EXECUTE_PROCESS( - COMMAND ${GIT_EXECUTABLE} remote rm submodulefix - COMMAND ${GIT_EXECUTABLE} remote add submodulefix ${FORCE_REMOTE} - COMMAND ${GIT_EXECUTABLE} fetch submodulefix - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH} + COMMAND "${GIT_EXECUTABLE}" remote rm submodulefix + COMMAND "${GIT_EXECUTABLE}" remote add submodulefix ${FORCE_REMOTE} + COMMAND "${GIT_EXECUTABLE}" fetch submodulefix + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}" OUTPUT_QUIET ERROR_QUIET ) # Recurse - GIT_SUBMODULE(${SUBMODULE_PATH} false false) + GIT_SUBMODULE(${SUBMODULE_PATH} false false ${NO_DEPTH_FLAG}) ELSEIF(${FORCE_DEINIT}) MESSAGE("-- Resetting ${SUBMODULE_PATH}") EXECUTE_PROCESS( - COMMAND ${GIT_EXECUTABLE} submodule deinit -f ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND "${GIT_EXECUTABLE}" submodule deinit -f "${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" OUTPUT_QUIET ) - # Recurse - GIT_SUBMODULE(${SUBMODULE_PATH} false false) + MESSAGE("-- Deleting ${CMAKE_SOURCE_DIR}/.git/${SUBMODULE_PATH}") + FILE(REMOVE_RECURSE "${CMAKE_SOURCE_DIR}/.git/modules/${SUBMODULE_PATH}") + # Recurse without depth + GIT_SUBMODULE(${SUBMODULE_PATH} false false true) ELSE() # Try to use the depth switch - SET(DEPTH_CMD "") + IF(NO_SHALLOW_CLONE OR GIT_VERSION_STRING VERSION_LESS "1.8.4" OR NO_DEPTH_FLAG) + # Shallow submodules were introduced in 1.8.4 MESSAGE("-- Fetching ${SUBMODULE_PATH}") - IF(DEPTH_VALUE) - SET(DEPTH_CMD "--depth" ) + SET(DEPTH_CMD "") + SET(DEPTH_VAL "") + ELSE() MESSAGE("-- Fetching ${SUBMODULE_PATH} @ --depth ${DEPTH_VALUE}") + SET(DEPTH_CMD "--depth") + SET(DEPTH_VAL "${DEPTH_VALUE}") ENDIF() EXECUTE_PROCESS( - COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ${DEPTH_CMD} ${DEPTH_VALUE} ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive ${DEPTH_CMD} ${DEPTH_VAL} "${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE GIT_RESULT OUTPUT_VARIABLE GIT_STDOUT ERROR_VARIABLE GIT_STDERR @@ -124,7 +158,7 @@ SET(RETRY_PHRASES "Failed to recurse;cannot create directory;already exists;${MI # Attempt to do lazy clone FOREACH(_submodule ${SUBMODULE_LIST}) - STRING(REPLACE "/" ";" PATH_PARTS ${_submodule}) + STRING(REPLACE "/" ";" PATH_PARTS "${_submodule}") LIST(REVERSE PATH_PARTS) LIST(GET PATH_PARTS 0 SUBMODULE_NAME) @@ -138,14 +172,12 @@ FOREACH(_submodule ${SUBMODULE_LIST}) ENDIF() ENDFOREACH() IF(NOT CRUMB_FOUND) - GIT_SUBMODULE(${_submodule} false false) + GIT_SUBMODULE("${_submodule}" false false false) SET(COUNTED 0) - SET(COUNTING "") # Handle edge-cases where submodule didn't clone properly or re-uses a non-empty directory WHILE(NOT GIT_RESULT EQUAL 0 AND COUNTED LESS MAX_ATTEMPTS) - LIST(APPEND COUNTING "x") - LIST(LENGTH COUNTING COUNTED) + MATH(EXPR COUNTED "${COUNTED}+1") SET(MISSING_COMMIT false) FOREACH(_phrase ${MISSING_COMMIT_PHRASES}) IF("${GIT_MESSAGE}" MATCHES "${_phrase}") @@ -154,25 +186,16 @@ FOREACH(_submodule ${SUBMODULE_LIST}) ENDIF() ENDFOREACH() FOREACH(_phrase ${RETRY_PHRASES}) - IF(${MISSING_COMMIT}) + IF(${MISSING_COMMIT} AND COUNTED LESS 2) LIST(FIND SUBMODULE_LIST ${_submodule} SUBMODULE_INDEX) LIST(GET SUBMODULE_URL_LIST ${SUBMODULE_INDEX} SUBMODULE_URL) MESSAGE("-- Retrying ${_submodule} using 'remote add submodulefix' (attempt ${COUNTED} of ${MAX_ATTEMPTS})...") - GIT_SUBMODULE(${_submodule} false "${SUBMODULE_URL}") + GIT_SUBMODULE("${_submodule}" false "${SUBMODULE_URL}" false) BREAK() ELSEIF("${GIT_MESSAGE}" MATCHES "${_phrase}") MESSAGE("-- Retrying ${_submodule} using 'deinit' (attempt ${COUNTED} of ${MAX_ATTEMPTS})...") - - # Shallow submodules were introduced in 1.8.4 - # Shallow commits can fail to clone from non-default branches, only try once - IF(GIT_VERSION_STRING VERSION_GREATER "1.8.3" AND COUNTED LESS 2) - # Try a shallow submodule clone - ELSE() - UNSET(DEPTH_VALUE) - ENDIF() - - GIT_SUBMODULE(${_submodule} true false) + GIT_SUBMODULE("${_submodule}" true false false) BREAK() ENDIF() ENDFOREACH() diff --git a/cmake/modules/CreateTempFile.cmake b/cmake/modules/CreateTempFile.cmake new file mode 100644 index 00000000000..5210342ac0d --- /dev/null +++ b/cmake/modules/CreateTempFile.cmake @@ -0,0 +1,21 @@ +function(CreateTempFilePath) + set(options CONFIG_SUFFIX) + set(oneValueArgs OUTPUT_VAR TAG) + set(multiValueArgs CONTENT) + cmake_parse_arguments(TEMP "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + # Use hash to create a unique identifier + # for this file. + string(SHA1 hashed_content "${TEMP_CONTENT}") + + set(file_name "${CMAKE_BINARY_DIR}/${TEMP_TAG}_${hashed_content}") + set(${TEMP_OUTPUT_VAR} "${file_name}" PARENT_SCOPE) + if(CONFIG_SUFFIX) + set(file_name "${file_name}_$") + endif() + + file(GENERATE OUTPUT "${file_name}" + CONTENT "${TEMP_CONTENT}") + +endfunction() diff --git a/cmake/modules/DefineInstallVar.cmake b/cmake/modules/DefineInstallVar.cmake new file mode 100644 index 00000000000..b13cb1d52b3 --- /dev/null +++ b/cmake/modules/DefineInstallVar.cmake @@ -0,0 +1,31 @@ +# This functions forwards a variable to +# the install stage. +# Parameters: +# CONTENT: Variable content. +# NAME: Variable name. +# Options: +# GENERATOR_EXPRESSION: Support generator expression for CONTENT. +function(DEFINE_INSTALL_VAR) + set(options GENERATOR_EXPRESSION) + set(oneValueArgs NAME ) + set(multiValueArgs CONTENT) + cmake_parse_arguments(VAR "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + # install(CODE) does not support generator expression in ver<3.14 + if(VAR_GENERATOR_EXPRESSION AND ${CMAKE_VERSION} VERSION_LESS "3.14.0") + include(CreateTempFile) + if(CMAKE_CONFIGURATION_TYPES) # in case of multi-config generators like MSVC generators + CreateTempFilePath(OUTPUT_VAR file_path TAG "${VAR_NAME}" CONTENT "${VAR_CONTENT}" CONFIG_SUFFIX) + install(CODE "file(READ \"${file_path}_\${CMAKE_INSTALL_CONFIG_NAME}\" \"${VAR_NAME}\")") + else() + CreateTempFilePath(OUTPUT_VAR file_path TAG "${VAR_NAME}" CONTENT "${VAR_CONTENT}") + install(CODE "file(READ \"${file_path}\" \"${VAR_NAME}\")") + endif() + else() + if(VAR_GENERATOR_EXPRESSION) + cmake_policy(SET CMP0087 NEW) + endif() + install(CODE "set(\"${VAR_NAME}\" \"${VAR_CONTENT}\")") + endif() +endfunction() diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake index f3458165b3d..86807b7573c 100644 --- a/cmake/modules/DetectMachine.cmake +++ b/cmake/modules/DetectMachine.cmake @@ -4,6 +4,8 @@ ELSEIF(APPLE) SET(LMMS_BUILD_APPLE 1) ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") SET(LMMS_BUILD_OPENBSD 1) +ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + SET(LMMS_BUILD_FREEBSD 1) ELSEIF(HAIKU) SET(LMMS_BUILD_HAIKU 1) ELSE() @@ -30,6 +32,25 @@ IF(WIN32) ELSE(WIN64) SET(IS_X86 TRUE) ENDIF(WIN64) + + if(MSVC) + SET(MSVC_VER ${CMAKE_CXX_COMPILER_VERSION}) + + IF(MSVC_VER VERSION_GREATER 19.20 OR MSVC_VER VERSION_EQUAL 19.20) + SET(LMMS_MSVC_GENERATOR "Visual Studio 16 2019") + SET(LMMS_MSVC_YEAR 2019) # Qt only provides binaries for MSVC 2017, but 2019 is binary compatible + ELSEIF(MSVC_VER VERSION_GREATER 19.10 OR MSVC_VER VERSION_EQUAL 19.10) + SET(LMMS_MSVC_GENERATOR "Visual Studio 15 2017") + SET(LMMS_MSVC_YEAR 2017) + ELSEIF(MSVC_VER VERSION_GREATER 19.0 OR MSVC_VER VERSION_EQUAL 19.0) + SET(LMMS_MSVC_GENERATOR "Visual Studio 14 2015") + SET(LMMS_MSVC_YEAR 2015) + ELSE() + MESSAGE(SEND_WARNING "Can't detect MSVC version: ${MSVC_VER}") + ENDIF() + + unset(MSVC_VER) + endif() ELSE(WIN32) EXEC_PROGRAM( ${CMAKE_C_COMPILER} ARGS "-dumpmachine ${CMAKE_C_FLAGS}" OUTPUT_VARIABLE Machine ) MESSAGE("Machine: ${Machine}") diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake index 89aea7a8a03..7b9e5b14977 100644 --- a/cmake/modules/FindSDL2.cmake +++ b/cmake/modules/FindSDL2.cmake @@ -82,7 +82,7 @@ SET(SDL2_SEARCH_PATHS FIND_PATH(SDL2_INCLUDE_DIR SDL.h HINTS $ENV{SDL2DIR} - PATH_SUFFIXES include/SDL2 include + PATH_SUFFIXES SDL2 include/SDL2 include PATHS ${SDL2_SEARCH_PATHS} ) diff --git a/cmake/modules/FindWine.cmake b/cmake/modules/FindWine.cmake index 50bf54edbc6..f7f3b0aa647 100644 --- a/cmake/modules/FindWine.cmake +++ b/cmake/modules/FindWine.cmake @@ -11,11 +11,19 @@ MACRO(_findwine_find_flags output expression result) STRING(REPLACE " " ";" WINEBUILD_FLAGS "${output}") FOREACH(FLAG ${WINEBUILD_FLAGS}) IF("${FLAG}" MATCHES "${expression}") - SET(${result} "${FLAG}") + LIST(APPEND ${result} "${FLAG}") ENDIF() ENDFOREACH() ENDMACRO() +MACRO(_regex_replace_foreach EXPRESSION REPLACEMENT RESULT INPUT) + SET(${RESULT} "") + FOREACH(ITEM ${INPUT}) + STRING(REGEX REPLACE "${EXPRESSION}" "${REPLACEMENT}" ITEM "${ITEM}") + LIST(APPEND ${RESULT} "${ITEM}") + ENDFOREACH() +ENDMACRO() + LIST(APPEND CMAKE_PREFIX_PATH /opt/wine-stable /opt/wine-devel /opt/wine-staging /usr/lib/wine/) FIND_PROGRAM(WINE_CXX @@ -31,10 +39,10 @@ IF(WINE_CXX) _findwine_find_flags("${WINEBUILD_OUTPUT_32}" "^-isystem" WINEGCC_INCLUDE_DIR) _findwine_find_flags("${WINEBUILD_OUTPUT_32}" "libwinecrt0\\.a.*" WINECRT_32) _findwine_find_flags("${WINEBUILD_OUTPUT_64}" "libwinecrt0\\.a.*" WINECRT_64) - STRING(REGEX REPLACE "^-isystem" "" WINE_INCLUDE_HINT "${WINEGCC_INCLUDE_DIR}") - STRING(REGEX REPLACE "/wine/windows$" "" WINE_INCLUDE_HINT "${WINE_INCLUDE_HINT}") - STRING(REGEX REPLACE "libwinecrt0\\.a.*" "" WINE_32_LIBRARY_DIR "${WINECRT_32}") - STRING(REGEX REPLACE "libwinecrt0\\.a.*" "" WINE_64_LIBRARY_DIR "${WINECRT_64}") + _regex_replace_foreach("^-isystem" "" WINE_INCLUDE_HINT "${WINEGCC_INCLUDE_DIR}") + _regex_replace_foreach("/wine/windows$" "" WINE_INCLUDE_HINT "${WINE_INCLUDE_HINT}") + STRING(REGEX REPLACE "wine/libwinecrt0\\.a.*" "" WINE_32_LIBRARY_DIR "${WINECRT_32}") + STRING(REGEX REPLACE "wine/libwinecrt0\\.a.*" "" WINE_64_LIBRARY_DIR "${WINECRT_64}") IF(BUGGED_WINEGCC) MESSAGE(WARNING "Your winegcc is unusable due to https://bugs.winehq.org/show_bug.cgi?id=46293,\n @@ -76,7 +84,7 @@ IF(WINE_CXX) ENDIF() FIND_PATH(WINE_INCLUDE_DIR wine/exception.h - HINTS "${WINE_INCLUDE_HINT}" + HINTS ${WINE_INCLUDE_HINT} ) SET(_ARCHITECTURE ${CMAKE_LIBRARY_ARCHITECTURE}) diff --git a/cmake/modules/InstallDependencies.cmake b/cmake/modules/InstallDependencies.cmake new file mode 100644 index 00000000000..791041bb24a --- /dev/null +++ b/cmake/modules/InstallDependencies.cmake @@ -0,0 +1,184 @@ +include(GetPrerequisites) +include(CMakeParseArguments) + +CMAKE_POLICY(SET CMP0011 NEW) +CMAKE_POLICY(SET CMP0057 NEW) + +function(make_absolute var) + get_filename_component(abs "${${var}}" ABSOLUTE BASE_DIR "${CMAKE_INSTALL_PREFIX}") + set(${var} ${abs} PARENT_SCOPE) +endfunction() + +# Reads lines of a file into a list, skipping '#' comment lines +function(READ_LIST_FILE FILE VAR) + file(STRINGS "${FILE}" list) + + set(result "") + foreach(item ${list}) + string(STRIP "${item}" item) + if(item STREQUAL "" OR item MATCHES "^\#") + continue() + endif() + list(APPEND result "${item}") + endforeach() + + set(${VAR} ${result} PARENT_SCOPE) +endfunction() + +function(make_all_absolute list_var) + set(result "") + foreach(file ${${list_var}}) + make_absolute(file) + list(APPEND result ${file}) + endforeach() + set(${list_var} ${result} PARENT_SCOPE) +endfunction() + +if(CMAKE_BINARY_DIR) + set(tmp_lib_dir "${CMAKE_BINARY_DIR}/bundled-libraries") +elseif(CMAKE_HOST_UNIX) + set(tmp_lib_dir "/tmp/bundled-libraries") +elseif(DEFINED ENV{TEMP}) + set(tmp_lib_dir "$ENV{TMP}/bundled-libraries") +else() + message(FATAL_ERROR "Can't find a temp dir for libraries") +endif() + +# Like file(INSTALL), but resolves symlinks +function(install_file_resolved file destination) + + get_filename_component(file_name "${file}" NAME) + if(IS_SYMLINK "${file}") + get_filename_component(real_path "${file}" REALPATH) + get_filename_component(real_name "${real_path}" NAME) + file(COPY "${real_path}" DESTINATION "${tmp_lib_dir}") + file(RENAME "${tmp_lib_dir}/${real_name}" "${tmp_lib_dir}/${file_name}") + set(file_path "${tmp_lib_dir}/${file_name}") + else() + set(file_path "${file}") + endif() + + file(INSTALL "${file_path}" DESTINATION "${destination}") +endfunction() + +function(install_resolved) + cmake_parse_arguments("" "" "DESTINATION" "FILES" ${ARGN}) + foreach(file ${_FILES}) + install_file_resolved("${file}" "${_DESTINATION}") + endforeach() +endfunction() + +if(CMAKE_CROSSCOMPILING) + # If we're cross-compiling, GetPrerequisites may not be able to find system libraries such as kernel32.dll because + # they're supplied by the toolchain. To suppress thousands of lines of warnings being printed to the console, we + # override gp_resolved_file_type to return "system" for any library in ${IGNORE_LIBS} without trying to resolve the + # file first. + # GetPrerequisites supports using an override function called gp_resolved_file_type_override, but it's not suited + # for our purpose because it's only called by gp_resolved_file_type *after* trying to resolve the file. + function(gp_resolved_file_type original_file file exepath dirs type_var) + set(file_find "${file}") + if(_IGNORE_CASE) + # On case-insensitive systems, convert to upper characters to respect it + string(TOUPPER "${file_find}" file_find) + endif() + SET(IGNORE_LIBS ${_IGNORE_LIBS} CACHE INTERNAL "Ignored library names" FORCE) + if(IGNORE_LIBS AND ${file_find} IN_LIST IGNORE_LIBS) + set(${type_var} system PARENT_SCOPE) + else() + #_gp_resolved_file_type(${ARGV}) + _gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "${dirs}" "${type_var}" ${ARGN}) + endif() + endfunction() +endif() + +function(INSTALL_DEPENDENCIES) + cmake_parse_arguments("" "INCLUDE_SYSTEM;IGNORE_CASE" "GP_TOOL;DESTINATION;IGNORE_LIBS_FILE" "FILES;LIB_DIRS;SEARCH_PATHS;IGNORE_LIBS" ${ARGN}) + + # Make paths absolute + make_absolute(_DESTINATION) + make_all_absolute(_FILES) + make_all_absolute(_LIB_DIRS) + make_all_absolute(_SEARCH_PATHS) + + if(_INCLUDE_SYSTEM) + set(EXCLUDE_SYSTEM 0) + else() + set(EXCLUDE_SYSTEM 1) + endif() + + if(_IGNORE_LIBS_FILE) + READ_LIST_FILE("${_IGNORE_LIBS_FILE}" _IGNORE_LIBS) + if(_IGNORE_CASE) + # On case-insensitive systems, convert to upper characters to respect it + string(TOUPPER "${_IGNORE_LIBS}" _IGNORE_LIBS) + endif() + SET(IGNORE_LIBS ${_IGNORE_LIBS} CACHE INTERNAL "Ignored library names" FORCE) + endif() + + if(_GP_TOOL) + set(gp_tool "${_GP_TOOL}") + endif() + + set(prereqs "") + foreach(file ${_FILES}) + get_filename_component(file_name "${file}" NAME) + message("-- Finding prerequisites of ${file_name}") + find_prerequisites("${file}" _prereqs + ${EXCLUDE_SYSTEM} # exclude system files + 1 # recurse + "" + "${_LIB_DIRS}" + "${_SEARCH_PATHS}" + "${_IGNORE_LIBS}" + ) + + list(APPEND prereqs ${_prereqs}) + endforeach() + + list(REMOVE_DUPLICATES prereqs) + + foreach(prereq ${prereqs}) + get_filename_component(prereq_name "${prereq}" NAME) + + foreach(rpath ${_SEARCH_PATHS}) + if(EXISTS "${rpath}/${prereq_name}") + list(REMOVE_ITEM prereqs "${prereq}") + break() + endif() + endforeach() + endforeach() + + #file(INSTALL ${prereqs} DESTINATION ${_DESTINATION}) + install_resolved(FILES ${prereqs} DESTINATION "${_DESTINATION}") +endfunction() + +# Like get_prerequisites, but returns full paths +function(FIND_PREREQUISITES target RESULT_VAR exclude_system recurse + exepath dirs rpaths) + set(RESULTS) + + get_prerequisites("${target}" _prereqs ${exclude_system} ${recurse} + "" "${dirs}" "${rpaths}") + + foreach(prereq ${_prereqs}) + get_filename_component(prereq_name "${prereq}" NAME) + if(_IGNORE_CASE) + # Windows is case insensitive. + # Use upper characters to respect it. + string(TOUPPER "${prereq_name}" prereq_name) + endif() + if("${prereq_name}" IN_LIST IGNORE_LIBS) + continue() + endif() + + gp_resolve_item("${LIB_DLL}" "${prereq}" "" "${dirs}" RESOLVED_PREREQ "${rpaths}") + + if(RESOLVED_PREREQ AND IS_ABSOLUTE ${RESOLVED_PREREQ} AND EXISTS ${RESOLVED_PREREQ}) + list(APPEND RESULTS ${RESOLVED_PREREQ}) + else() + message(FATAL_ERROR "Can't resolve dependency ${prereq}.") + endif() + endforeach() + + set(${RESULT_VAR} ${RESULTS} PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/InstallTargetDependencies.cmake b/cmake/modules/InstallTargetDependencies.cmake new file mode 100644 index 00000000000..8e48c9ef7fb --- /dev/null +++ b/cmake/modules/InstallTargetDependencies.cmake @@ -0,0 +1,90 @@ +include(DefineInstallVar) + +SET(DEFAULT_SEARCH_DIRECTORIES "${BIN_DIR}" "${LIB_DIR}" "${CMAKE_FIND_ROOT_PATH}" "${CMAKE_PREFIX_PATH}") +SET(DEFAULT_SEARCH_SUFFIXES "bin" "lib" "../bin") + +# Like INSTALL_DEPENDENCIES but can be called from regular cmake code +# (instead of install(CODE)), takes targets instead of files, +# takes care of configuring search paths, and other platform-specific tweaks. +# Arguments: +# TARGETS: list of cmake targets to install. +# NAME: unique string for this install. +# DESTINATION: directory path to install the binaries to. +# LIB_DIRS: list of paths for looking up dependencies. +# LIB_DIRS_SUFFIXES: list of possible suffixes for LIB_DIRS entries. +# SEARCH_PATHS: list of library search paths on runtime +# NO_DEFAULT_PATHS: supply this value to avoid adding DEFAULT_SEARCH_DIRECTORIES +# to LIB_DIRS and DEFAULT_SEARCH_SUFFIXES to LIB_DIRS_SUFFIXES. +FUNCTION(INSTALL_TARGET_DEPENDENCIES) + set(options NO_DEFAULT_PATHS) + set(oneValueArgs NAME) + set(multiValueArgs TARGETS DESTINATION LIB_DIRS_SUFFIXES LIB_DIRS SEARCH_PATHS) + cmake_parse_arguments(DEPS "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + if(NOT DEPS_LIB_DIRS) + set(DEPS_LIB_DIRS "") + endif() + + # Set default values. + if(NOT DEPS_NO_DEFAULT_PATHS) + list(APPEND DEPS_LIB_DIRS ${DEFAULT_SEARCH_DIRECTORIES}) + set(DEPS_LIB_DIRS_SUFFIXES "${DEPS_LIB_DIRS_SUFFIXES}" ${DEFAULT_SEARCH_SUFFIXES}) + endif() + + FOREACH(TARGET ${DEPS_TARGETS}) + IF(NOT TARGET ${TARGET}) + message(FATAL_ERROR "Not a target: ${TARGET}") + ENDIF() + + # Collect target output files. + LIST(APPEND DEPLOY_TARGETS "$") + + # Collect target link directories + get_target_property(target_libs ${TARGET} LINK_LIBRARIES) + + foreach(lib ${target_libs}) + if(TARGET ${lib} OR NOT IS_ABSOLUTE ${lib}) + continue() + endif() + + get_filename_component(lib_dir ${lib} PATH) + list(APPEND DEPS_LIB_DIRS ${lib_dir}) + endforeach() + ENDFOREACH() + + LIST(APPEND DEPS_LIB_DIRS ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) + + FOREACH(LIB_PATH ${DEPS_LIB_DIRS}) + FOREACH(suffix ${DEPS_LIB_DIRS_SUFFIXES}) + list(APPEND DEPS_LIB_DIRS "${LIB_PATH}/${suffix}") + ENDFOREACH() + ENDFOREACH() + + DEFINE_INSTALL_VAR(NAME "DEPLOY_FILES" CONTENT "${DEPLOY_TARGETS}" GENERATOR_EXPRESSION) + + LIST(REMOVE_DUPLICATES DEPS_LIB_DIRS) + + IF(LMMS_BUILD_LINUX) + FILE(DOWNLOAD "https://raw.githubusercontent.com/AppImage/AppImages/master/excludelist" + "${CMAKE_BINARY_DIR}/excludelist") + SET(additional_args INCLUDE_SYSTEM IGNORE_LIBS_FILE ${CMAKE_BINARY_DIR}/excludelist) + ELSEIF(LMMS_BUILD_WIN32) + SET(additional_args IGNORE_CASE IGNORE_LIBS_FILE "${LMMS_SOURCE_DIR}/cmake/install/excludelist-win") + IF(CMAKE_CROSSCOMPILING) + SET(additional_args "${additional_args}" GP_TOOL objdump) + ENDIF() + ENDIF() + + INSTALL(CODE " + INCLUDE(\"${LMMS_SOURCE_DIR}/cmake/modules/InstallDependencies.cmake\") + + INSTALL_DEPENDENCIES( + FILES \"\${DEPLOY_FILES}\" + DESTINATION \"${DEPS_DESTINATION}\" + LIB_DIRS \"${DEPS_LIB_DIRS}\" + SEARCH_PATHS \"${DEPS_SEARCH_PATHS}\" + ${additional_args} + ) + ") +ENDFUNCTION() diff --git a/cmake/modules/PluginList.cmake b/cmake/modules/PluginList.cmake new file mode 100644 index 00000000000..5e22e2cece7 --- /dev/null +++ b/cmake/modules/PluginList.cmake @@ -0,0 +1,109 @@ +# Provides a fast mechanism for filtering the plugins used at build-time +SET(PLUGIN_LIST "" CACHE STRING "List of plug-ins to build") +STRING(REPLACE " " ";" PLUGIN_LIST "${PLUGIN_LIST}") +OPTION(LMMS_MINIMAL "Build a minimal list of plug-ins" OFF) +OPTION(LIST_PLUGINS "Lists the available plugins for building" OFF) + +SET(MINIMAL_LIST + audio_file_processor + kicker + triple_oscillator +) + +IF(LMMS_MINIMAL) + IF("${PLUGIN_LIST}" STREQUAL "") + STRING(REPLACE ";" " " MINIMAL_LIST_STRING "${MINIMAL_LIST}") + MESSAGE( +"-- Using minimal plug-ins: ${MINIMAL_LIST_STRING}\n" +" Note: You can specify specific plug-ins using -DPLUGIN_LIST=\"foo bar\"" + ) + ENDIF() + SET(PLUGIN_LIST ${MINIMAL_LIST} ${PLUGIN_LIST}) +ENDIF() + +SET(LMMS_PLUGIN_LIST + ${MINIMAL_LIST} + Amplifier + AudioMixMaster + BassBooster + bit_invader + Bitcrush + carlabase + carlapatchbay + carlarack + CrossoverEQ + Delay + DualFilter + dynamics_processor + Eq + Flanger + HydrogenImport + ladspa_browser + LadspaEffect + Lv2Effect + Lv2Instrument + lb302 + MidiImport + MidiExport + MixSetup + MultitapEcho + monstro + nes + OpulenZ + organic + FreeBoy + patman + peak_controller_effect + GigPlayer + ReverbSC + sf2_player + sfxr + sid + SpectrumAnalyzer + stereo_enhancer + stereo_matrix + stk + vst_base + vestige + VstEffect + watsyn + waveshaper + Vectorscope + vibed + Xpressive + zynaddsubfx +) + +IF("${PLUGIN_LIST}" STREQUAL "") + SET(PLUGIN_LIST ${LMMS_PLUGIN_LIST}) +ENDIF() + +MACRO(LIST_ALL_PLUGINS) + MESSAGE("\n\nAll possible -DPLUGIN_LIST values") + MESSAGE("\n KEYWORD:") + MESSAGE(" -DLMMS_MINIMAL=True") + FOREACH(item IN LISTS MINIMAL_LIST) + MESSAGE(" ${item}") + ENDFOREACH() + MESSAGE("\n NAME:") + FOREACH(item IN LISTS LMMS_PLUGIN_LIST) + MESSAGE(" ${item}") + ENDFOREACH() + MESSAGE("\nNote: This value also impacts the fetching of git submodules.\n") + MESSAGE(FATAL_ERROR "Information was requested, aborting build!") +ENDMACRO() + +IF(LIST_PLUGINS) + UNSET(LIST_PLUGINS CACHE) + LIST_ALL_PLUGINS() +ENDIF() + +IF(MSVC) + SET(MSVC_INCOMPATIBLE_PLUGINS + LadspaEffect + zynaddsubfx + ) + message(WARNING "Compiling with MSVC. The following plugins are not available: ${MSVC_INCOMPATIBLE_PLUGINS}") + LIST(REMOVE_ITEM PLUGIN_LIST ${MSVC_INCOMPATIBLE_PLUGINS}) +ENDIF() + diff --git a/cmake/modules/winegcc_wrapper.in b/cmake/modules/winegcc_wrapper.in index d32aec66432..7677e4c376b 100755 --- a/cmake/modules/winegcc_wrapper.in +++ b/cmake/modules/winegcc_wrapper.in @@ -58,6 +58,9 @@ if [ "$win64" = true ] && [ "$no_link" != true ]; then extra_args="$extra_args @WINE_64_FLAGS@" fi +# Work around https://bugs.winehq.org/show_bug.cgi?id=47710 +extra_args="$extra_args -D__WIDL_objidl_generated_name_0000000C=" + # Run winegcc export WINEBUILD=@WINE_BUILD@ @WINE_CXX@ $extra_args $args diff --git a/cmake/msys/extract_debs.sh b/cmake/msys/extract_debs.sh index cb2a868d3e9..939912bb2c3 100644 --- a/cmake/msys/extract_debs.sh +++ b/cmake/msys/extract_debs.sh @@ -1,4 +1,6 @@ #!/bin/bash +set -e + ppa_dir=./ppa/ pushd $ppa_dir diff --git a/cmake/msys/msys_helper.sh b/cmake/msys/msys_helper.sh index 294edd476da..a6a7e6aae38 100644 --- a/cmake/msys/msys_helper.sh +++ b/cmake/msys/msys_helper.sh @@ -68,7 +68,7 @@ stkver="4.5.1" mingw_root="/$(echo "$MSYSTEM"|tr '[:upper:]' '[:lower:]')" info "Downloading and building fltk $fltkver" -if ! which fluid; then +if ! command -v fluid; then wget http://fltk.org/pub/fltk/$fltkver/fltk-$fltkver-source.tar.gz -O "$HOME/fltk-source.tar.gz" tar zxf "$HOME/fltk-source.tar.gz" -C "$HOME/" pushd "$HOME/fltk-$fltkver" diff --git a/cmake/nsis/CMakeLists.txt b/cmake/nsis/CMakeLists.txt index ac628d549a4..3fcb4b2f3d7 100644 --- a/cmake/nsis/CMakeLists.txt +++ b/cmake/nsis/CMakeLists.txt @@ -1,3 +1,8 @@ +SET(WIN_PLATFORM mingw) +if(LMMS_MSVC_YEAR) + SET(WIN_PLATFORM "msvc${LMMS_MSVC_YEAR}") +endif() + SET(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/cmake/nsis/nsis_branding.bmp") IF(MSVC) STRING(REPLACE "/" "\\\\" CPACK_PACKAGE_ICON ${CPACK_PACKAGE_ICON}) @@ -15,7 +20,7 @@ SET(CPACK_NSIS_DEFINES " !include FileAssociation.nsh !include LogicLib.nsh !include WinVer.nsh") -SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-win32") +SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-${WIN_PLATFORM}-win32") SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS " \\\${registerExtension} \\\"$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe\\\" \\\".mmp\\\" \\\"${PROJECT_NAME_UCASE} Project\\\" \\\${registerExtension} \\\"$INSTDIR\\\\${CMAKE_PROJECT_NAME}.exe\\\" \\\".mmpz\\\" \\\"${PROJECT_NAME_UCASE} Project (compressed)\\\" @@ -31,7 +36,7 @@ SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS " " PARENT_SCOPE) IF(WIN64) - SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-win64") + SET(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-${WIN_PLATFORM}-win64") SET(CPACK_INSTALL_FIX "$PROGRAMFILES64\\\\${CPACK_PACKAGE_INSTALL_DIRECTORY}\\\\") SET(CPACK_NSIS_DEFINES " ${CPACK_NSIS_DEFINES} diff --git a/cmake/postinstall/CMakeLists.txt b/cmake/postinstall/CMakeLists.txt deleted file mode 100644 index 434d1c54e79..00000000000 --- a/cmake/postinstall/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -IF(LMMS_BUILD_APPLE) - INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x ${CMAKE_BINARY_DIR}/install_apple.sh)") - INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_BINARY_DIR}/install_apple.sh)") -ENDIF() \ No newline at end of file diff --git a/data/locale/CMakeLists.txt b/data/locale/CMakeLists.txt index 9cb25f4265c..4ce666dcfef 100644 --- a/data/locale/CMakeLists.txt +++ b/data/locale/CMakeLists.txt @@ -47,9 +47,9 @@ FOREACH(_item ${qm_targets}) ADD_DEPENDENCIES(finalize-locales "${_item}") ENDFOREACH(_item ${qm_targets}) -IF(LMMS_BUILD_WIN32) - FILE(GLOB QT_QM_FILES "${QT_TRANSLATIONS_DIR}/qt*[^h].qm") +IF(BUNDLE_QT_TRANSLATIONS) + FILE(GLOB QT_QM_FILES "${QT_TRANSLATIONS_DIR}/qt*.qm") LIST(SORT QT_QM_FILES) -ENDIF(LMMS_BUILD_WIN32) +ENDIF() INSTALL(FILES ${QM_FILES} ${QT_QM_FILES} DESTINATION "${LMMS_DATA_DIR}/locale") diff --git a/data/locale/cs.ts b/data/locale/cs.ts index ffb3b8a0964..6e2435a4d65 100644 --- a/data/locale/cs.ts +++ b/data/locale/cs.ts @@ -1,37 +1,113 @@ - - - + + + AboutDialog + + + About LMMS + O LMMS + + + + LMMS + LMMS + + + + Version %1 (%2/%3, Qt %4, %5) + Verze %1 (%2/%3, Qt %4, %5) + + + + About + O LMMS + + + + LMMS - easy music production for everyone + LMMS – snadné vytváření hudby pro každého + + + + Copyright © %1 + Copyright © %1 + + + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + + + + Authors + Autoři + + + + Involved + Spolupracovníci + + + + Contributors ordered by number of commits: + Přispěvatelé řazení podle počtu příspěvků: + + + + Translation + Překlad + + + + Current language not translated (or native English). + +If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! + Chcete-li vylepšit stávající překlad, Vaše pomoc bude vítána! Stačí jen kontaktovat vývojáře! + + + + License + Licence + + AmplifierControlDialog + VOL HLA + Volume: Hlasitost: + PAN PAN + Panning: Panoráma: + LEFT LEVÝ + Left gain: Zesílení vlevo: + RIGHT PRAVÝ + Right gain: Zesílení vpravo: @@ -39,4270 +115,11631 @@ AmplifierControls + Volume Hlasitost + Panning Panoráma + Left gain Zesílení vlevo + Right gain Zesílení vpravo + + AudioAlsaSetupWidget + + + DEVICE + ZAŘÍZENÍ + + + + CHANNELS + KANÁLY + + AudioFileProcessorView - Reverse sample - Přehrávat pozpátku + + Open other sample + Otevřít jiný sampl - Amplify: - Zesílení: + + Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. + Klepnutím sem můžete otevřít jiný audio soubor. Zobrazí se dialog, pomocí kterého si soubor můžete vybrat. Nastavení smyčky, počátečního a koncového bodu, zesílení apod. zůstanou nezměněná, takže to nemusí znít jako původní sampl. - Continue sample playback across notes - Pokračovat v přehrávání samplu při změně noty + + Reverse sample + Přehrávat pozpátku + + + + If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. + Zapnete-li toto tlačítko, celý sampl bude přehráván pozpátku. Tato volba je užitečná pro zajímavé efekty jako např. pozpátku přehraná srážka. + Disable loop Vypnout smyčku + + This button disables looping. The sample plays only once from start to end. + Toto tlačítko vypne smyčku. Sampl bude přehrán jen jednou od začátku do konce. + + + + Enable loop Zapnout smyčku - Loopback point: - Začátek smyčky: + + This button enables forwards-looping. The sample loops between the end point and the loop point. + Toto tlačítko zapne smyčku směrem dopředu. Vzorek se bude vracet z koncového bodu na začátek. - Open sample - + + This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. + Toto tlačítko zapne smyčku typu ping-pong. Vzorek bude přehráván dopředu a zpět mezi koncovým bodem a začátkem smyčky. - Enable ping-pong loop - + + Continue sample playback across notes + Pokračovat v přehrávání samplu přes znějící tóny - Start point: - + + Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) + Povolení této možnosti způsobí, že se sampl bude přehrávat přes různé tóny – když změníte výšku tónu nebo když tón skončí před koncem samplu, bude další přehrávaný tón pokračovat tam, kde přestal. Pro obnovení přehrávání od začátku samplu vložte tón do spodní části klávesnice (< 20 Hz) - End point: - + + Amplify: + Zesílení: - - - AudioFileProcessorWaveView - Sample length: - Délka samplu: + + With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + Tímto otočným ovladačem můžete nastavit poměr zesílení. Pokud nastavíte hodnotu 100%, sampl se nezmění. Jinak se zesílí nebo ztiší (váš stávající soubor samplu tím nebude nijak ovlivněn!) - - - BassBoosterControlDialog - FREQ - FREKV + + Startpoint: + Začátek samplu: - Frequency: - Frekvence: + + With this knob you can set the point where AudioFileProcessor should begin playing your sample. + Tímto otočným ovladačem můžete nastavit bod, od kterého bude AudioFileProcessor přehrávat váš sampl. - GAIN - ZES + + Endpoint: + Konec samplu: - Gain: - Zesílení: + + With this knob you can set the point where AudioFileProcessor should stop playing your sample. + Tímto otočným ovladačem můžete nastavit bod, ve kterém AudioFileProcessor zastaví přehrávání vašeho samplu. - RATIO - POMĚR + + Loopback point: + Začátek smyčky: - Ratio: - Poměr: + + With this knob you can set the point where the loop starts. + Tímto otočným ovladačem můžete nastavit bod, kterým začíná smyčka. - BassBoosterControls - - Frequency - Frekvence - - - Gain - Zesílení - + AudioFileProcessorWaveView - Ratio - Poměr + + Sample length: + Délka samplu: - BitcrushControlDialog + AudioJack - IN - IN + + JACK client restarted + Klient JACK je restartován - OUT - OUT + + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. + LMMS bylo z nějakého důvodu shozeno JACKem. Proto byl ovladač JACK v LMMS restartován. Musíte znovu provést ruční připojení. - GAIN - ZISK + + JACK server down + JACK server byl zastaven - CLIP - OŘÍZ + + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. + Vypnutí a nové spuštění serveru JACK se nezdařilo. LMMS proto nemůže pokračovat. Uložte svůj projekt a restartujte JACK i LMMS. - Sample rate: - Vzorkovací frekvence: + + CLIENT-NAME + JMÉNO-KLIENTA - Stereo difference: - Stereo rozdíl: + + CHANNELS + KANÁLY + + + AudioOss::setupWidget - Levels: - Úrovně: + + DEVICE + ZAŘÍZENÍ - NOISE - ŠUM + + CHANNELS + KANÁLY + + + AudioPortAudio::setupWidget - FREQ - FREKV + + BACKEND + OVLADAČ - STEREO - STEREO + + DEVICE + ZAŘÍZENÍ + + + AudioPulseAudio::setupWidget - QUANT - KVANT + + DEVICE + ZAŘÍZENÍ - Input gain: - Zesílení vstupu: + + CHANNELS + KANÁLY + + + AudioSdl::setupWidget - Input noise: - + + DEVICE + ZAŘÍZENÍ + + + AudioSndio::setupWidget - Output gain: - Zesílení výstupu: + + DEVICE + ZAŘÍZENÍ - Output clip: - + + CHANNELS + KANÁLY + + + AudioSoundIo::setupWidget - Rate enabled - + + BACKEND + OVLADAČ - Enable sample-rate crushing - + + DEVICE + ZAŘÍZENÍ + + + AutomatableModel - Depth enabled - + + &Reset (%1%2) + &Resetovat hodnoty (%1%2) - Enable bit-depth crushing - + + &Copy value (%1%2) + &Kopírovat hodnoty (%1%2) - - - BitcrushControls - Input gain - Zesílení vstupu + + &Paste value (%1%2) + &Vložit hodnoty (%1%2) - Input noise - + + Edit song-global automation + Upravit hlavní automatizaci skladby - Output gain - Zesílení výstupu + + Remove song-global automation + Odebrat hlavní automatizaci skladby - Output clip - + + Remove all linked controls + Odebrat všechny propojené ovládací prvky - Sample rate - + + Connected to %1 + Připojeno k %1 - Stereo difference - + + Connected to controller + Připojeno k ovladači - Levels - + + Edit connection... + Upravit připojení... - Rate enabled - + + Remove connection + Odebrat připojení - Depth enabled - + + Connect to controller... + Připojit k ovladači... - CarlaInstrumentView + AutomationEditor - Show GUI - Ukázar grafické rozhraní + + Please open an automation pattern with the context menu of a control! + Otevřete prosím automatizační záznam pomocí kontextové nabídky ovládání! + + + + Values copied + Hodnoty zkopírovány + + + + All selected values were copied to the clipboard. + Všechny označené hodnoty byly zkopírovány do schránky. - CrossoverEQControlDialog + AutomationEditorWindow - Band 1/2 crossover: - + + Play/pause current pattern (Space) + Přehrát/Pozastavit přehrávání aktuálního záznamu (mezerník) - Band 2/3 crossover: - + + Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. + Klepněte sem, pokud chcete přehrát aktuální záznam. To je užitečné při editaci. Záznam je automaticky přehráván ve smyčce. - Band 3/4 crossover: - + + Stop playing of current pattern (Space) + Zastavit přehrávání aktuálního záznamu (mezerník) - Band 1 gain - + + Click here if you want to stop playing of the current pattern. + Klepněte sem, pokud chcete zastavit přehrávání aktuálního záznamu. - Band 1 gain: - + + Edit actions + Akce úprav - Band 2 gain - + + Draw mode (Shift+D) + Režim kreslení (Shift+D) - Band 2 gain: - + + Erase mode (Shift+E) + Režim mazání (Shift+E) - Band 3 gain - + + Flip vertically + Převrátit vertikálně - Band 3 gain: - + + Flip horizontally + Převrátit horizontálně - Band 4 gain - + + Click here and the pattern will be inverted.The points are flipped in the y direction. + Klepněte sem, pokud chcete převrátit záznam. Body budou převráceny v ose y. - Band 4 gain: - + + Click here and the pattern will be reversed. The points are flipped in the x direction. + Klepněte sem, pokud chcete převrátit záznam. Body budou převráceny v ose x. - Band 1 mute - + + Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. + Klepněte sem, pokud chcete aktivovat režim kreslení. V tomto výchozím a nejčastěji užívaném režimu lze přidávat a přesunovat jednotlivé hodnoty. Pro aktivaci můžete využít též klávesové zkratky "Shift+D". - Mute band 1 - + + Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. + Klepněte sem, pokud chcete aktivovat režim mazání. V tomto režimu lze mazat jednotlivé hodnoty. Pro aktivaci můžete využít též klávesové zkratky "Shift+E". - Band 2 mute - + + Interpolation controls + Ovládání interpolace - Mute band 2 - + + Discrete progression + Terasovitý průběh - Band 3 mute - + + Linear progression + Lineární průběh - Mute band 3 - + + Cubic Hermite progression + Křivkovitý průběh - Band 4 mute - + + Tension value for spline + Hodnota napětí pro křivku - Mute band 4 - + + A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. + Vyšší hodnota napětí vytvoří hladší křivku, ale více se vzdálí od zadaných hodnot. Nižší hodnota napětí upřednostní výchozí sklon křivky v každém kontrolním bodě. - - - DelayControls - Feedback - Zpětná vazba + + Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. + Klepnutím sem vyberete terasovitý vývoj pro tento automatizační záznam. Hodnota připojeného objektu zůstane neměnná mezi ovládacími body a okamžitě bude nastavena na novou hodnotu, když se dosáhne dalšího ovládacího bodu. - Output gain - Zesílení výstupu + + Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. + Klepnutím sem vyberete lineární vývoj pro tento automatizační záznam. Hodnota připojeného objektu bude mezi ovládacími body měněna přímočaře, aby postupně došlo k dosažení dalšího kontrolního bodu. - Delay samples - + + Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. + Klepnutím sem vyberte vývoj typu cubic hermite pro tento automatizační záznam. Hodnota připojeného objektu se změní po plynulé křivce a hladce přejde do vrchních i spodních bodů. - LFO frequency - + + Tension: + Napětí: - LFO amount - + + Cut selected values (%1+X) + Vyjmout označené hodnoty (%1+X) - - - DelayControlsDialog - Gain - Zesílení + + Copy selected values (%1+C) + Kopírovat označené hodnoty (%1+C) - DELAY - ZPOŽ + + Paste values from clipboard (%1+V) + Vložit hodnoty ze schránky (%1+V) - FDBK - FDBK + + Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klepněte sem, pokud chcete označené hodnoty vyjmout a uložit do schránky. Vložit je pak můžete kdekoliv v libovolném záznamu pomocí tlačítka Vložit. - RATE - RYCH + + Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klepněte sem, pokud chcete označené hodnoty zkopírovat do schránky. Vložit je pak můžete kdekoliv v libovolném záznamu pomocí tlačítka Vložit. - AMNT - MNOŽ + + Click here and the values from the clipboard will be pasted at the first visible measure. + Klepnete-li sem, budou hodnoty ze schránky vloženy do prvního viditelného taktu. + + + + Zoom controls + Ovládání zvětšení + + + + Quantization controls + Ovládání kvantizace - Delay time - + + Quantization + Kvantizace - Feedback amount - + + Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. + Kvantizace. Nastaví nejmenší velikost kroku pro body automatizace. Ve výchozím stavu také nastaví délku a vymazává další body v rozsahu. Stisknutím <Ctrl> zrušíte toto chování. - LFO frequency - + + + Automation Editor - no pattern + Editor automatizace – žádný záznam - LFO amount - + + + Automation Editor - %1 + Editor automatizace – %1 - Out gain - + + Model is already connected to this pattern. + Model je již k tomuto záznamu připojen. - DualFilterControlDialog + AutomationPattern - Filter 1 enabled - Filtr 1 zapnutý + + Drag a control while pressing <%1> + Ovládací prvek táhni při stisknutém <%1> + + + AutomationPatternView - Filter 2 enabled - Filtr 2 zapnutý + + double-click to open this pattern in automation editor + dvojklikem otevřít tento pattern v Editoru automatizace - FREQ - FREKV + + Open in Automation editor + Otevřít v Editoru automatizace - Cutoff frequency - Frekvence oříznutí + + Clear + Vyčistit - RESO - REZON + + Reset name + Obnovit výchozí jméno - Resonance - Rezonance + + Change name + Změnit jméno - GAIN - ZESIL + + Set/clear record + Zapnout/Vypnout záznam - Gain - Zesílení + + Flip Vertically (Visible) + Převrátit vertikálně (viditelné) - MIX - POMĚR + + Flip Horizontally (Visible) + Převrátit horizontálně (viditelné) - Mix - Poměr + + %1 Connections + %1 Připojení - Enable/disable filter 1 - + + Disconnect "%1" + Odpojit "%1" - Enable/disable filter 2 - + + Model is already connected to this pattern. + Model je již k tomuto záznamu připojen. - DualFilterControls + AutomationTrack - Filter 1 enabled - Filtr 1 zapnutý + + Automation track + Stopa automatizace + + + BBEditor - Filter 1 type - Typ filtru 1 + + Beat+Bassline Editor + Editor bicích/basů - Q/Resonance 1 - Q/rezonance 1 + + Play/pause current beat/bassline (Space) + Přehrát/Pozastavit přehrávání aktuálního záznamu bicích/basů (mezerník) - Gain 1 - Zesílení 1 + + Stop playback of current beat/bassline (Space) + Zastavit přehrávání aktuálního záznamu bicích/basů (mezerník) - Mix - Mix + + Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. + Klepněte sem, pokud chcete přehrát aktuální záznam bicích/basů. Bicí/basy jsou automaticky přehrávány ve smyčce. - Filter 2 enabled - Filtr 1 zapnutý + + Click here to stop playing of current beat/bassline. + Klepněte sem, pokud chcete zastavit přehrávání aktuálního záznamu bicích/basů. - Filter 2 type - Typ filtru 2 + + Beat selector + Výběr rytmu - Q/Resonance 2 - Q/rezonance 2 + + Track and step actions + Akce stopy a kroků - Gain 2 - Zesílení 2 + + Add beat/bassline + Přidat bicí/basy - Notch - Pásmová zádrž + + Add sample-track + Přidat stopu samplů - Moog - Moogův filtr + + Add automation-track + Přidat stopu automatizace - 2x Moog - 2x Moogův filtr + + Remove steps + Odstranit kroky - SV Notch - SV pásmová zádrž + + Add steps + Přidat kroky - Fast Formant - Rychlý formantový filtr + + Clone Steps + Klonovat kroky + + + BBTCOView - Tripole - Třípólový filtr + + Open in Beat+Bassline-Editor + Otevřít v editoru bicích/basů - Cutoff frequency 1 - + + Reset name + Resetovat jméno - Cutoff frequency 2 - + + Change name + Změnit jméno - Low-pass - + + Change color + Změnit barvu - Hi-pass - + + Reset color to default + Obnovit výchozí barvy + + + BBTrack - Band-pass csg - + + Beat/Bassline %1 + Bicí/basy %1 - Band-pass czpg - + + Clone of %1 + Klon z %1 + + + BassBoosterControlDialog - All-pass - + + FREQ + FREKV - 2x Low-pass - + + Frequency: + Frekvence: - RC Low-pass 12 dB/oct - + + GAIN + ZES - RC Band-pass 12 dB/oct - + + Gain: + Zesílení: - RC High-pass 12 dB/oct - + + RATIO + POMĚR - RC Low-pass 24 dB/oct - + + Ratio: + Poměr: + + + BassBoosterControls - RC Band-pass 24 dB/oct - + + Frequency + Frekvence - RC High-pass 24 dB/oct - + + Gain + Zesílení - Vocal Formant - + + Ratio + Poměr + + + BitcrushControlDialog - SV Low-pass - + + IN + IN - SV Band-pass - + + OUT + OUT - SV High-pass - + + + GAIN + ZISK - - - EqControls - Input gain - Zesílení vstupu - - - Output gain - Zesílení výstupu + + Input Gain: + Zesílení vstupu: - Peak 1 gain - Zesílení špičky 1 + + NOISE + ŠUM - Peak 2 gain - Zesílení špičky 2 + + Input Noise: + Vstup šumu: - Peak 3 gain - Zesílení špičky 3 + + Output Gain: + Zesílení výstupu: - Peak 4 gain - Zesílení špičky 4 + + CLIP + OŘÍZ - HP res - Rezonance horní propusti + + Output Clip: + Oříznutí výstupu: - Peak 1 BW - Šířka pásma špičky 1 + + Rate Enabled + Frekvence zapnuta - Peak 2 BW - Šířka pásma špičky 2 + + Enable samplerate-crushing + Zapnout drtič vzorkovací frekvence - Peak 3 BW - Šířka pásma špičky 3 + + Depth Enabled + Hloubka zapnuta - Peak 4 BW - Šířka pásma špičky 4 + + Enable bitdepth-crushing + Zapnout drtič bitové hloubky - LP res - Rezonance dolní propusti + + FREQ + FREKV - HP freq - Frekvence horní propusti + + Sample rate: + Vzorkovací frekvence: - Peak 1 freq - Frekvence špičky 1 + + STEREO + STEREO - Peak 2 freq - Frekvence špičky 2 + + Stereo difference: + Stereo rozdíl: - Peak 3 freq - Frekvence špičky 3 + + QUANT + KVANT - Peak 4 freq - Frekvence špičky 3 + + Levels: + Úrovně: + + + CaptionMenu - LP freq - Frekvence dolní propusti + + &Help + &Nápověda - HP active - Horní propust aktivní + + Help (not available) + Nápověda (nedostupná) + + + CarlaInstrumentView - Peak 1 active - Špička 1 aktivní + + Show GUI + Ukázar grafické rozhraní - Peak 2 active - Špička 2 aktivní + + Click here to show or hide the graphical user interface (GUI) of Carla. + Klepněte sem pro zobrazení nebo skrytí grafického uživatelského rozhraní (GUI) Carla. + + + Controller - Peak 3 active - Špička 3 aktivní + + Controller %1 + Ovladač %1 + + + ControllerConnectionDialog - Peak 4 active - Špička 4 aktivní + + Connection Settings + Nastavení připojení - LP active - Dolní propust aktivní + + MIDI CONTROLLER + MIDI OVLADAČ - LP 12 - DP 12 + + Input channel + Vstupní kanál - LP 24 - DP 24 + + CHANNEL + KANÁL - LP 48 - DP 48 + + Input controller + Vstupní ovladač - HP 12 - HP 12 + + CONTROLLER + OVLADAČ - HP 24 - HP 24 + + + Auto Detect + Autodetekce - HP 48 - HP 48 + + MIDI-devices to receive MIDI-events from + MIDI zařízení k přijmu MIDI události - Analyse IN - Analýza VSTUPU + + USER CONTROLLER + UŽIVATELSKÝ OVLADAČ - Analyse OUT - Analýza VÝSTUPU + + MAPPING FUNCTION + MAPOVACÍ FUNKCE - Low-shelf gain - + + OK + OK - High-shelf gain - + + Cancel + Zrušit - Low-shelf res - + + LMMS + LMMS - High-shelf res - + + Cycle Detected. + Zjištěno zacyklení. + + + ControllerRackView - Low-shelf freq - + + Controller Rack + Ovladače - High-shelf freq - + + Add + Přidat - Low-shelf active - + + Confirm Delete + Potvrdit smazání - High-shelf active - + + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. + Opravdu smazat? Je (jsou) zde propojení na tento ovladač. Nebude možné vrátit se zpět. + + + ControllerView - Low-pass type - + + Controls + Ovládací prvky - High-pass type - + + Controllers are able to automate the value of a knob, slider, and other controls. + Kontroléry jsou schopny automatizovat nastavení otočných ovladačů, táhel a dalších řídicích prvků. - - - EqControlsDialog - HP - HP + + Rename controller + Přejmenovat ovladač - Peak 1 - Špička 1 + + Enter the new name for this controller + Vložte nové jméno pro tento ovladač - Peak 2 - Špička 2 + + LFO + LFO - Peak 3 - Špička 3 + + &Remove this controller + Odst&ranit tento ovladač - Peak 4 - Špička 4 + + Re&name this controller + Přejme&novat tento ovladač + + + CrossoverEQControlDialog - LP - DP + + Band 1/2 Crossover: + Přechod mezi pásmy 1/2: - Gain - Zesílení + + Band 2/3 Crossover: + Přechod mezi pásmy 2/3: - Bandwidth: - Šířka pásma: + + Band 3/4 Crossover: + Přechod mezi pásmy 3/4: - Resonance : - Rezonance: + + Band 1 Gain: + Zesílení pásma 1: - Frequency: - Frekvence: + + Band 2 Gain: + Zesílení pásma 2: - Octave - oktávy + + Band 3 Gain: + Zesílení pásma 3: - Low-shelf - + + Band 4 Gain: + Zesílení pásma 4: - High-shelf - + + Band 1 Mute + Ztlumení pásma 1 - Input gain - Zesílení vstupu + + Mute Band 1 + Ztlumit pásmo 1 - Output gain - Zesílení výstupu + + Band 2 Mute + Ztlumení pásma 2 - LP group - + + Mute Band 2 + Ztlumit pásmo 2 - HP group - + + Band 3 Mute + Ztlumení pásma 3 - - - EqHandle - Reso: - Rezon: + + Mute Band 3 + Ztlumit pásmo 3 - BW: - ŠPás: + + Band 4 Mute + Ztlumení pásma 4 - Freq: - Frekv: + + Mute Band 4 + Ztlumit pásmo 4 - FlangerControls - - Seconds - Sekund - + DelayControls - Regen - Obnov + + Delay Samples + Zpoždění vzorků - Noise - Šum + + Feedback + Zpětná vazba - Invert - Převrátit + + Lfo Frequency + Frekvence LFO - Delay samples - + + Lfo Amount + Hloubka LFO - LFO frequency - + + Output gain + Zesílení výstupu - FlangerControlsDialog + DelayControlsDialog + DELAY ZPOŽ - RATE - POMĚR - - - AMNT - MNOŽ + + Delay Time + Délka zpoždění - Amount: - Množství: + + FDBK + ZPVAZ - FDBK - FDBK + + Feedback Amount + Hloubka zpětné vazby - NOISE - ŠUM + + RATE + RYCH - Invert - Převrátit + + Lfo + LFO - Period: - Perioda: + + AMNT + MNOŽ - Delay time: - + + Lfo Amt + Hloubka LFO - Feedback amount: - + + Out Gain + Zesílení výstupu - White noise amount: - + + Gain + Zesílení - FreeBoyInstrument + DualFilterControlDialog - Sweep time - Trvání sweepu + + + FREQ + FREKV - Sweep direction - Směr sweepu + + + Cutoff frequency + Frekvence oříznutí - Channel 1 volume - Hlasitost kanálu 1 + + + RESO + REZON - Volume sweep direction - Směr hlasitosti sweepu + + + Resonance + Rezonance - Length of each step in sweep - Délka každého kroku ve sweepu + + + GAIN + ZESIL - Channel 2 volume - Hlasitost kanálu 2 + + + Gain + Zesílení - Channel 3 volume - Hlasitost kanálu 3 + + MIX + POMĚR - Channel 4 volume - Hlasitost kanálu 4 + + Mix + Poměr - Channel 1 to SO2 (Left) - Kanál 1 do SO2 (pravý) + + Filter 1 enabled + Filtr 1 zapnutý - Channel 2 to SO2 (Left) - Kanál 2 do SO2 (pravý) + + Filter 2 enabled + Filtr 2 zapnutý - Channel 3 to SO2 (Left) - Kanál 3 do SO2 (pravý) + + Click to enable/disable Filter 1 + Klepněte pro zapnutí/vypnutí filtru 1 - Channel 4 to SO2 (Left) - Kanál 4 do SO2 (pravý) + + Click to enable/disable Filter 2 + Klepněte pro zapnutí/vypnutí filtru 2 + + + DualFilterControls - Channel 1 to SO1 (Right) - Kanál 1 do SO1 (pravý) + + Filter 1 enabled + Filtr 1 zapnutý - Channel 2 to SO1 (Right) - Kanál 2 do SO1 (pravý) + + Filter 1 type + Typ filtru 1 - Channel 3 to SO1 (Right) - Kanál 3 do SO1 (pravý) + + Cutoff 1 frequency + Frekvence oříznutí 1 - Channel 4 to SO1 (Right) - Kanál 4 do SO1 (pravý) + + Q/Resonance 1 + Q/rezonance 1 - Treble - Výšky + + Gain 1 + Zesílení 1 - Bass - Basy + + Mix + Mix - Shift Register width - Posun šířky registru - - - Sweep rate shift amount - - - - Wave pattern duty cycle - - - - Right output level - - - - Left output level - - - - - FreeBoyInstrumentView - - Length of each step in sweep: - Délka každého kroku ve sweepu: + + Filter 2 enabled + Filtr 1 zapnutý - Length of each step in sweep - Délka každého kroku ve sweepu + + Filter 2 type + Typ filtru 2 - Treble: - Výšky: + + Cutoff 2 frequency + Frekvence oříznutí 2 - Treble - Výšky + + Q/Resonance 2 + Q/rezonance 2 - Bass: - Basy: + + Gain 2 + Zesílení 2 - Bass - Basy + + + LowPass + Dolní propust - Sweep time: - + + + HiPass + Horní propust - Sweep time - Trvání sweepu + + + BandPass csg + Pásmová propust csg - Sweep rate shift amount: - + + + BandPass czpg + Pásmová propust czpg - Sweep rate shift amount - + + + Notch + Pásmová zádrž - Wave pattern duty cycle: - + + + Allpass + Všepásmový filtr - Wave pattern duty cycle - + + + Moog + Moogův filtr - Square channel 1 volume: - + + + 2x LowPass + 2x dolní propust - Square channel 1 volume - + + + RC LowPass 12dB + RC dolní propust 12dB - Square channel 2 volume: - + + + RC BandPass 12dB + RC pásmová propust 12dB - Square channel 2 volume - + + + RC HighPass 12dB + RC horní propust 12dB - Wave pattern channel volume: - + + + RC LowPass 24dB + RC dolní propust 24dB - Wave pattern channel volume - + + + RC BandPass 24dB + RC pásmová propust 24dB - Noise channel volume: - + + + RC HighPass 24dB + RC horní propust 24dB - Noise channel volume - + + + Vocal Formant Filter + Vokální formantový filtr - SO1 volume (Right): - + + + 2x Moog + 2x Moogův filtr - SO1 volume (Right) - + + + SV LowPass + SV dolní propust - SO2 volume (Left): - + + + SV BandPass + SV pásmová propust - SO2 volume (Left) - + + + SV HighPass + SV horní propust - Sweep direction - Směr sweepu + + + SV Notch + SV pásmová zádrž - Volume sweep direction - Směr hlasitosti sweepu + + + Fast Formant + Rychlý formantový filtr - Shift register width - + + + Tripole + Třípólový filtr + + + Editor - Channel 1 to SO1 (Right) - Kanál 1 do SO1 (pravý) + + Transport controls + Řízení přenosu - Channel 2 to SO1 (Right) - Kanál 2 do SO1 (pravý) + + Play (Space) + Přehrát (mezerník) - Channel 3 to SO1 (Right) - Kanál 3 do SO1 (pravý) + + Stop (Space) + Zastavit (mezerník) - Channel 4 to SO1 (Right) - Kanál 4 do SO1 (pravý) + + Record + Nahrávat - Channel 1 to SO2 (Left) - Kanál 1 do SO2 (pravý) + + Record while playing + Nahrávat při přehrávání + + + Effect - Channel 2 to SO2 (Left) - Kanál 2 do SO2 (pravý) + + Effect enabled + Efekt aktivován - Channel 3 to SO2 (Left) - Kanál 3 do SO2 (pravý) + + Wet/Dry mix + Poměr zpracovaného/původního signálu - Channel 4 to SO2 (Left) - Kanál 4 do SO2 (pravý) + + Gate + Brána - Wave pattern graph - + + Decay + Pokles - GigInstrument + EffectChain - Bank - Banka + + Effects enabled + Efekty aktivovány + + + EffectRackView - Patch - Patch + + EFFECTS CHAIN + ŘETĚZ EFEKTŮ - Gain - Zisk + + Add effect + Přidat efekt - GigInstrumentView + EffectSelectDialog - Open GIG file - Otevřít GIG soubor + + Add effect + Přidat efekt - GIG Files (*.gig) - GIG soubory (*.gig) + + + Name + Název - Choose patch - + + Type + Typ - Gain: - + + Description + Popis - - - InstrumentTrack - Default preset - Výchozí předvolba + + Author + Autor - LadspaControlDialog + EffectView - Link Channels - Propojit kanály + + Toggles the effect on or off. + Zapnout nebo vypnout efekty. - Channel - Kanál + + On/Off + Zap/Vyp - - - LadspaEffect - Unknown LADSPA plugin %1 requested. - Je požadován neznámý LADSPA plugin %1. + + W/D + POM - - - MidiImport - Setup incomplete - Nastavení není dokončeno + + Wet Level: + Úroveň zpracovaného signálu: - You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. - Nelze zkompilovat LMMS s podporou přehrávače SoundFont2, který je použitý k přidání výchozího zvuku do importovaných MIDI souborů. Proto nebude po importování tohoto MIDI souboru přehráván žádný zvuk. + + The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. + Otočný ovladač Poměr nastavuje poměr mezi vstupním signálem a signálem efektu, který formuje výstup. - Track - Stopa + + DECAY + POKLES - You have not set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. - + + Time: + Délka: - - - MonstroInstrument - Osc 3 Stereo phase offset - Osc 3 posun stereo fáze + + The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. + Otočný ovladač Útlum nastavuje, kolik bufferů ticha musí proběhnout před tím, než plugin přestane zpracovávat. Menší hodnoty zredukují přetížení CPU, ale mohou způsobit oříznutí na konci zpožďovacích a dozvukových efektů. - Selected view - Zvolený pohled + + GATE + BRÁ - Sine wave - Sinusová vlna + + Gate: + Brána: - Bandlimited Triangle wave - Pásmově zúžená trojúhelníková vlna + + The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. + Otočný ovladač Brána určuje sílu signálu, který je považován za "ticho" při rozhodování, kdy skončit se zpracováním signálů. - Bandlimited Saw wave - Pásmově zúžená pilovitá vlna + + Controls + Ovladače - Bandlimited Ramp wave - Pásmově zúžená šikmá vlna + + Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. + +The On/Off switch allows you to bypass a given plugin at any point in time. + +The Wet/Dry knob controls the balance between the input signal and the effected signal that is the resulting output from the effect. The input for the stage is the output from the previous stage. So, the 'dry' signal for effects lower in the chain contains all of the previous effects. + +The Decay knob controls how long the signal will continue to be processed after the notes have been released. The effect will stop processing signals when the volume has dropped below a given threshold for a given length of time. This knob sets the 'given length of time'. Longer times will require more CPU, so this number should be set low for most effects. It needs to be bumped up for effects that produce lengthy periods of silence, e.g. delays. + +The Gate knob controls the 'given threshold' for the effect's auto shutdown. The clock for the 'given length of time' will begin as soon as the processed signal level drops below the level specified with this knob. + +The Controls button opens a dialog for editing the effect's parameters. + +Right clicking will bring up a context menu where you can change the order in which the effects are processed or delete an effect altogether. + Efektové pluginy fungují jako zřetězená série efektů, kde signál bude postupně zpracováván shora dolů. + +Přepínač Zapnuto/Vypnuto vám umožní v libovolném časovém okamžiku daný plugin odpojit. + +Otočný ovladač Poměr řídí vyvážení mezi vstupním a již zpracovaným signálem ve výsledném výstupu efektu. Vstup je v této fázi shodný s výstupem předchozího efektu. Takže když je Poměr nastaven na nízkou hodnotu, obsahuje signál všechny předchozí efekty. + +Otočný ovladač Útlum určuje, jak dlouho bude zpracovávání signálu pokračovat po skončení noty. Efekt přestane zpracovávat signál, když hlasitost klesne pod hodnotu daného prahu v daném časovém úseku. Tento ovladač nastavuje právě "daný časový úsek". Delší časy vyžadují více výkonu procesoru, takže pro většinu efektů by měla být nastavena nízká hodnota. Naopak je potřeba nastavit vyšší hodnotu pro efekty, které vytvářejí delší úseky ticha, jako je např. echo (delay). +Otočný ovladač Brána určuje "daný práh" pro automatické ukončení efektu. + +Počítání délky "daného časového úseku" začíná bezprostředně poté, co úroveň zpracovávaného signálu poklesne pod úroveň určenou tímto ovladačem. + +Tlačítko Ovladače otevře dialogové okno pro úpravu parametrů efektu. + +Klepnutí pravým tlačítkem myši vyvolá kontextovou nabídku, kde můžete měnit pořadí, ve kterém budou efekty zpracovávány, nebo můžete efekt úplně odstranit. - Bandlimited Square wave - Pásmově zúžená pravoúhlá vlna + + Move &up + Posunout &nahoru - Bandlimited Moog saw wave - Pásmově zúžená pilovitá vlna typu Moog + + Move &down + Posunout &dolů - Soft square wave - Zaoblená pravoúhlá vlna + + &Remove this plugin + &Odstranit tento plugin + + + EnvelopeAndLfoParameters - Absolute sine wave - Absolutní sinusová vlna + + Predelay + Předzpoždění - Exponential wave - Exponenciální vlna + + Attack + Náběh - White noise - Bílý šum + + Hold + Držení - Digital Triangle wave - Digitální trojúhelníková vlna + + Decay + Útlum - Digital Saw wave - Digitální pilovitá vlna + + Sustain + Vydržení - Digital Ramp wave - Digitální šikmá vlna + + Release + Doznění - Digital Square wave - Digitální pravoúhlá vlna + + Modulation + Modulace - Digital Moog saw wave - Digitální pilovitá vlna typu Moog + + LFO Predelay + Předzpoždění LFO - Triangle wave - Trojúhelníková vlna + + LFO Attack + Náběh LFO - Saw wave - Pilovitá vlna + + LFO speed + Rychlost LFO - Ramp wave - Šikmá vlna + + LFO Modulation + Modulace LFO - Square wave - Pravoúhlá vlna + + LFO Wave Shape + Tvar vlny LFO - Moog saw wave - Pilovitá vlna typu Moog + + Freq x 100 + Frekvence x 100 - Abs. sine wave - Abs. sinusová vlna + + Modulate Env-Amount + Hloubka modulace + + + EnvelopeAndLfoView - Random - Náhodná + + + DEL + PŘED - Random smooth - Vyhlazená náhodná + + Predelay: + Předzpoždění: - Osc 1 volume - + + Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. + Tento otočný ovladač nastavuje předzpoždění (predelay) aktuální obálky. Zvýšením hodnoty se prodlouží čas před začátkem obálky. - Osc 1 panning - + + + ATT + NÁB - Osc 1 coarse detune - + + Attack: + Náběh: - Osc 1 fine detune left - + + Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. + Tento otočný ovladač nastavuje náběh (attack) u aktuální obálky. Zvýšením hodnoty se prodlouží délka náběhu obálky. Zvolte nižší hodnotu pro nástroje typu piano a vyšší pro smyčce. - Osc 1 fine detune right - + + HOLD + DRŽ - Osc 1 stereo phase offset - + + Hold: + Držení: - Osc 1 pulse width - + + Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. + Tento otočný ovladač nastavuje délku držení (hold) u aktuální obálky. Zvýšením hodnoty se prodlouží část obálky, která zůstává na úrovni náběhu (attack) ještě před začátkem útlumu (decay) na úroveň vydržení (sustain). - Osc 1 sync send on rise - + + DEC + ÚTL - Osc 1 sync send on fall - + + Decay: + Útlum: - Osc 2 volume - + + Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. + Tento otočný ovladač nastavuje délku útlumu (decay) u aktuální obálky. Zvýšením hodnoty se prodlouží část obálky, potřebná k zeslabení z úrovně náběhu (attack) na úroveň vydržení (sustain). Zvolte nižší hodnotu pro nástroje typu piano. - Osc 2 panning - + + SUST + VYD - Osc 2 coarse detune - + + Sustain: + Držení: - Osc 2 fine detune left - + + Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. + Tento otočný ovladač nastavuje vydržení (sustain) u aktuální obálky. Zvýšením hodnoty se navýší úroveň, na které obálka zůstává před poklesem na nulu. - Osc 2 fine detune right - + + REL + UVOL - Osc 2 stereo phase offset - + + Release: + Uvolnění: - Osc 2 waveform - + + Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. + Tento otočný ovladač nastavuje délku uvolnění (release) u aktuální obálky. Zvýšením hodnoty se prodlouží část obálky, potřebná k zeslabení z úrovně vydržení (sustain) na nulovou úroveň. Zvolte vyšší hodnotu pro nástroje s měkkým zvukem, jako např. smyčce. - Osc 2 sync hard - + + + AMT + MOD - Osc 2 sync reverse - + + + Modulation amount: + Hloubka modulace: - Osc 3 volume - + + Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. + Tento otočný ovladač nastavuje hloubku modulace u aktuální obálky. Zvýšení této hodnoty v závislosti na velikosti (např. hlasitosti nebo frekvence odstřihnutí) způsobí větší ovlivnění touto obálkou. - Osc 3 panning - + + LFO predelay: + Předzpoždění LFO: - Osc 3 coarse detune - + + Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. + Tento otočný ovladač nastavuje délku předzpoždění (predelay) aktuálního LFO. Zvýšením hodnoty se prodlouží čas před spuštěním kmitání LFO. - Osc 3 sub-oscillator mix - + + LFO- attack: + Náběh LFO: - Osc 3 waveform 1 - + + Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. + Tento otočný ovladač nastavuje délku náběhu (attack) u aktuálního LFO. Zvýšením hodnoty se prodlouží čas potřebný pro zvýšení amplitudy LFO na maximum. - Osc 3 waveform 2 - + + SPD + RYCH - Osc 3 sync hard - + + LFO speed: + Rychlost LFO: - Osc 3 Sync reverse - + + Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. + Tento otočný ovladač nastavuje rychlost u aktuálního LFO. Zvýšením hodnoty se zrychlí kmitání LFO a průběh vašeho efektu. - LFO 1 waveform - + + Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. + Tento otočný ovladač nastavuje hloubku modulace u aktuálního LFO. Zvýšení hodnoty v závislosti na velikosti (např. hlasitosti nebo frekvence odstřihnutí) způsobí větší ovlivnění tímto LFO. - LFO 1 attack - + + Click here for a sine-wave. + Klepněte sem pro sinusovou vlnu. - LFO 1 rate - + + Click here for a triangle-wave. + Klepněte sem pro trojúhelníkovou vlnu. - LFO 1 phase - + + Click here for a saw-wave for current. + Klepněte sem pro pilovitou vlnu. - LFO 2 waveform - + + Click here for a square-wave. + Klepněte sem pro pravoúhlou vlnu. - LFO 2 attack - + + Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. + Klepněte sem pro vlastní vlnu. Poté přetáhněte zvolený soubor samplu do grafického okna LFO. - LFO 2 rate - + + Click here for random wave. + Klepněte sem pro náhodnou vlnu. - LFO 2 phase - + + FREQ x 100 + FREKVENCE x 100 - Env 1 pre-delay - + + Click here if the frequency of this LFO should be multiplied by 100. + Klepněte sem, pokud má být frekvence LFO vynásobena x100. - Env 1 attack - + + multiply LFO-frequency by 100 + vynásobit frekvenci LFO x100 - Env 1 hold - + + MODULATE ENV-AMOUNT + MODULOVAT OBÁLKU - Env 1 decay - + + Click here to make the envelope-amount controlled by this LFO. + Klepněte sem, pokud má být množství obálky řízeno tímto LFO. - Env 1 sustain - + + control envelope-amount by this LFO + řízení množství obálky tímto LFO - Env 1 release - + + ms/LFO: + ms/LFO: - Env 1 slope - + + Hint + Rada - Env 2 pre-delay - + + Drag a sample from somewhere and drop it in this window. + Sampl odněkud přetáhněte a pusťte jej v tomto okně. + + + EqControls - Env 2 attack - + + Input gain + Zesílení vstupu - Env 2 hold - + + Output gain + Zesílení výstupu - Env 2 decay - + + Low shelf gain + Zesílení dolního šelfu - Env 2 sustain - + + Peak 1 gain + Zesílení špičky 1 - Env 2 release - + + Peak 2 gain + Zesílení špičky 2 - Env 2 slope - + + Peak 3 gain + Zesílení špičky 3 - Osc 2+3 modulation - + + Peak 4 gain + Zesílení špičky 4 - Osc 1 - Vol env 1 - + + High Shelf gain + Zesílení horního šelfu - Osc 1 - Vol env 2 - + + HP res + Rezonance horní propusti - Osc 1 - Vol LFO 1 - + + Low Shelf res + Rezonance dolního šelfu - Osc 1 - Vol LFO 2 - + + Peak 1 BW + Šířka pásma špičky 1 - Osc 2 - Vol env 1 - + + Peak 2 BW + Šířka pásma špičky 2 - Osc 2 - Vol env 2 - + + Peak 3 BW + Šířka pásma špičky 3 - Osc 2 - Vol LFO 1 - + + Peak 4 BW + Šířka pásma špičky 4 - Osc 2 - Vol LFO 2 - + + High Shelf res + Rezonance horního šelfu - Osc 3 - Vol env 1 - + + LP res + Rezonance dolní propusti - Osc 3 - Vol env 2 - + + HP freq + Frekvence horní propusti - Osc 3 - Vol LFO 1 - + + Low Shelf freq + Frekvence dolního šelfu - Osc 3 - Vol LFO 2 - + + Peak 1 freq + Frekvence špičky 1 - Osc 1 - Phs env 1 - + + Peak 2 freq + Frekvence špičky 2 - Osc 1 - Phs env 2 - + + Peak 3 freq + Frekvence špičky 3 - Osc 1 - Phs LFO 1 - + + Peak 4 freq + Frekvence špičky 3 - Osc 1 - Phs LFO 2 - + + High shelf freq + Frekvence špičky 4 - Osc 2 - Phs env 1 - + + LP freq + Frekvence dolní propusti - Osc 2 - Phs env 2 - + + HP active + Horní propust aktivní - Osc 2 - Phs LFO 1 - + + Low shelf active + Dolní šelf aktivní - Osc 2 - Phs LFO 2 - + + Peak 1 active + Špička 1 aktivní - Osc 3 - Phs env 1 - + + Peak 2 active + Špička 2 aktivní - Osc 3 - Phs env 2 - + + Peak 3 active + Špička 3 aktivní - Osc 3 - Phs LFO 1 - + + Peak 4 active + Špička 4 aktivní - Osc 3 - Phs LFO 2 - + + High shelf active + Horní šelf aktivní - Osc 1 - Pit env 1 - + + LP active + Dolní propust aktivní - Osc 1 - Pit env 2 - + + LP 12 + DP 12 - Osc 1 - Pit LFO 1 - + + LP 24 + DP 24 - Osc 1 - Pit LFO 2 - + + LP 48 + DP 48 - Osc 2 - Pit env 1 - + + HP 12 + HP 12 - Osc 2 - Pit env 2 - + + HP 24 + HP 24 - Osc 2 - Pit LFO 1 - + + HP 48 + HP 48 - Osc 2 - Pit LFO 2 - + + low pass type + typ dolní propusti - Osc 3 - Pit env 1 - + + high pass type + typ horní propusti - Osc 3 - Pit env 2 - - + + Analyse IN + Analýza VSTUPU + - Osc 3 - Pit LFO 1 - + + Analyse OUT + Analýza VÝSTUPU + + + EqControlsDialog - Osc 3 - Pit LFO 2 - + + HP + HP - Osc 1 - PW env 1 - + + Low Shelf + Dolní šelf - Osc 1 - PW env 2 - + + Peak 1 + Špička 1 - Osc 1 - PW LFO 1 - + + Peak 2 + Špička 2 - Osc 1 - PW LFO 2 - + + Peak 3 + Špička 3 - Osc 3 - Sub env 1 - + + Peak 4 + Špička 4 - Osc 3 - Sub env 2 - + + High Shelf + Horní šelf - Osc 3 - Sub LFO 1 - + + LP + DP - Osc 3 - Sub LFO 2 - + + In Gain + Zesílení vstupu - - - MonstroView - Operators view - Zobrazení operátorů + + + + Gain + Zesílení - Matrix view - Zobrazení matrice + + Out Gain + Zesílení výstupu - Volume - Hlasitost + + Bandwidth: + Šířka pásma: - Panning - Panoráma + + Octave + oktávy - Coarse detune - Hrubé rozladění + + Resonance : + Rezonance: - semitones - půltónů + + Frequency: + Frekvence: - cents - centů + + lp grp + dp skup - Stereo phase offset - Posun stereo fáze + + hp grp + hp skup + + + EqHandle - deg - stupňů + + Reso: + Rezon: - Pulse width - Délka pulzu + + BW: + ŠPás: - Send sync on pulse rise - Synchronizace při nárůstu pulzu + + + Freq: + Frekv: + + + ExportProjectDialog - Send sync on pulse fall - Synchronizace při poklesu pulzu + + Export project + Exportovat projekt - Hard sync oscillator 2 - Pevně synchronizovat oscilátor 2 + + Output + Výstup - Reverse sync oscillator 2 - Reverzně synchronizovat oscilátor 2 + + File format: + Formát souboru: - Sub-osc mix - Míchání sub-osc + + Samplerate: + Vzorkovací frekvence: - Hard sync oscillator 3 - Pevně synchronizovat oscilátor 3 + + 44100 Hz + 44100 Hz - Reverse sync oscillator 3 - Reverzně synchronizovat oscilátor 3 + + 48000 Hz + 48000 Hz - Attack - Náběh + + 88200 Hz + 88200 Hz - Rate - Typ + + 96000 Hz + 96000 Hz - Phase - Fáze + + 192000 Hz + 192000 Hz - Pre-delay - Předzpoždění + + Depth: + Hloubka: - Hold - Držení + + 16 Bit Integer + 16 bitů celočíselně - Decay - Útlum + + 24 Bit Integer + 24 bitů celočíselně - Sustain - Vydržení + + 32 Bit Float + 32 bitů s plovoucí čárkou - Release - Uvolnění + + Stereo mode: + Režim stereo: - Slope - Stoupání + + Stereo + Stereo - Modulation amount - Hloubka modulace + + Joint Stereo + Joint stereo - Fine tune left - + + Mono + Mono - Fine tune right - + + Bitrate: + Datový tok: - Mix osc 2 with osc 3 - + + 64 KBit/s + 64 kbit/s - Modulate amplitude of osc 3 by osc 2 - + + 128 KBit/s + 128 kbit/s - Modulate frequency of osc 3 by osc 2 - + + 160 KBit/s + 160 kbit/s - Modulate phase of osc 3 by osc 2 - + + 192 KBit/s + 192 kbit/s - - - MultitapEchoControlDialog - Length - Délka + + 256 KBit/s + 256 kbit/s - Step length: - Délka kroku: + + 320 KBit/s + 320 kbit/s - Dry - Poměr + + Use variable bitrate + Použít proměnlivý datový tok - Stages - Úrovně + + Quality settings + Nastavení kvality - Swap inputs - Přepnout vstupy + + Interpolation: + Interpolace: - Dry gain: - + + Zero Order Hold + Zero-order hold - Low-pass stages: - + + Sinc Fastest + Sinc nejrychlejší - Swap left and right input channels for reflections - + + Sinc Medium (recommended) + Sinc střední (doporučeno) - - - NesInstrument - Channel 2 Coarse detune - Kanál 2 hrubé rozladění + + Sinc Best (very slow!) + Sinc nejlepší (velmi pomalé!) - Channel 2 Volume - Hlasitost kanálu 2 + + Oversampling (use with care!): + Převzorkování (používejte opatrně!): - Master volume - Hlavní hlasitost + + 1x (None) + 1x (žádné) - Vibrato - Vibráto + + 2x + 2x - Channel 1 coarse detune - + + 4x + 4x - Channel 1 volume - Hlasitost kanálu 1 + + 8x + 8x - Channel 1 envelope length - + + Export as loop (remove end silence) + Exportovat jako smyčku (odstranění ticha na konci) - Channel 1 duty cycle - + + Export between loop markers + Exportovat obsah smyčky - Channel 1 sweep amount - + + Start + Začít - Channel 1 sweep rate - + + Cancel + Zrušit - Channel 2 envelope length - + + Could not open file + Nemohu otevřít soubor - Channel 2 duty cycle - + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Nelze otevřít soubor %1 pro zápis. +Ověřte si prosím, zda máte povolen zápis do souboru a do složky, ve které je umístěn, a zkuste znovu! - Channel 2 sweep amount - + + Export project to %1 + Exportovat projekt do %1 - Channel 2 sweep rate - + + Error + Chyba - Channel 3 coarse detune - + + Error while determining file-encoder device. Please try to choose a different output format. + Chyba při zjišťování souboru enkodéru. Zkuste prosím vybrat jiný výstupní formát. - Channel 3 volume - Hlasitost kanálu 3 + + Rendering: %1% + Renderuji: %1% - Channel 4 volume - Hlasitost kanálu 4 + Compression level: + Úroveň komprese: - Channel 4 envelope length - + (fastest) + (nejrychlejší) - Channel 4 noise frequency - + (default) + (výchozí) - Channel 4 noise frequency sweep - + (smallest) + (nejmenší) - NesInstrumentView + Expressive - Volume - Hlasitost + Selected graph + Zvolený graf - Coarse detune - Hrubé rozladění + A1 + A1 - Envelope length - Délka obálky + A2 + A2 - Enable channel 1 - Zapnout kanál 1 + A3 + A3 - Enable envelope 1 - Zapnout obálku 1 + W1 smoothing + W1 vyhlazování - Enable envelope 1 loop - Zapnout smyčku obálky 1 + W2 smoothing + W2 vyhlazování - Enable sweep 1 - Zapnout sweep 1 + W3 smoothing + W3 vyhlazování - Sweep amount - Množství sweepu + PAN1 + PAN1 - Sweep rate - Rychlost sweepu + PAN2 + PAN2 - 12.5% Duty cycle - 12.5% pracovního cyklu + REL TRANS + + + + Fader - 25% Duty cycle - 25% pracovního cyklu + + + Please enter a new value between %1 and %2: + Vložte prosím novou hodnotu mezi %1 a %2: + + + FileBrowser - 50% Duty cycle - 50% pracovního cyklu + + Browser + Prohlížeč - 75% Duty cycle - 75% pracovního cyklu + Search + Hledat - Enable channel 2 - Zapnout kanál 2 + Refresh list + Obnovit seznam + + + FileBrowserTreeWidget - Enable envelope 2 - Zapnout obálku 2 + + Send to active instrument-track + Odeslat do aktivní stopy nástroje - Enable envelope 2 loop - Zapnout smyčku obálky 2 + + Open in new instrument-track/Song Editor + Otevřít v nové nástrojové stopě / Editoru skladby - Enable sweep 2 - Zapnout sweep 2 + + Open in new instrument-track/B+B Editor + Otevřít v nové nástrojové stopě / editoru bicich/basů - Enable channel 3 - Zapnout kanál 3 + + Loading sample + Načítám vzorek - Noise Frequency - Frekvence šumu + + Please wait, loading sample for preview... + Počkejte prosím, načítám vzorek pro náhled... - Frequency sweep - Frekvence sweepu + + Error + Chyba - Enable channel 4 - Zapnout kanál 4 + + does not appear to be a valid + nevypadá, že je platný - Enable envelope 4 - Zapnout obálku 4 + + file + soubor - Enable envelope 4 loop - Zapnout smyčku obálky 4 + + --- Factory files --- + --- Tovární soubory --- + + + FileBrowserTreeWidget + + + FlangerControls - Quantize noise frequency when using note frequency - Kvantizovat frekvenci šumu při použití frekvence noty + + Delay Samples + Zpoždění vzorků - Use note frequency for noise - Použít frekvenci pro šum + + Lfo Frequency + Frekvence LFO - Noise mode - Typ šumu + + Seconds + Sekund - Vibrato - Vibráto + + Regen + Obnov - Master volume - Hlavní hlasitost + + Noise + Šum + + + + Invert + Převrátit - OpulenzInstrument + FlangerControlsDialog - Patch - Patch + + DELAY + ZPOŽ - Op 1 attack - + + Delay Time: + Délka zpoždění: - Op 1 decay - + + RATE + POMĚR - Op 1 sustain - + + Period: + Perioda: - Op 1 release - + + AMNT + MNOŽ - Op 1 level - + + Amount: + Množství: - Op 1 level scaling - + + FDBK + ZP. VAZ - Op 1 frequency multiplier - + + Feedback Amount: + Velikost zpětné vazby: - Op 1 feedback - + + NOISE + ŠUM - Op 1 key scaling rate - + + White Noise Amount: + Množství bílého šumu: - Op 1 percussive envelope - + + Invert + Převrátit + + + FxLine - Op 1 tremolo - + + Channel send amount + Množství odeslaného kanálu - Op 1 vibrato - + + The FX channel receives input from one or more instrument tracks. + It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. + +In order to route the channel to another channel, select the FX channel and click on the "send" button on the channel you want to send to. The knob under the send button controls the level of signal that is sent to the channel. + +You can remove and move FX channels in the context menu, which is accessed by right-clicking the FX channel. + + Efektový (FX) kanál přijímá vstup z jedné nebo více nástrojových stop. +Ten může být následně směrován do dalších efektových kanálů. LMMS automaticky zabraňuje vzniku nekonečných smyček a nedovoluje provést propojení, které by ke vzniku smyčky mohlo vést. + +Chcete-li směrovat kanál do jiného kanálu, vyberte efektový kanál a klepněte na tlačítko "SEND" v kanálu, který chcete odeslat. Otočný ovladač pod tlačítkem "SEND" určuje množství signálu, které bude do kanálu odesláno. + +Efektové kanály můžete odstranit nebo přesunout v kontextové nabídce, která je dostupná po klepnutí pravým tlačítkem myši na efektový kanál. + - Op 1 waveform - + + Move &left + Přesunout do&leva - Op 2 attack - + + Move &right + Přesun dop&rava - Op 2 decay - + + Rename &channel + Přejmenovat &kanál - Op 2 sustain - + + R&emove channel + Př&esunout kanál - Op 2 release - + + Remove &unused channels + Odstranit nepo&užívané kanály + + + FxMixer - Op 2 level - + + Master + Hlavní - Op 2 level scaling - + + + + FX %1 + Efekt %1 - Op 2 frequency multiplier - + + Volume + Hlasitost - Op 2 key scaling rate - + + Mute + Ztlumit - Op 2 percussive envelope - + + Solo + Sólo + + + FxMixerView - Op 2 tremolo - + + FX-Mixer + Efektový mixážní panel - Op 2 vibrato - + + FX Fader %1 + Efektový fader %1 - Op 2 waveform - + + Mute + Ztlumit - FM - FM + + Mute this FX channel + Ztlumit tento efektový kanál - Vibrato depth - + + Solo + Sólo - Tremolo depth - + + Solo FX channel + Sólovat efektový kanál - OpulenzInstrumentView + FxRoute - Attack - Náběh + + + Amount to send from channel %1 to channel %2 + Množství k odeslání z kanálu %1 do kanálu %2 + + + GigInstrument - Decay - Útlum + + Bank + Banka - Release - Uvolnění + + Patch + Patch - Frequency multiplier - Násobič frekvence + + Gain + Zisk - OscillatorObject + GigInstrumentView - Osc %1 volume - Osc %1 hlasitost + + Open other GIG file + Otevřít jiný GIG soubor - Osc %1 panning - Osc %1 panoráma + + Click here to open another GIG file + Klepněte sem pro otevření jiného GIG souboru - Osc %1 coarse detuning - Osc %1 hrubé rozladění + + Choose the patch + Vybrat patch - Osc %1 fine detuning left - Osc %1 jemné rozladění vlevo + + Click here to change which patch of the GIG file to use + Klepněte sem pro změnu patche GIG souboru - Osc %1 fine detuning right - Osc %1 jemné rozladění vpravo + + + Change which instrument of the GIG file is being played + Změnit přehrávaný nástroj GIG souboru - Osc %1 phase-offset - Osc %1 posun fáze + + Which GIG file is currently being used + Který GIG soubor je právě používán - Osc %1 stereo phase-detuning - Osc %1 rozladění stereo fáze + + Which patch of the GIG file is currently being used + Který patch GIG souboru je právě používán - Osc %1 wave shape - Osc %1 forma vlny + + Gain + Zesílení - Modulation type %1 - Typ modulace %1 + + Factor to multiply samples by + Vynásobit vzorky x - Osc %1 waveform - Osc %1 vlna + + Open GIG file + Otevřít GIG soubor - Osc %1 harmonic - Osc %1 harmonické + + GIG Files (*.gig) + GIG soubory (*.gig) - PatchesDialog - - Qsynth: Channel Preset - Qsynth: Předvolba kanálu - - - Bank selector - Výběr banky - + GuiApplication - Bank - Banka + + Working directory + Pracovní adresář - Program selector - Výběr programu + + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. + Pracovní adresář LMMS %1 neexistuje. Chcete jej nyní vytvořit? Změnu adresáře mžete provést později v nabídce Úpravy -> Nastavení. - Patch - Patch + + Preparing UI + Připravuji UI - Name - Název + + Preparing song editor + Připravuji editor skladby - OK - OK + + Preparing mixer + Připravuji mixážní panel - Cancel - Zrušit + + Preparing controller rack + Připravuji panel ovladačů - - - PatmanView - Loop - Smyčka + + Preparing project notes + Připravuji poznámky k projektu - Loop mode - Režim smyčky + + Preparing beat/bassline editor + Připravuji editor bicích/basů - Tune - Ladění + + Preparing piano roll + Připravuji Piano roll - Tune mode - Režim ladění + + Preparing automation editor + Připravuji Editor automatizace + + + InstrumentFunctionArpeggio - No file selected - Není vybrán žádný soubor + + Arpeggio + Arpeggio - Open patch file - Otevřít soubor patch + + Arpeggio type + Typ arpeggia - Patch-Files (*.pat) - Soubor patch (*.pat) + + Arpeggio range + Rozsah arpeggia - Open patch - + + Cycle steps + Počet kroků v cyklu - - - PeakControllerEffectControlDialog - BASE - ZÁKL + + Skip rate + Míra vynechávání - Modulation amount: - Hloubka modulace: + + Miss rate + Míra míjení - Attack: - Náběh: + + Arpeggio time + Trvání arpeggia - Release: - Uvolnění: + + Arpeggio gate + Brána arpeggia - AMNT - MNOŽ + + Arpeggio direction + Směr arpeggia - MULT - NÁSB + + Arpeggio mode + Styl arpeggia - ATCK - NÁBH + + Up + Nahoru - DCAY - ÚTLM + + Down + Dolů - Treshold: - Práh: + + Up and down + Nahoru a dolů - TRSH - PRÁH + + Down and up + Dolů a nahoru - Base: - + + Random + Náhodné - Amount multiplicator: - + + Free + Volné - Mute output - Ztlumit výstup + + Sort + Tříděné - Absolute value - + + Sync + Synchronizované - PeakControllerEffectControls - - Base value - Základní hodnota - + InstrumentFunctionArpeggioView - Modulation amount - Hloubka modulace + + ARPEGGIO + ARPEGGIO - Mute output - Ztlumit výstup + + An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. + Arpeggio je způsob hry (zejména na drnkací nástroje), který činí hudbu mnohem živější. Struny těchto nástrojů (např. harfy) jsou rozezněny jako v akordech. Jediným rozdílem je, že se tak stane sekvenčně, takže tóny nejsou zahrány ve stejnou dobu. Typickým arpeggiem jsou durové a mollové trojzvuky, ale možných dalších akordů, které si můžete vybrat, je spousta. - Attack - Náběh + + RANGE + ROZSAH - Release - Uvolnění + + Arpeggio range: + Rozsah arpeggia: - Treshold - Práh + + octave(s) + oktáva(y) - Absolute value - + + Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. + Tento otočný ovladač použijte pro nastavení rozsahu arpeggia v oktávách. Vybrané arpeggio bude zahráno ve zvoleném počtu oktáv. - Amount multiplicator - + + CYCLE + CYKL - - - QWidget - Name: - Název: + + Cycle notes: + Počet not v cyklu: - Maker: - Tvůrce: + + note(s) + nota(y) - Copyright: - Autorská práva: + + Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. + Skočí přes n kroků v arpeggiu a pokud přesáhne rozsah not, zacyklí se zde. Je-li je celkový rozsah not rovnoměrně dělitelný počtem kroků nad rozdah, uvíznete v kratším arpeggiu nebo dokonce na jedné notě. - Requires Real Time: - Vyžaduje běh v reálném čase: + + SKIP + VYNECH - Yes - Ano + + Skip rate: + Míra vynechávání: - No - Ne + + + + % + % - Real Time Capable: - Schopnost běhu v reálném čase: + + The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. + Funkce vynechávání způsobí, že arpeggiator náhodně pozastaví některý krok. Od počáteční pozice, kde nemá žádný efekt, se po směru hodinových ručiček efekt stupňuje až po maximální nastavení, kdy vynechá vše. - In Place Broken: - Na místě poškozeného: + + MISS + MÍJ - Channels In: - Vstupní kanály: + + Miss rate: + Míra míjení: - Channels Out: - Výstupní kanály: + + The miss function will make the arpeggiator miss the intended note. + Funkce míjení způsobí, že arpeggiator netrefí dotyčnou notu. - File: - Soubor: + + TIME + TRVÁNÍ - File: %1 - Soubor: %1 + + Arpeggio time: + Trvání arpeggia: - - - ReverbSCControlDialog - Input - Vstup + + ms + ms - Size - Velikost + + Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. + Tento otočný ovladač nastavuje trvání arpeggia v milisekundách. Trvání arpeggia udává, jak dlouho bude každý tón arpeggia přehráván. - Size: - Velikost: + + GATE + BRÁNA - Color - Barva + + Arpeggio gate: + Brána arpeggia: - Color: - Barva: + + Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. + Tento otočný ovladač nastavuje bránu arpeggia. Brána arpeggia určuje procento délky jednotlivých arpeggiových tónů, které budou zahrány. Pomocí brány arpeggia můžete udělat skvělé staccatové arpeggio. - Output - Výstup + + Chord: + Akord: - Input gain: - Zesílení vstupu: + + Direction: + Směr: - Output gain: - Zesílení výstupu: + + Mode: + Styl: - ReverbSCControls + InstrumentFunctionNoteStacking - Size - Velikost + + octave + Oktáva - Color - Barva + + + Major + Dur - Input gain - Zesílení vstupu + + Majb5 + Maj5b - Output gain - Zesílení výstupu + + minor + Moll - - - SpectrumAnalyzerControlDialog - Linear spectrum - Lineární spektrum + + minb5 + m5b - Linear Y axis - Lineární osa Y + + sus2 + sus2 - - - SpectrumAnalyzerControls - Linear spectrum - Lineární spektrum + + sus4 + sus4 - Linear Y axis - Lineární osa Y + + aug + aug - Channel mode - Režim kanálu + + augsus4 + aug sus4 - - - TrackContainer - Cancel - Zrušit + + tri + tri - Please wait... - Prosím čekejte... + + 6 + 6 - Importing MIDI-file... - Importuji MIDI soubor... + + 6sus4 + 6 sus4 - - - TripleOscillatorView - Synchronize oscillator 1 with oscillator 2 - Synchronizovat oscilátor 1 oscilátorem 2 + + 6add9 + 6 add9 - Synchronize oscillator 2 with oscillator 3 - Synchronizovat oscilátor 2 oscilátorem 3 + + m6 + m6 - Osc %1 volume: - Osc %1 hlasitost: + + m6add9 + m6 add9 - Osc %1 panning: - Osc %1 panoráma: + + 7 + 7 - Osc %1 coarse detuning: - Osc %1 hrubé rozladění: + + 7sus4 + 7 sus4 - semitones - půltónů + + 7#5 + 7/5# - Osc %1 fine detuning left: - Osc %1 jemné rozladění vlevo: + + 7b5 + 7/5b - cents - centů + + 7#9 + 7/9# - Osc %1 fine detuning right: - Osc %1 jemné rozladění vpravo: + + 7b9 + 7/9b - Osc %1 phase-offset: - Osc %1 posun fáze: + + 7#5#9 + 7/5#/9# - degrees - stupňů + + 7#5b9 + 7/5#/9b - Osc %1 stereo phase-detuning: - Osc %1 rozladění stereo fáze: + + 7b5b9 + 7/5b/9b - Modulate phase of oscillator 1 by oscillator 2 - + + 7add11 + 7 add11 - Modulate amplitude of oscillator 1 by oscillator 2 - + + 7add13 + 7 add13 - Mix output of oscillators 1 & 2 - + + 7#11 + 7/11# - Modulate frequency of oscillator 1 by oscillator 2 - + + Maj7 + Maj7 - Modulate phase of oscillator 2 by oscillator 3 - + + Maj7b5 + Maj7/5b - Modulate amplitude of oscillator 2 by oscillator 3 - + + Maj7#5 + Maj7/5# - Mix output of oscillators 2 & 3 - + + Maj7#11 + Maj7/11# - Modulate frequency of oscillator 2 by oscillator 3 - + + Maj7add13 + Maj7 add13 - Sine wave - Sinusová vlna + + m7 + m7 - Triangle wave - Trojúhelníková vlna + + m7b5 + m7/5b - Saw wave - Pilovitá vlna + + m7b9 + m7/9b - Square wave - Pravoúhlá vlna + + m7add11 + m7 add11 - Moog-like saw wave - + + m7add13 + m7 add13 - Exponential wave - Exponenciální vlna + + m-Maj7 + m-Maj7 - White noise - Bílý šum + + m-Maj7add11 + m-Maj7 add11 - User-defined wave - + + m-Maj7add13 + m-Maj7 add13 - - - VestigeInstrumentView - Show/hide GUI - Zobrazit/Skrýt grafické rozhraní + + 9 + 9 - Turn off all notes - Vypnout všechny noty + + 9sus4 + 9 sus4 - DLL-files (*.dll) - DLL soubory (*.dll) + + add9 + add9 - EXE-files (*.exe) - EXE soubory (*.exe) + + 9#5 + 9/5# - Previous (-) - Předchozí (-) + + 9b5 + 9/5b - Save preset - Uložit předvolbu + + 9#11 + 9/11# - Next (+) - Další (+) + + 9b13 + 9/13b - Preset - Předvolba + + Maj9 + Maj9 - by - od + + Maj9sus4 + Maj9 sus4 - - VST plugin control - – ovládání VST pluginu + + Maj9#5 + Maj9/5# - Open VST plugin - + + Maj9#11 + Maj9/11# - Control VST plugin from LMMS host - + + m9 + m9 - Open VST plugin preset - + + madd9 + m add9 - No VST plugin loaded - + + m9b5 + m9/5b - - - VstEffectControlDialog - Show/hide - Ukázat/Skrýt + + m9-Maj7 + m9-Maj7 - Previous (-) - Předchozí (-) + + 11 + 11 - Next (+) - Další (+) + + 11b9 + 11/9b - Save preset - Uložit předvolbu + + Maj11 + Maj11 - Effect by: - Efekt od: + + m11 + m11 - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + + m-Maj11 + m-Maj11 - Control VST plugin from LMMS host - + + 13 + 13 - Open VST plugin preset - - - - - VstPlugin - - Loading plugin - Načítám plugin + + 13#9 + 13/9# - Open Preset - Otevřít předvolbu + + 13b9 + 13/9b - Vst Plugin Preset (*.fxp *.fxb) - Předvolba VST pluginu (*.fxp *.fxb) + + 13b5b9 + 13/9b/5b - : default - : výchozí + + Maj13 + Maj13 - " - " + + m13 + m13 - ' - ' + + m-Maj13 + m-Maj13 - Save Preset - Uložit předvolbu + + Harmonic minor + Mollová harmonická - .fxp - .fxp + + Melodic minor + Mollová melodická - .FXP - .FXP + + Whole tone + Celotónová stupnice - .FXB - .FXB + + Diminished + Zmenšená - .fxb - .fxb + + Major pentatonic + Durová pentatonika - Please wait while loading VST plugin... - Počkejte prosím, než se načte VST plugin... + + Minor pentatonic + Mollová pentatonika - The VST plugin %1 could not be loaded. - VST plugin %1 nelze načíst. + + Jap in sen + Japonská (in sen) stupnice - - - WatsynInstrument - Volume A1 - Hlasitost A1 + + Major bebop + Durová bebopová - Volume A2 - Hlasitost A2 + + Dominant bebop + Dominantní bebopová - Volume B1 - Hlasitost B1 + + Blues + Bluesová stupnice - Volume B2 - Hlasitost B2 + + Arabic + Arabská - Panning A1 - Panoráma A1 + + Enigmatic + Enigmatická - Panning A2 - Panoráma A2 + + Neopolitan + Neapolská - Panning B1 - Panoráma B1 + + Neopolitan minor + Mollová neapolská - Panning B2 - Panoráma B2 + + Hungarian minor + Mollová maďarská - Freq. multiplier A1 - Násobič frekv. A1 + + Dorian + Dórská - Freq. multiplier A2 - Násobič frekv. A2 + + Phrygian + Frygický - Freq. multiplier B1 - Násobič frekv. B1 + + Lydian + Lydická - Freq. multiplier B2 - Násobič frekv. B2 + + Mixolydian + Mixolydická - Left detune A1 - Rozladění vlevo A1 + + Aeolian + Aiolská - Left detune A2 - Rozladění vlevo A2 + + Locrian + Lokrická - Left detune B1 - Rozladění vlevo B1 + + Minor + Moll - Left detune B2 - Rozladění vlevo B2 + + Chromatic + Chromatická - Right detune A1 - Rozladění vpravo A1 + + Half-Whole Diminished + Zmenšená (půltón–celý tón) - Right detune A2 - Rozladění vpravo A2 + + 5 + 5 - Right detune B1 - Rozladění vpravo B1 + + Phrygian dominant + Frygická dominanta - Right detune B2 - Rozladění vpravo B2 + + Persian + Perská - A-B Mix - Směšovač A-B + + Chords + Akordy - A-B Mix envelope amount - Množství obálky směšovače A-B + + Chord type + Typ akordu - A-B Mix envelope attack - Náběh obálky směšovače A-B + + Chord range + Rozsah akordu + + + InstrumentFunctionNoteStackingView - A-B Mix envelope hold - Množství držení směšovače A-B + + STACKING + VRSTVENÍ - A-B Mix envelope decay - Útlum obálky směšovače A-B + + Chord: + Akord: - A1-B2 Crosstalk - Přeslech A1-B2 + + RANGE + ROZSAH - A2-A1 modulation - Modulace A1-B2 + + Chord range: + Rozsah akordu: - B2-B1 modulation - Modulace B2-B1 + + octave(s) + oktáva(y) - Selected graph - Zvolený graf + + Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. + Tento otočný ovladač nastavuje rozsah akordů v oktávách. Vybraný akord bude zahrán ve zvoleném počtu oktáv. - WatsynView - - Select oscillator A1 - Vybrat oscilátor A1 - - - Select oscillator A2 - Vybrat oscilátor A2 - + InstrumentMidiIOView - Select oscillator B1 - Vybrat oscilátor B1 + + ENABLE MIDI INPUT + POVOLIT MIDI VSTUP - Select oscillator B2 - Vybrat oscilátor B2 + + + CHANNEL + KANÁL - Mix output of A2 to A1 - Přimíchat výstup A1 do A2 + + + VELOCITY + DYNAM - Mix output of B2 to B1 - Přimíchat výstup B1 do B2 + + ENABLE MIDI OUTPUT + POVOLIT MIDI VÝSTUP - Draw your own waveform here by dragging your mouse on this graph. - Kreslení vlastní křivky tahem myši na tomto grafu. + + PROGRAM + PROGRAM - Load waveform - Načíst vlnu + + NOTE + NOTA - Phase left - Fáze vlevo + + MIDI devices to receive MIDI events from + MIDI zařízení pro přijímání MIDI událostí - Phase right - Fáze vpravo + + MIDI devices to send MIDI events to + MIDI zařízení pro odesílání MIDI událostí - Normalize - Normalizovat + + CUSTOM BASE VELOCITY + VLASTNÍ VÝCHOZÍ DYNAMIKA - Invert - Převrátit + + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity + Udává výchozí úroveň dynamiky pro MIDI nástroje při 100 % dynamiky tónu - Smooth - Uhladit + + BASE VELOCITY + VÝCHOZÍ DYNAMIKA + + + InstrumentMiscView - Sine wave - Sinusová vlna + + MASTER PITCH + TRANSPOZICE - Triangle wave - Trojúhelníková vlna + + Enables the use of Master Pitch + Umožní použití transpozice + + + InstrumentSoundShaping - Square wave - Pravoúhlá vlna + + VOLUME + HLASITOST + Volume Hlasitost - Panning - Panoráma - - - Freq. multiplier - Násobič frekv. - - - Left detune - Rozladění vlevo + + CUTOFF + SEŘÍZNUTÍ - cents - centů + + + Cutoff frequency + Frekvence oříznutí - Right detune - Rozladění vpravo + + RESO + REZONANCE - A-B Mix - Směšovač A-B + + Resonance + Rezonance - Mix envelope amount - Množství obálky směšovače + + Envelopes/LFOs + Obálky/LFO - Mix envelope attack - Náběh obálky směšovače + + Filter type + Typ filtru - Mix envelope hold - Držení obálky směšovače + + Q/Resonance + Q/rezonance - Mix envelope decay - Útlum obálky směšovače + + LowPass + Dolní propust - Crosstalk - Přeslech + + HiPass + Horní propust - Modulate amplitude of A1 by output of A2 - + + BandPass csg + Pásmová propust csg - Ring modulate A1 and A2 - + + BandPass czpg + Pásmová propust czpg - Modulate phase of A1 by output of A2 - + + Notch + Pásmová zádrž - Modulate amplitude of B1 by output of B2 - + + Allpass + Všepásmový filtr - Ring modulate B1 and B2 - + + Moog + Moogův filtr - Modulate phase of B1 by output of B2 - + + 2x LowPass + 2x dolní propust - Load a waveform from a sample file - + + RC LowPass 12dB + RC dolní propust 12dB - Shift phase by -15 degrees - + + RC BandPass 12dB + RC pásmová propust 12dB - Shift phase by +15 degrees - + + RC HighPass 12dB + RC horní propust 12dB - Saw wave - Pilovitá vlna + + RC LowPass 24dB + RC dolní propust 24dB - - - Xpressive - Selected graph - Zvolený graf + + RC BandPass 24dB + RC pásmová propust 24dB - A1 - A1 + + RC HighPass 24dB + RC horní propust 24dB - A2 - A2 + + Vocal Formant Filter + Vokální formantový filtr - A3 - A3 + + 2x Moog + 2x Moogův filtr - W1 smoothing - W1 vyhlazování + + SV LowPass + SV dolní propust - W2 smoothing - W2 vyhlazování + + SV BandPass + SV pásmová propust - W3 smoothing - W3 vyhlazování + + SV HighPass + SV horní propust - Panning 1 - + + SV Notch + SV pásmová zádrž - Panning 2 - + + Fast Formant + Rychlý formantový filtr - Rel trans - + + Tripole + Třípólový filtr - XpressiveView + InstrumentSoundShapingView - Draw your own waveform here by dragging your mouse on this graph. - Kreslení vlastní křivky tahem myši na tomto grafu. + + TARGET + CÍL: - Select oscillator W1 - Vybrat oscilátor W1 + + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + Tato stránka obsahuje obálky. Ty jsou velmi důležité pro úpravu zvuku a obvykle také i nezbytné pro rozdílovou (subtraktivní) syntézu. Pokud máte například obálku hlasitosti, můžete nastavit, kdy má mít zvuk jakou sílu. Pokud chcete vytvořit něco jako smyčce, váš zvuk by měl mít velmi měkké nasazení i ukončení tónu. Toho dosáhneme nastavením dlouhého času náběhu i uvolnění. Totéž se týká ostatních druhů obálek, jako je obálka panorámatu, frekvence odříznutí pro použití u filtrů apod. Prostě si s tím můžete vyhrát dle libosti! Můžete vytvořit opravdu úžasné zvuky třeba jen z pilovité vlny pomocí vhodných obálek...! - Select oscillator W2 - Vybrat oscilátor W2 + + FILTER + FILTR - Select oscillator W3 - Vybrat oscilátor W3 + + Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. + Zde si můžete vybrat z vestavěných filtrů, které chcete použít pro tuto stopu nástroje. Filtry jsou velmi důležité pro změnu charakteristiky zvuku. - Select output O1 - + + FREQ + FREKV - Select output O2 - + + cutoff frequency: + Frekvence oříznutí: - Open help window - Otevřít okno nápovědy + + Hz + Hz - Sine wave - Sinusová vlna + + Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... + Tento otočný ovladač nastavuje frekvenci odříznutí pro vybraný filtr. Frekvence odříznutí určuje frekvenci pro odříznutí signálu filtrem. Například filtr typu dolní propust (low-pass) odstřihne všechny frekvence, které jsou vyšší než frekvence odříznutí. Filtr typu horní propust (high-pass) odstřihne všechny frekvence, které jsou nižší než frekvence odříznutí atd... - Moog-saw wave - + + RESO + REZO - Exponential wave - Exponenciální vlna + + Resonance: + Rezonance: - Saw wave - Pilovitá vlna + + Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. + Tento otočný ovladač nastavuje Q/rezonanci pro vybraný filtr. Q/rezonance určuje, jak hodně filtr zesílí frekvence poblíž frekvence oříznutí. - User-defined wave - + + Envelopes, LFOs and filters are not supported by the current instrument. + Obálky, LFO a filtry nejsou podporovány stávajícím nástrojem. + + + InstrumentTrack - Triangle wave - Trojúhelníková vlna + + With this knob you can set the volume of the opened channel. + Tímto otočným ovladačem můžete nastavit hlasitost otevřeného kanálu. - Square wave - Pravoúhlá vlna + + + unnamed_track + nepojmenovaná_stopa - White noise - Bílý šum + + Base note + Základní nota - WaveInterpolate - Interpolace vlnění + + Volume + Hlasitost - ExpressionValid - Platnost výrazu + + Panning + Panoráma - General purpose 1: - Celkový účel 1: + + Pitch + Ladění - General purpose 2: - Celkový účel 2: + + Pitch range + Výškový rozsah - General purpose 3: - Celkový účel 3: + + FX channel + Efektový kanál - O1 panning: - O1 vyvážení: + + Master Pitch + Transpozice - O2 panning: - O2 vyvážení: + + + Default preset + Výchozí předvolba + + + InstrumentTrackView - Release transition: - Přechod mezi uvolněním: + + Volume + Hlasitost - Smoothness - Hladkost + + Volume: + Hlasitost: - - - ZynAddSubFxInstrument - Portamento - Portamento + + VOL + HLA - Bandwidth - Šířka pásma + + Panning + Panoráma - Filter frequency - + + Panning: + Panoráma: - Filter resonance - + + PAN + PAN - FM gain - + + MIDI + MIDI - Resonance center frequency - + + Input + Vstup - Resonance bandwidth - + + Output + Výstup - Forward MIDI control change events - + + FX %1: %2 + Efekt %1: %2 - ZynAddSubFxView + InstrumentTrackWindow - Show GUI - Ukázar grafické rozhraní + + GENERAL SETTINGS + HLAVNÍ NASTAVENÍ - Portamento: - Portamento: + + Use these controls to view and edit the next/previous track in the song editor. + Použije tyto ovládací prvky pro zobrazení a editaci další/předchozí stopy v editoru skladby. - PORT - PORT + + Instrument volume + Hlasitost nástroje - FREQ - FREKV + + Volume: + Hlasitost: - RES - REZ + + VOL + HLA - Bandwidth: - Šířka pásma: + + Panning + Panoráma - BW - ŠP - + + Panning: + Panoráma: + - FM GAIN - ZISK FM + + PAN + PAN - Resonance center frequency: - Střední frekvence rezonance: + + Pitch + Ladění - RES CF - SF REZ + + Pitch: + Ladění: - Resonance bandwidth: - Šířka pásma rezonance: + + cents + centů - RES BW - ŠP REZ + + PITCH + LADĚNÍ - Filter frequency: - + + Pitch range (semitones) + Rozsah výšky (v půltónech) - Filter resonance: - + + RANGE + ROZSAH - FM gain: - + + FX channel + Efektový kanál - Forward MIDI control changes - + + FX + EFEKT - - - audioFileProcessor - Amplify - Zesílení + + Save current instrument track settings in a preset file + Uložit aktuální nastavení nástrojové stopy do souboru předvoleb - Start of sample - Začátek samplu + + Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. + Klepněte sem, chcete-li uložit aktuální nastavení nástrojové stopy do souboru předvoleb. Později můžete nahrát tuto předvolbu poklepáním na prohlížeč předvoleb. - End of sample - Konec samplu + + SAVE + ULOŽIT - Reverse sample - Přehrávat pozpátku + + Envelope, filter & LFO + Obálka, filtr a LFO - Stutter - Pokračování v přehrávání samplu při změně noty + + Chord stacking & arpeggio + Vrstvení akordů a arpeggio - Loopback point - Začátek smyčky + + Effects + Efekty - Loop mode - Režim smyčky + + MIDI settings + MIDI nastavení - Interpolation mode - Režim interpolace + + Miscellaneous + Různé - None - Žádný + + Save preset + Uložit předvolbu - Linear - Lineární + + XML preset file (*.xpf) + XML soubor předvoleb (*.xpf) - Sinc - Sinusový + + Plugin + Plugin + + + + Knob + + + Set linear + Lineární zobrazení - Sample not found: %1 - Vzorek nenalezen: %1 + + Set logarithmic + Logaritmické zobrazení + + + + Please enter a new value between -96.0 dBFS and 6.0 dBFS: + Zadejte prosím novou hodnotu mezi -96.0 dBFS a 6.0 dBFS: + + + + Please enter a new value between %1 and %2: + Vložte prosím novou hodnotu mezi %1 a %2: - bitInvader + LadspaControl - Sample length - + + Link channels + Propojit kanály - bitInvaderView + LadspaControlDialog - Sine wave - Sinusová vlna + + Link Channels + Propojit kanály - Triangle wave - Trojúhelníková vlna + + Channel + Kanál + + + LadspaControlView - Saw wave - Pilovitá vlna + + Link channels + Propojit kanály - Square wave - Pravoúhlá vlna + + Value: + Hodnota: - Interpolation - Interpolovat + + Sorry, no help available. + Promiňte, nápověda není k dispozici. + + + LadspaEffect - Normalize - Normalizovat + + Unknown LADSPA plugin %1 requested. + Je požadován neznámý LADSPA plugin %1. + + + LcdSpinBox - Draw your own waveform here by dragging your mouse on this graph. - Kreslení vlastní křivky tahem myši na tomto grafu. + + Please enter a new value between %1 and %2: + Vložte prosím novou hodnotu mezi %1 a %2: + + + LeftRightNav - Sample length - + + + + Previous + Předchozí - White noise - Bílý šum + + + + Next + Další - User-defined wave - + + Previous (%1) + Předchozí (%1) - Smooth waveform - + + Next (%1) + Další (%1) - dynProcControlDialog - - INPUT - VSTUP - + LfoController - Input gain: - Zesílení vstupu: + + LFO Controller + Ovladač LFO - OUTPUT - VÝSTUP + + Base value + Základní hodnota - Output gain: - Zesílení výstupu: + + Oscillator speed + Rychlost oscilátoru - ATTACK - NÁBĚH + + Oscillator amount + Míra oscilátoru - Peak attack time: - Délka náběhu špičky: + + Oscillator phase + Fáze oscilátoru - RELEASE - UVOLNĚNÍ + + Oscillator waveform + Vlna oscilátoru - Peak release time: - Délka uvolnění špičky: + + Frequency Multiplier + Frekvenční multiplikátor + + + LfoControllerDialog - Process based on the maximum of both stereo channels - Zpracování vycházející z maxima obou stereo kanálů + + LFO + LFO - Process based on the average of both stereo channels - Zpracování vycházející z průměru obou stereo kanálů + + LFO Controller + Ovladač LFO - Process each stereo channel independently - Zpracování každého stereo kanálu zvlášť + + BASE + ZÁKL - Reset wavegraph - + + Base amount: + Základní míra: - Smooth wavegraph - + + todo + udělat - Increase wavegraph amplitude by 1 dB - + + SPD + RYCH - Decrease wavegraph amplitude by 1 dB - + + LFO-speed: + Rychlost LFO: - Stereo mode: maximum - + + Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. + Tento otočný ovladač nastavuje rychlost LFO. Zvýšením hodnoty se zrychlí kmitání LFO a průběh efektu. - Stereo mode: average - + + AMNT + MNOŽ - Stereo mode: unlinked - + + Modulation amount: + Hloubka modulace: - - - dynProcControls - Input gain - Zesílení vstupu + + Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. + Tento otočný ovladač nastavuje množství modulace LFO. Čím vyšší bude tato hodnota, tím více budou propojené parametry (např. hlasitost nebo frekvence odříznutí) ovlivněny LFO. - Output gain - Zesílení výstupu + + PHS + FÁZ - Attack time - Doba náběhu + + Phase offset: + Posun fáze: - Release time - Délka uvolnění + + degrees + stupňů - Stereo mode - Režim sterea + + With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + Tímto otočným ovladačem můžete nastavit fázový posun LFO. To znamená, že můžete posunout bod, ve kterém oscilátor začne kmitat. Například pokud máte sinusovou vlnu s fázovým posunem 180 stupňů, vlna půjde nejdříve dolů. Totéž se stane u vlny pravoúhlé. - - - kickerInstrument - Start frequency - Počáteční frekvence + + Click here for a sine-wave. + Klepněte sem pro sinusovou vlnu. - End frequency - Konečná frekvence + + Click here for a triangle-wave. + Klepněte sem pro trojúhelníkovou vlnu. - Gain - Zisk + + Click here for a saw-wave. + Klepněte sem pro pilovitou vlnu. - Length - Délka + + Click here for a square-wave. + Klepněte sem pro pravoúhlou vlnu. - Noise - Šum + + Click here for a moog saw-wave. + Klepněte sem pro pilovitou vlnu typu Moog. - Click - Klik + + Click here for an exponential wave. + Klepněte sem pro exponenciální vlnu. - Start from note - Začít od noty + + Click here for white-noise. + Klepněte sem pro bílý šum. - End to note - Skončit na notě + + Click here for a user-defined shape. +Double click to pick a file. + Klepněte sem pro uživatelem definovaný tvar. +Poklepejte pro výběr souboru. + + + LmmsCore - Start distortion - + + Generating wavetables + Generuji vlny - End distortion - + + Initializing data structures + Inicializuji datové struktury - Envelope slope - + + Opening audio and midi devices + Spouštím zvuková a MIDI zařízení - Frequency slope - + + Launching mixer threads + Spouštím vlákna mixážního panelu - kickerInstrumentView + MainWindow - Start frequency: - Počáteční frekvence: + + Configuration file + Soubor nastavení - End frequency: - Konečná frekvence: + + Error while parsing configuration file at line %1:%2: %3 + Chyba při kontrole konfiguračního souboru na řádku %1:%2: %3 - Gain: - Zisk: + + Could not open file + Nemohu otevřít soubor - Click: - Klik: + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Nelze otevřít soubor %1 pro zápis. +Ujistěte se prosím, zda máte povolen zápis do souboru a do složky obsahující soubor a zkuste znovu! - Noise: - Šum: + + Project recovery + Obnovení projektu - Frequency slope: - + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + Je k dispozici soubor pro obnovu. Zdá se, že poslední práce nebyla správně ukončena nebo že je již spuštěna jiná instance LMMS. Chcete obnovit tuto verzi projektu? - Envelope length: - + + + + Recover + Obnovit - Envelope slope: - + + Recover the file. Please don't run multiple instances of LMMS when you do this. + Obnovit soubor. Před dokončením prosím nespouštějte další instance LMMS. - Start distortion: - + + + + Discard + Zrušit - End distortion: - + + Launch a default session and delete the restored files. This is not reversible. + Spustit LMMS do výchozího stavu a smazat obnovené soubory. Tento krok je nevratný. - - - ladspaBrowserView - Available Effects - Dostupné efekty + + Version %1 + Verze %1 - Unavailable Effects - Nedostupné efekty + + Preparing plugin browser + Připravuji prohlížeč pluginů - Instruments - Nástroje + + Preparing file browsers + Připravuji prohlížeč souborů - Analysis Tools - Analyzační nástroje + + My Projects + Moje projekty - Don't know - Neznámé + + My Samples + Moje samply - Type: - Typ: + + My Presets + Moje předvolby - - - ladspaDescription - Plugins - Pluginy + + My Home + Domů - Description - Popis + + Root directory + Kořenový adresář - - - ladspaPortDialog - Ports - Porty + + Volumes + Hlasitosti - Name - Název + + My Computer + Můj počítač - Rate - Druh + + Loading background artwork + Načítám grafiku prostředí - Direction - Směr + + &File + &Soubor - Type - Typ + + &New + &Nový - Min < Default < Max - Min < Výchozí < Max + + New from template + Nový z šablony - Logarithmic - Logaritmický + + &Open... + &Otevřít... - SR Dependent - SR závislý + + &Recently Opened Projects + &Naposledy otevřené projekty - Audio - Zvuk + + &Save + &Uložit - Control - Ovládání + + Save &As... + Uložit &jako... - Input - Vstup + + Save as New &Version + Uložit jako novou &verzi - Output - Výstup + + Save as default template + Uložit jako výchozí šablonu - Toggled - Zapnuto + + Import... + Importovat... - Integer - Celočíselný + + E&xport... + E&xportovat... - Float - S plovoucí čárkou + + E&xport Tracks... + E&xportovat stopy... - Yes - Ano + + Export &MIDI... + &Exportovat MIDI... - - - lb302Synth - VCF Cutoff Frequency - VCF frekvence vypnutí + + &Quit + &Ukončit - VCF Resonance - VCF rezonance + + &Edit + Úpr&avy - VCF Envelope Mod - VCF modulace obálky + + Undo + Zpět - VCF Envelope Decay - VCF útlum obálky + + Redo + Znovu - Distortion - Zkreslení + + Settings + Nastavení + + &View + &Zobrazení + + + + &Tools + &Nástroje + + + + &Help + &Nápověda + + + + Online Help + Nápověda online + + + + Help + Nápověda + + + + What's This? + Co je to? + + + + About + O LMMS + + + + Create new project + Vytvořit nový projekt + + + + Create new project from template + Vytvořit nový projekt ze šablony + + + + Open existing project + Otevřít existující projekt + + + + Recently opened projects + Naposledy otevřené projekty + + + + Save current project + Uložit aktuální projekt + + + + Export current project + Exportovat aktuální projekt + + + + What's this? + Co je to? + + + + Toggle metronome + Zapnout/Vypnout metronom + + + + Show/hide Song-Editor + Zobrazit/Skrýt editor skladby + + + + By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. + Stisknutím tohoto tlačítka zobrazíte nebo skryjete Editor skladby. S jeho pomocí můžete upravovat playlist skladby a určit, kdy a která stopa má být přehrána. Můžete také vkládat a přesunovat samply (např. rapové) přímo do playlistu. + + + + Show/hide Beat+Bassline Editor + Zobrazit/Skrýt editor bicích/basů + + + + By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. + Stisknutím tohoto tlačítka zobrazíte nebo skryjete editor bicích/basů. Tento editor je nezbytný pro tvorbu beatů, otevírání, přidávání či odebírání kanálů a dále pro vyjímání, kopírování a vkládání beatů, bicích/basových záznamů apod. + + + + Show/hide Piano-Roll + Zobrazit/Skrýt Piano roll + + + + Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. + Klepněte sem, pokud chcete ukázat nebo skrýt Piano roll. S pomocí Piano rollu můžete jednoduchým způsobem upravovat melodie. + + + + Show/hide Automation Editor + Zobrazit/Skrýt Editor automatizace + + + + Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. + Klepněte sem, pokud chcete ukázat nebo skrýt Editor automatizace. S pomocí Editoru automatizace můžete jednoduchým způsobem upravovat proměnlivý průběh hodnot. + + + + Show/hide FX Mixer + Zobrazit/Skrýt efektový mixážní panel + + + + Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. + Klepněte sem, pokud chcete ukázat nebo skrýt efektový (FX) mixážní panel. Efektový mixážní panel je velmi výkonný nástroj pro správu efektů ve vaší skladbě. Efekty můžete vkládat do různých efektových kanálů. + + + + Show/hide project notes + Zobrazit/Skrýt poznámky k projektu + + + + Click here to show or hide the project notes window. In this window you can put down your project notes. + Klepněte sem, pokud chcete ukázat nebo schovat okno pro poznámky. V tomto okně lze vkládat vaše poznámky k projektu. + + + + Show/hide controller rack + Zobrazit/Skrýt panel ovladačů + + + + Untitled + Nepojmenovaný + + + + Recover session. Please save your work! + Obnovit projekt. Uložte prosím svou práci! + + + + LMMS %1 + LMMS %1 + + + + Recovered project not saved + Obnovený projekt není uložen + + + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + Tento projekt byl obnoven z minulého spuštění LMMS. Zatím není uložen a pokud tak neučiníte, práce bude ztracena. Chcete jej nyní uložit? + + + + Project not saved + Projekt není uložen + + + + The current project was modified since last saving. Do you want to save it now? + Aktuální projekt byl od posledního uložení změněn. Chcete jej nyní uložit? + + + + Open Project + Otevřít projekt + + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + + Save Project + Uložit projekt + + + + LMMS Project + Projekt LMMS + + + + LMMS Project Template + Šablona projektu LMMS + + + + Save project template + Uložit šablonu projektu + + + + Overwrite default template? + Přepsat výchozí šablonu? + + + + This will overwrite your current default template. + Tímto se přepíše vaše nynější výchozí šablona. + + + + Help not available + Nápověda není dostupná + + + + Currently there's no help available in LMMS. +Please visit http://lmms.sf.net/wiki for documentation on LMMS. + V současnosti není v LMMS nápověda dostupná. +Navštivte prosím stránku s dokumentací k LMMS na adrese http://lmms.sf.net/wiki. + + + + Song Editor + Editor skladby + + + + Beat+Bassline Editor + Editor bicích/basů + + + + Piano Roll + Piano roll + + + + Automation Editor + Editor automatizace + + + + FX Mixer + Efektový mixážní panel + + + + Project Notes + Poznámky k projektu + + + + Controller Rack + Panel ovladačů + + + + Volume as dBFS + Hlasitost v dBFS + + + + Smooth scroll + Plynulé posouvání + + + + Enable note labels in piano roll + Povolit názvy tónů v Piano rollu + + + + MeterDialog + + + + Meter Numerator + Počet dob v taktu + + + + + Meter Denominator + Délka doby v taktu + + + + TIME SIG + METRUM + + + + MeterModel + + + Numerator + Počet dob + + + + Denominator + Délka doby + + + + MidiController + + + MIDI Controller + MIDI ovladač + + + + unnamed_midi_controller + nepojmenovaný_midi_ovladač + + + + MidiImport + + + + Setup incomplete + Nastavení není dokončeno + + + + You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. + Nemáte nastaven výchozí soundfont v dialogovém okně (Edit-> Nastavení). Z tohoto důvodu nebude po importu MIDI souboru přehráván žádný zvuk. Stáhněte si nějaký General MIDI soundfont, zadejte jej v dialogovém okně nastavení a zkuste to znovu. + + + + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. + Nelze zkompilovat LMMS s podporou přehrávače SoundFont2, který je použitý k přidání výchozího zvuku do importovaných MIDI souborů. Proto nebude po importování tohoto MIDI souboru přehráván žádný zvuk. + + + + Track + Stopa + + + + MidiJack + + + JACK server down + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) + JACK server zhavaroval + + + + The JACK server seems to be shuted down. + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) + Zdá se, že JACK server zhavaroval. + + + + MidiPort + + + Input channel + Vstupní kanál + + + + Output channel + Výstupní kanál + + + + Input controller + Vstupní ovladač + + + + Output controller + Výstupní ovladač + + + + Fixed input velocity + Pevná vstupní dynamika + + + + Fixed output velocity + Pevná výstupní dynamika + + + + Fixed output note + Pevná výstupní nota + + + + Output MIDI program + Výstupní MIDI program + + + + Base velocity + Výchozí dynamika + + + + Receive MIDI-events + Přijímat MIDI události + + + + Send MIDI-events + Posílat MIDI události + + + + MidiSetupWidget + + + DEVICE + ZAŘÍZENÍ + + + + MonstroInstrument + + + Osc 1 Volume + Osc 1 hlasitost + + + + Osc 1 Panning + Osc 1 panoráma + + + + Osc 1 Coarse detune + Osc 1 hrubé rozladění + + + + Osc 1 Fine detune left + Osc 1 jemné rozladění vlevo + + + + Osc 1 Fine detune right + Osc 1 jemné rozladění vpravo + + + + Osc 1 Stereo phase offset + Osc 1 posun stereo fáze + + + + Osc 1 Pulse width + Osc 1 délka pulzu + + + + Osc 1 Sync send on rise + Osc 1 synchronizace při nárůstu + + + + Osc 1 Sync send on fall + Osc 1 synchronizace při poklesu + + + + Osc 2 Volume + Osc 2 hlasitost + + + + Osc 2 Panning + Osc 2 panoráma + + + + Osc 2 Coarse detune + Osc 2 hrubé rozladění + + + + Osc 2 Fine detune left + Osc 2 jemné rozladění vlevo + + + + Osc 2 Fine detune right + Osc 2 jemné rozladění vpravo + + + + Osc 2 Stereo phase offset + Osc 2 posun stereo fáze + + + + Osc 2 Waveform + Osc 2 vlna + + + + Osc 2 Sync Hard + Osc 2 pevná synchronizace + + + + Osc 2 Sync Reverse + Osc 2 reverzní synchronizace + + + + Osc 3 Volume + Osc 3 hlasitost + + + + Osc 3 Panning + Osc 3 panoráma + + + + Osc 3 Coarse detune + Osc 3 hrubé rozladění + + + + Osc 3 Stereo phase offset + Osc 3 posun stereo fáze + + + + Osc 3 Sub-oscillator mix + Osc 3 smíchání se sub-oscilátorem + + + + Osc 3 Waveform 1 + Osc 3 vlna 1 + + + + Osc 3 Waveform 2 + Osc 3 vlna 2 + + + + Osc 3 Sync Hard + Osc 3 pevná synchronizace + + + + Osc 3 Sync Reverse + Osc 3 reverzní synchronizace + + + + LFO 1 Waveform + LFO 1 vlna + + + + LFO 1 Attack + LFO 1 náběh + + + + LFO 1 Rate + LFO 1 rychlost + + + + LFO 1 Phase + LFO 1 fáze + + + + LFO 2 Waveform + LFO 2 vlna + + + + LFO 2 Attack + LFO 2 náběh + + + + LFO 2 Rate + LFO 2 rychlost + + + + LFO 2 Phase + LFO 2 fáze + + + + Env 1 Pre-delay + Obálka 1 předzpoždění + + + + Env 1 Attack + Obálka 1 náběh + + + + Env 1 Hold + Obálka 1 držení + + + + Env 1 Decay + Obálka 1 útlum + + + + Env 1 Sustain + Obálka 1 vydržení + + + + Env 1 Release + Obálka 1 uvolnění + + + + Env 1 Slope + Obálka 1 sklon + + + + Env 2 Pre-delay + Obálka 2 předzpoždění + + + + Env 2 Attack + Obálka 2 náběh + + + + Env 2 Hold + Obálka 2 držení + + + + Env 2 Decay + Obálka 2 útlum + + + + Env 2 Sustain + Obálka 2 vydržení + + + + Env 2 Release + Obálka 2 uvolnění + + + + Env 2 Slope + Obálka 2 sklon + + + + Osc2-3 modulation + Osc 2–3 modulace + + + + Selected view + Zvolený pohled + + + + Vol1-Env1 + Hla1-Obá1 + + + + Vol1-Env2 + Hla1-Obá2 + + + + Vol1-LFO1 + Hla1-LFO1 + + + + Vol1-LFO2 + Hla1-LFO2 + + + + Vol2-Env1 + Hla2-Obá1 + + + + Vol2-Env2 + Hla2-Obá2 + + + + Vol2-LFO1 + Hla2-LFO1 + + + + Vol2-LFO2 + Hla2-LFO2 + + + + Vol3-Env1 + Hla3-Obá1 + + + + Vol3-Env2 + Hla3-Obá2 + + + + Vol3-LFO1 + Hla3-LFO1 + + + + Vol3-LFO2 + Hla3-LFO2 + + + + Phs1-Env1 + Fáz1-Obá1 + + + + Phs1-Env2 + Fáz1-Obá2 + + + + Phs1-LFO1 + Fáz1-LFO1 + + + + Phs1-LFO2 + Fáz1-LFO2 + + + + Phs2-Env1 + Fáz2-Obá1 + + + + Phs2-Env2 + Fáz2-Obá2 + + + + Phs2-LFO1 + Fáz2-LFO1 + + + + Phs2-LFO2 + Fáz2-LFO2 + + + + Phs3-Env1 + Fáz3-Obá1 + + + + Phs3-Env2 + Fáz3-Obá2 + + + + Phs3-LFO1 + Fáz3-LFO1 + + + + Phs3-LFO2 + Fáz3-LFO2 + + + + Pit1-Env1 + Výš1-Obá1 + + + + Pit1-Env2 + Výš1-Obá2 + + + + Pit1-LFO1 + Výš1-LFO1 + + + + Pit1-LFO2 + Výš1-LFO2 + + + + Pit2-Env1 + Výš2-Obá1 + + + + Pit2-Env2 + Výš2-Obá2 + + + + Pit2-LFO1 + Výš2-LFO1 + + + + Pit2-LFO2 + Výš2-LFO2 + + + + Pit3-Env1 + Výš3-Obá1 + + + + Pit3-Env2 + Výš3-Obá2 + + + + Pit3-LFO1 + Výš3-LFO1 + + + + Pit3-LFO2 + Výš3-LFO2 + + + + PW1-Env1 + Pul1-Obá1 + + + + PW1-Env2 + Pul1-Obá2 + + + + PW1-LFO1 + Pul1-LFO1 + + + + PW1-LFO2 + Pul1-LFO2 + + + + Sub3-Env1 + Sub3-Obá1 + + + + Sub3-Env2 + Sub3-Obá2 + + + + Sub3-LFO1 + Sub3-LFO1 + + + + Sub3-LFO2 + Sub3-LFO2 + + + + + Sine wave + Sinusová vlna + + + + Bandlimited Triangle wave + Pásmově zúžená trojúhelníková vlna + + + + Bandlimited Saw wave + Pásmově zúžená pilovitá vlna + + + + Bandlimited Ramp wave + Pásmově zúžená šikmá vlna + + + + Bandlimited Square wave + Pásmově zúžená pravoúhlá vlna + + + + Bandlimited Moog saw wave + Pásmově zúžená pilovitá vlna typu Moog + + + + + Soft square wave + Zaoblená pravoúhlá vlna + + + + Absolute sine wave + Absolutní sinusová vlna + + + + + Exponential wave + Exponenciální vlna + + + + White noise + Bílý šum + + + + Digital Triangle wave + Digitální trojúhelníková vlna + + + + Digital Saw wave + Digitální pilovitá vlna + + + + Digital Ramp wave + Digitální šikmá vlna + + + + Digital Square wave + Digitální pravoúhlá vlna + + + + Digital Moog saw wave + Digitální pilovitá vlna typu Moog + + + + Triangle wave + Trojúhelníková vlna + + + + Saw wave + Pilovitá vlna + + + + Ramp wave + Šikmá vlna + + + + Square wave + Pravoúhlá vlna + + + + Moog saw wave + Pilovitá vlna typu Moog + + + + Abs. sine wave + Abs. sinusová vlna + + + + Random + Náhodná + + + + Random smooth + Vyhlazená náhodná + + + + MonstroView + + + Operators view + Zobrazení operátorů + + + + The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. + +Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. + Zobrazení operátorů obsahuje všechny operátory. Toto společně zahrnuje jak přímo slyšitelné operátory (oscilátory), tak i neslyšitelné operátory nebo modulátory: generátory nízkých kmitů (LFO) a obálek. + +Otočné ovladače a další ovládací prvky v Zobrazení operátorů mají své vlastní textové popisky, takže můžete získat bližší nápovědu, co který konkrétně dělá. + + + + Matrix view + Zobrazení matrice + + + + The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. + +The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. + +Each modulation target has 4 knobs, one for each modulator. By default the knobs are at 0, which means no modulation. Turning a knob to 1 causes that modulator to affect the modulation target as much as possible. Turning it to -1 does the same, but the modulation is inversed. + Zobrazení matrice obsahuje modulační matrici. Zde můžete nadefinovat modulační vazby mezi různými operátory: každý slyšitelný operátor (oscilátory 1–3) má 3–4 vlastnosti, které mohou být modulovány dalšími modulátory. Použití více modulací spotřebovává více výkonu procesoru. + +Okno je rozděleno na cíle modulace, seskupené podle cílových oscilátorů. Dostupné cíle jsou: hlasitost, výška, fáze, délka pulzu a poměr sub-oscilátoru. Poznámka: některé cíle jsou dostupné pouze pro určitý oscilátor. + +Každý cíl modulace má 4 otočné ovladače, jeden pro každý modulátor. Výchozí stav ovladačů je 0, tedy bez modulace. Otočení ovladače na 1 způsobí, že modulátor bude působit na cíl nejvíce, jak je možno. Otočení na -1 způsobí totéž, ale modulace bude inverzně obrácena. + + + + + + Volume + Hlasitost + + + + + + Panning + Panoráma + + + + + + Coarse detune + Hrubé rozladění + + + + + + semitones + půltónů + + + + + Finetune left + Jemné rozladění vlevo + + + + + + + cents + centů + + + + + Finetune right + Jemné rozladění vpravo + + + + + + Stereo phase offset + Posun stereo fáze + + + + + + + + deg + stupňů + + + + Pulse width + Délka pulzu + + + + Send sync on pulse rise + Synchronizace při nárůstu pulzu + + + + Send sync on pulse fall + Synchronizace při poklesu pulzu + + + + Hard sync oscillator 2 + Pevně synchronizovat oscilátor 2 + + + + Reverse sync oscillator 2 + Reverzně synchronizovat oscilátor 2 + + + + Sub-osc mix + Míchání sub-osc + + + + Hard sync oscillator 3 + Pevně synchronizovat oscilátor 3 + + + + Reverse sync oscillator 3 + Reverzně synchronizovat oscilátor 3 + + + + + + + Attack + Náběh + + + + + Rate + Typ + + + + + Phase + Fáze + + + + + Pre-delay + Předzpoždění + + + + + Hold + Držení + + + + + Decay + Pokles + + + + + Sustain + Držení + + + + + Release + Doznění + + + + + Slope + Strmost + + + + Mix Osc2 with Osc3 + Smíchat Osc2 a Osc3 + + + + Modulate amplitude of Osc3 with Osc2 + Modulovat amplitudu Osc3 pomocí Osc2 + + + + Modulate frequency of Osc3 with Osc2 + Modulovat frekvenci Osc3 pomocí Osc2 + + + + Modulate phase of Osc3 with Osc2 + Modulovat fázi Osc3 pomocí Osc2 + + + + The CRS knob changes the tuning of oscillator 1 in semitone steps. + Otočný ovladač CRS mění ladění oscilátoru 1 v půltónových krocích. + + + + The CRS knob changes the tuning of oscillator 2 in semitone steps. + Otočný ovladač CRS mění ladění oscilátoru 2 v půltónových krocích. + + + + The CRS knob changes the tuning of oscillator 3 in semitone steps. + Otočný ovladač CRS mění ladění oscilátoru 3 v půltónových krocích. + + + + + + + FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. + FTL a FTR změní jemné ladění oscilátoru pro levý a pravý kanál. To přidává oscilátoru stereo rozladění, které rozšíří stereo obraz a vytvoří dojem prostoru. + + + + + + The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. + Otočný ovladač SPO upravuje rozdíl ve fázi mezi levým a pravým kanálem. Větší rozdíl vytváří širší stereofonní obraz. + + + + The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. + Otočný ovladač PW řídí šířku pulzu, jinak též pracovní cyklus, oscilátoru 1. Oscilátor 1 je digitální generátor pulzních vln, který nevytváří pásmově omezený výstup, což znamená, že jej sice můžete použít jako zdroj slyšitelného signálu, ale způsobuje aliasing. Můžete jej ale také využít jako neslyšitelný zdroj synchronizačního signálu, který může sloužit k synchronizaci oscilátorů 2 a 3. + + + + Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + Zaslání synchronizačního signálu při nárůstu: je-li zapnuto, bude synchronizační signál zasílán pokaždé, když bude stav oscilátoru 1 změněn na vyšší, např. když se amplituda změní z -1 na 1. Výška, fáze a šířka pulzu oscilátoru 1 mohou mít vliv na časování synchronizace, ale jejich množství zde nemá žádný efekt. Synchronizační signály jsou odesílány nezávisle pro levý a pravý kanál. + + + + Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + Zaslání synchronizačního signálu při poklesu: je-li zapnuto, bude synchronizační signál zasílán pokaždé, když bude stav oscilátoru 1 změněn na nižší, např. když se amplituda změní z 1 na -1. Výška, fáze a šířka pulzu oscilátoru 1 mohou mít vliv na časování synchronizace, ale jejich množství zde nemá žádný efekt. Synchronizační signály jsou odesílány nezávisle pro levý a pravý kanál. + + + + + Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. + Pevná synchronizace: pokaždé, když oscilátor přijme synchronizační signál z oscilátoru 1, jeho fáze bude nastavena na 0, bez ohledu na jeho fázový posun. + + + + + Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. + Reverzní synchronizace: pokaždé, když oscilátor přijme synchronizační signál z oscilátoru 1, jeho amplituda bude převrácena. + + + + Choose waveform for oscillator 2. + Vyberte vlnu pro oscilátor 2. + + + + Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + Vyberte vlnu pro první suboscilátor oscilátoru 3. Oscilátor 3 může plynule interpolovat mezi dvěma různými vlnovými průběhy. + + + + Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + Vyberte vlnu pro druhý suboscilátor oscilátoru 3. Oscilátor 3 může plynule interpolovat mezi dvěma různými vlnovými průběhy. + + + + The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. + Otočný ovladač SUB mění poměr směšování mezi dvěma suboscilátory oscilátoru 3. Každý suboscilátor může být nastaven tak, aby vytvářel jiný vlnový průběh, a oscilátor 3 může plynule interpolovat mezi nimi. Všechny příchozí modulace oscilátoru 3 jsou shodným způsobem aplikovány na oba suboscilátory / vlnové průběhy. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +Mix mode means no modulation: the outputs of the oscillators are simply mixed together. + Kromě vyhrazených modulátorů Monstro umožňuje oscilátor 3 modulovat výstupem oscilátoru 2. + +Režim směšování znamená bez modulace: výstupy oscilátorů se jednoduše smíchají. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. + Kromě vyhrazených modulátorů Monstro umožňuje oscilátor 3 modulovat výstupem oscilátoru 2. + +AM znamená amplitudovou modulaci: Amplituda (hlasitost) oscilátoru 3 je modulována oscilátorem 2. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. + Kromě vyhrazených modulátorů Monstro umožňuje oscilátor 3 modulovat výstupem oscilátoru 2. + +FM znamená frekvenční modulaci: frekvence (výška) oscilátoru 3 je modulována oscilátorem 2. Frekvenční modulace je implementována jako fázová modulace, která poskytuje stabilnější výslednou výšku než "čistá" frekvenční modulace. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. + Kromě vyhrazených modulátorů Monstro umožňuje oscilátor 3 modulovat výstupem oscilátoru 2. + +PM znamená fázovou modulaci: fáze oscilátoru 3 je modulována oscilátorem 2. To se liší od frekvenční modulace tím, že fázové změny nejsou kumulativní. + + + + Select the waveform for LFO 1. +"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + Vyberte tvar vlny pro LFO 1. +"Náhodná" a "Vyhlazená náhodná" jsou speciální vlny: produkují náhodný výstup, kde rychlost LFO řídí, jak často se mění stav LFO. Vyhlazená verze interpoluje mezi těmito stavy kosinovou interpolací. Tyto náhodné režimy mohou být použity k oživení vašich předvoleb – přidávají něco z analogové nepředvídatelnosti... + + + + Select the waveform for LFO 2. +"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + Vyberte tvar vlny pro LFO 2. +"Náhodná" a "Vyhlazená náhodná" jsou speciální vlny: produkují náhodný výstup, kde rychlost LFO řídí, jak často se mění stav LFO. Vyhlazená verze interpoluje mezi těmito stavy kosinovou interpolací. Tyto náhodné režimy mohou být použity k oživení vašich předvoleb – přidávají něco z analogové nepředvídatelnosti... + + + + + Attack causes the LFO to come on gradually from the start of the note. + Náběh způsobí, že LFO najede postupně od začátku noty. + + + + + Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. + Rate nastavuje rychlost LFO, měřenou v milisekundách za cyklus. Lze synchronizovat s tempem. + + + + + PHS controls the phase offset of the LFO. + PHS řídí fázový posun LFO. + + + + + PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. + PRE nebo předzpoždění (PRE, predelay) zpozdí začátek obálky oproti začátku noty. Hodnota 0 znamená bez zpoždění. + + + + + ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. + NÁB nebo náběh určuje, jak rychle vystoupá začátek obálky do špičky, měřeno v milisekundách. Hodnota 0 znamená okamžitý náběh. + + + + + HOLD controls how long the envelope stays at peak after the attack phase. + Držení určuje, jak dlouho obálka zůstane na špičce po fázi náběhu. + + + + + DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. + ÚTL nebo útlum (DEC, decoy) řídí rychlost poklesu obálky ze špičky do nulové úrovně (měřeno v milisekundách). Aktuální útlum může být kratší, pokud je použito podržení (sustain). + + + + + SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. + POD nebo podržení (SUS, sustain) řídí úroveň podržení v obálce. Fáze útlumu (decoy) nemůže jít pod tuto úroveň, dokud je nota držená. + + + + + REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. + UVO nebo uvolnění určuje, jak dlouhé bude ukončení noty, tedy jak dlouho bude trvat zeslabení ze špičky na nulu. Skutečná délka uvolnění může být kratší v závislosti na tom, ve které fázi je nota ukončena. + + + + + The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. + Otočný ovladač sklon řídí křivku a tvar obálky. Hodnota 0 vytváří přímý nárůst i pokles. Záporné hodnoty vytvářejí křivku, která začíná pomalu, rychle dosáhne špičky a opět pomalu klesá. Pozitivní hodnoty vytvářejí křivku, která začíná a končí rychle a udržuje se v blízkosti špičky. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modulation amount + Hloubka modulace + + + + MultitapEchoControlDialog + + + Length + Délka + + + + Step length: + Délka kroku: + + + + Dry + Poměr + + + + Dry Gain: + Poměr zdrojového zvuku: + + + + Stages + Úrovně + + + + Lowpass stages: + Počet úrovní dolní propusti: + + + + Swap inputs + Přepnout vstupy + + + + Swap left and right input channel for reflections + Přepnout levý a pravý vstupní kanál pro odrazy + + + + NesInstrument + + + Channel 1 Coarse detune + Kanál 1 hrubé rozladění + + + + Channel 1 Volume + Hlasitost kanálu 1 + + + + Channel 1 Envelope length + Kanál 1 délka obálky + + + + Channel 1 Duty cycle + Kanál 1 pracovní cyklus + + + + Channel 1 Sweep amount + Kanál 1 množství sweepu + + + + Channel 1 Sweep rate + Kanál 1rychlost sweepu + + + + Channel 2 Coarse detune + Kanál 2 hrubé rozladění + + + + Channel 2 Volume + Hlasitost kanálu 2 + + + + Channel 2 Envelope length + Kanál 2 délka obálky + + + + Channel 2 Duty cycle + Kanál 2 pracovní cyklus + + + + Channel 2 Sweep amount + Kanál 2 množství sweepu + + + + Channel 2 Sweep rate + Kanál 2 rychlost sweepu + + + + Channel 3 Coarse detune + Kanál 3 hrubé rozladění + + + + Channel 3 Volume + Hlasitost kanálu 3 + + + + Channel 4 Volume + Hlasitost kanálu 4 + + + + Channel 4 Envelope length + Kanál 4 délka obálky + + + + Channel 4 Noise frequency + Kanál 4 frekvence šumu + + + + Channel 4 Noise frequency sweep + Kanál 4 sweep frekvence šumu + + + + Master volume + Hlavní hlasitost + + + + Vibrato + Vibráto + + + + NesInstrumentView + + + + + + Volume + Hlasitost + + + + + + Coarse detune + Hrubé rozladění + + + + + + Envelope length + Délka obálky + + + + Enable channel 1 + Zapnout kanál 1 + + + + Enable envelope 1 + Zapnout obálku 1 + + + + Enable envelope 1 loop + Zapnout smyčku obálky 1 + + + + Enable sweep 1 + Zapnout sweep 1 + + + + + Sweep amount + Množství sweepu + + + + + Sweep rate + Rychlost sweepu + + + + + 12.5% Duty cycle + 12.5% pracovního cyklu + + + + + 25% Duty cycle + 25% pracovního cyklu + + + + + 50% Duty cycle + 50% pracovního cyklu + + + + + 75% Duty cycle + 75% pracovního cyklu + + + + Enable channel 2 + Zapnout kanál 2 + + + + Enable envelope 2 + Zapnout obálku 2 + + + + Enable envelope 2 loop + Zapnout smyčku obálky 2 + + + + Enable sweep 2 + Zapnout sweep 2 + + + + Enable channel 3 + Zapnout kanál 3 + + + + Noise Frequency + Frekvence šumu + + + + Frequency sweep + Frekvence sweepu + + + + Enable channel 4 + Zapnout kanál 4 + + + + Enable envelope 4 + Zapnout obálku 4 + + + + Enable envelope 4 loop + Zapnout smyčku obálky 4 + + + + Quantize noise frequency when using note frequency + Kvantizovat frekvenci šumu při použití frekvence noty + + + + Use note frequency for noise + Použít frekvenci pro šum + + + + Noise mode + Typ šumu + + + + Master Volume + Hlavní hlasitost + + + + Vibrato + Vibráto + + + + OscillatorObject + + + Osc %1 waveform + Osc %1 vlna + + + + Osc %1 harmonic + Osc %1 harmonické + + + + + Osc %1 volume + Osc %1 hlasitost + + + + + Osc %1 panning + Osc %1 panoráma + + + + + Osc %1 fine detuning left + Osc %1 jemné rozladění vlevo + + + + Osc %1 coarse detuning + Osc %1 hrubé rozladění + + + + Osc %1 fine detuning right + Osc %1 jemné rozladění vpravo + + + + Osc %1 phase-offset + Osc %1 posun fáze + + + + Osc %1 stereo phase-detuning + Osc %1 rozladění stereo fáze + + + + Osc %1 wave shape + Osc %1 forma vlny + + + + Modulation type %1 + Typ modulace %1 + + + + PatchesDialog + + + Qsynth: Channel Preset + Qsynth: Předvolba kanálu + + + + Bank selector + Výběr banky + + + + Bank + Banka + + + + Program selector + Výběr programu + + + + Patch + Patch + + + + Name + Název + + + + OK + OK + + + + Cancel + Zrušit + + + + PatmanView + + + Open other patch + Otevřít jiný patch + + + + Click here to open another patch-file. Loop and Tune settings are not reset. + Klepněte sem, pokud chcete otevřít další patch-soubor. Nastavení smyčky a režimu ladění zůstanou zachována. + + + + Loop + Smyčka + + + + Loop mode + Režim smyčky + + + + Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. + Zde můžete přepínat režim smyčky. Je-li zapnutá, PatMan použije informace o smyčce dostupné v souboru. + + + + Tune + Ladění + + + + Tune mode + Režim ladění + + + + Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. + Zde můžete přepínat režim ladění. Je-li zapnut, PatMan naladí vzorek tak, aby odpovídal frekvenci noty. + + + + No file selected + Není vybrán žádný soubor + + + + Open patch file + Otevřít soubor patch + + + + Patch-Files (*.pat) + Soubor patch (*.pat) + + + + PatternView + + + use mouse wheel to set velocity of a step + použijte kolečko myši pro nastavení dynamiky kroku + + + + double-click to open in Piano Roll + poklepáním otevřete v Piano rollu + + + + Open in piano-roll + Otevřít v Piano rollu + + + + Clear all notes + Vymazat všechny noty + + + + Reset name + Resetovat jméno + + + + Change name + Změnit jméno + + + + Add steps + Přidat kroky + + + + Remove steps + Odstranit kroky + + + + Clone Steps + Klonovat kroky + + + + PeakController + + + Peak Controller + Ovladač špičky + + + + Peak Controller Bug + Chyba ovladače špičky + + + + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. + Z důvodu chyby ve starší verzi LMMS nemusí být ovladače špiček správně připojeny. Ujistěte se prosím, zda jsou ovladače špiček správně připojeny a znovu uložte tento soubor. Omlouváme se za způsobené nepříjemnosti. + + + + PeakControllerDialog + + + PEAK + ŠPIČ + + + + LFO Controller + Ovladač LFO + + + + PeakControllerEffectControlDialog + + + BASE + ZÁKL + + + + Base amount: + Základní míra: + + + + AMNT + MNOŽ + + + + Modulation amount: + Hloubka modulace: + + + + MULT + NÁSB + + + + Amount Multiplicator: + Násobič množství: + + + + ATCK + NÁBH + + + + Attack: + Náběh: + + + + DCAY + POKL + + + + Release: + Doznění: + + + + TRSH + PRÁH + + + + Treshold: + Práh: + + + + PeakControllerEffectControls + + + Base value + Základní hodnota + + + + Modulation amount + Hloubka modulace + + + + Attack + Náběh + + + + Release + Doznění + + + + Treshold + Práh + + + + Mute output + Ztlumit výstup + + + + Abs Value + Abs hodnota + + + + Amount Multiplicator + Násobič množství + + + + PianoRoll + + + Note Velocity + Dynamika noty + + + + Note Panning + Panoráma noty + + + + Mark/unmark current semitone + Zvýraznit/Skrýt zvolený tón + + + + Mark/unmark all corresponding octave semitones + Zvýraznit/Skrýt zvolený tón ve všech oktávách + + + + Mark current scale + Zvýraznit zvolenou stupnici + + + + Mark current chord + Zvýraznit zvolený akord + + + + Unmark all + Skrýt vše + + + + Select all notes on this key + Vybrat všechny noty zvolené výšky + + + + Note lock + Zamknout notu + + + + Last note + Podle poslední noty + + + + No scale + Žádná stupnice + + + + No chord + Žádný akord + + + + Velocity: %1% + Dynamika: %1% + + + + Panning: %1% left + Panoráma: %1% vlevo + + + + Panning: %1% right + Panoráma: %1% vpravo + + + + Panning: center + Panoráma: střed + + + + Please open a pattern by double-clicking on it! + Otevřete prosím záznam poklepáním! + + + + + Please enter a new value between %1 and %2: + Vložte prosím novou hodnotu mezi %1 a %2: + + + + PianoRollWindow + + + Play/pause current pattern (Space) + Přehrát/Pozastavit přehrávání aktuálního záznamu (mezerník) + + + + Record notes from MIDI-device/channel-piano + Nahrávat z MIDI zařízení / virtuální klávesnice + + + + Record notes from MIDI-device/channel-piano while playing song or BB track + Nahrávat z MIDI zařízení / virtuální klávesnice při přehrávání skladby nebo stopy bicích/basů + + + + Stop playing of current pattern (Space) + Zastavit přehrávání aktuálního záznamu (mezerník) + + + + Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. + Klepněte sem, pokud chcete přehrát aktuální záznam. To je užitečné při editaci. Záznam je automaticky přehráván ve smyčce. + + + + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. + Klepněte sem, pokud chcete nahrávat z MIDI zařízení nebo z virtuální klávesnice příslušného kanálového okna do aktuálního záznamu. Při nahrávání se zapíší všechny zahrané noty do tohoto záznamu, a následně je můžete přehrát nebo upravit. + + + + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. + Klepněte sem, pokud chcete nahrávat z MIDI zařízení nebo z virtuální klávesnice příslušného kanálového okna do aktuálního záznamu. Při nahrávání se zapíší všechny zahrané noty do tohoto záznamu a na pozadí uslyšíte skladbu nebo stopu bicích/basů. + + + + Click here to stop playback of current pattern. + Klepněte sem, pokud chcete zastavit přehrávání aktuálního záznamu. + + + + Edit actions + Akce úprav + + + + Draw mode (Shift+D) + Režim kreslení (Shift+D) + + + + Erase mode (Shift+E) + Režim mazání (Shift+E) + + + + Select mode (Shift+S) + Režim výběru (Shift+S) + + + + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + Klepněte sem pro aktivaci režimu kreslení. V tomto režimu můžete přidávat, měnit a přesouvat noty. Toto je výchozí režim, který se používá nejčastěji. Pro aktivaci tohoto režimu můžete také stisknout "Shift+D" na klávesnici. V tomto režimu podržte %1 pro dočasné přepnutí do režimu výběru. + + + + Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. + Klepněte sem pro aktivaci režimu mazání. V tomto režimu můžete vymazávat noty. Pro aktivaci tohoto režimu můžete také stisknout tlačítko "Shift+E" na klávesnici. + + + + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Klepněte sem pro aktivaci režimu výběru. V tomto režimu můžete vybírat noty. Alternativně můžete v režimu kreslení držet %1 pro dočasné přepnutí do režimu výběru. + + + + Pitch Bend mode (Shift+T) + Režim ohýbání výšky (Shift+T) + + + + Click here and Pitch Bend mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + Klepněte sem pro aktivaci režimu ohýbání výšky tónu. V tomto režimu můžete klepnutím na notu otevřít její automatizované rozladění. To můžete využít ke sklouznutí z jedné noty na jinou. Pro aktivaci tohoto režimu můžete také stisknout klávesu "Shift+T" na klávesnici. + + + + Quantize + Kvantizace + + + + Copy paste controls + Ovládání kopírování a vkládání + + + + Cut selected notes (%1+X) + Vyjmout označené noty (%1+X) + + + + Copy selected notes (%1+C) + Kopírovat označené noty (%1+C) + + + + Paste notes from clipboard (%1+V) + Vložit noty ze schránky (%1+V) + + + + Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klepněte sem, pokud chcete označené noty vyjmout a uložit do schránky. Vložit je pak můžete kdekoliv v libovolném záznamu pomocí tlačítka Vložit. + + + + Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klepněte sem, pokud chcete označené noty zkopírovat do schránky. Vložit je pak můžete kdekoliv v libovolném záznamu pomocí tlačítka Vložit. + + + + Click here and the notes from the clipboard will be pasted at the first visible measure. + Klepnete-li sem, budou noty ze schránky vloženy do prvního viditelného taktu. + + + + Timeline controls + Ovládání časové osy + + + + Zoom and note controls + Lupa a ovládání not + + + + This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. + Tímto se ovládá zvětšení osy. To může být užitečné při volbě zvětšení pro konkrétní úkol. Při běžné úpravě by mělo být zvětšení použito na vaše nejmenší noty. + + + + The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. + "Q" znamená kvantizaci, která ovládá mřížku velikosti not a kontrolní body krokování. S menšími hodnotami kvantizace můžete kreslit kratší noty v Piano rollu a přesnější kontrolní body v editoru automatizace. + + + + This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited + Tímto je možno vybrat délku nových not. "Poslední nota" znamená, že LMMS použije délku naposledy upravované noty. + + + + The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! + Funkce je přímo propojena s kontextovou nabídkou na virtuální klávesnici vlevo v Piano rollu. Poté, co jste v rozbalovací nabídce zvolili stupnici, můžete klepnout pravým tlačítkem na požadovanou klávesu na virtuální klávesnici, a pak zvolit "Zvýraznit zvolenou stupnici". LMMS zvýrazní všechny noty, které patří do zvolené stupnice, a to od klávesy, kterou jste vybrali! + + + + Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + Vyberte si akord, který pak LMMS může nakreslit nebo zvýraznit. V rozbalovací nabídce najdete nejčastěji používané akordy. Po výběru akordu klepněte kamkoliv pro umístění akordu, klepnutím pravým tlačítkem na virtuální klávesnici pak otevřete kontextové menu a zvýrazníte akord. Chcete-li se vrátit k práci s jednotlivými notami, musíte v rozbalovací nabídce zvolit možnost "Žádný akord". + + + + + Piano-Roll - %1 + Piano roll – %1 + + + + + Piano-Roll - no pattern + Piano roll – žádný záznam + + + + PianoView + + + Base note + Základní nota + + + + Plugin + + + Plugin not found + Plugin nenalezen + + + + The plugin "%1" wasn't found or could not be loaded! +Reason: "%2" + Plugin "%1" nebyl nalezen nebo nemůže být načten! +Důvod: "%2" + + + + Error while loading plugin + Při načítání pluginu došlo k chybě + + + + Failed to load plugin "%1"! + Načtení pluginu "%1" selhalo! + + + + PluginBrowser + + + Instrument Plugins + Nástrojové pluginy + + + + Instrument browser + Prohlížeč nástrojů + + + + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. + Nástroj přetáhněte do editoru skladby, editoru bicích/basů nebo do existující nástrojové stopy. + + + + PluginFactory + + + Plugin not found. + Plugin nebyl nalezen. + + + + LMMS plugin %1 does not have a plugin descriptor named %2! + U LMMS pluginu %1 chybí popisovač pluginu s názvem %2! + + + + ProjectNotes + + + Project Notes + Poznámky k projektu + + + + Enter project notes here + Sem zapište poznámky k projektu + + + + Edit Actions + Provedené úpravy + + + + &Undo + &Zpět + + + + %1+Z + %1+Z + + + + &Redo + &Znovu + + + + %1+Y + %1+Z + + + + &Copy + &Kopírovat + + + + %1+C + %1+C + + + + Cu&t + &Vyjmout + + + + %1+X + %1+X + + + + &Paste + V&ložit + + + + %1+V + %1+V + + + + Format Actions + Formátování + + + + &Bold + &Tučné + + + + %1+B + %1+B + + + + &Italic + &Kurzíva + + + + %1+I + %1+I + + + + &Underline + &Podtržené + + + + %1+U + %1+U + + + + &Left + &Vlevo + + + + %1+L + %1+L + + + + C&enter + &Na střed + + + + %1+E + %1+E + + + + &Right + V&pravo + + + + %1+R + %1+R + + + + &Justify + &Do bloku + + + + %1+J + %1+J + + + + &Color... + &Barva... + + + + ProjectRenderer + + + WAV-File (*.wav) + WAV soubor (*.wav) + + + + Compressed OGG-File (*.ogg) + Komprimovaný OGG soubor (*.ogg) + + + FLAC-File (*.flac) + Soubor FLAC (*.flac) + + + + Compressed MP3-File (*.mp3) + Komprimovaný soubor MP3 (*.mp3) + + + + QWidget + + + + + Name: + Název: + + + + + Maker: + Tvůrce: + + + + + Copyright: + Autorská práva: + + + + + Requires Real Time: + Vyžaduje běh v reálném čase: + + + + + + + + + Yes + Ano + + + + + + + + + No + Ne + + + + + Real Time Capable: + Schopnost běhu v reálném čase: + + + + + In Place Broken: + Na místě poškozeného: + + + + + Channels In: + Vstupní kanály: + + + + + Channels Out: + Výstupní kanály: + + + + File: %1 + Soubor: %1 + + + + File: + Soubor: + + + + RenameDialog + + + Rename... + Přejmenovat... + + + + ReverbSCControlDialog + + + Input + Vstup + + + + Input Gain: + Zesílení vstupu: + + + + Size + Velikost + + + + Size: + Velikost: + + + + Color + Barva + + + + Color: + Barva: + + + + Output + Výstup + + + + Output Gain: + Zesílení výstupu: + + + + ReverbSCControls + + + Input Gain + Vstupní úroveň + + + + Size + Velikost + + + + Color + Barva + + + + Output Gain + Zesílení výstupu + + + + SampleBuffer + + + Fail to open file + Chyba otevírání souboru + + + + Audio files are limited to %1 MB in size and %2 minutes of playing time + Audio soubory jsou omezeny na %1 MB velikosti a %2 minut délky + + + + Open audio file + Otevřít audio soubor + + + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + Všechny audio soubory (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + + + + Wave-Files (*.wav) + WAV soubory (*.wav) + + + + OGG-Files (*.ogg) + OGG soubory (*.ogg) + + + + DrumSynth-Files (*.ds) + DrumSynth soubory (*.ds) + + + + FLAC-Files (*.flac) + FLAC soubory (*.flac) + + + + SPEEX-Files (*.spx) + SPEEX soubory (*.spx) + + + + VOC-Files (*.voc) + VOC soubory (*.voc) + + + + AIFF-Files (*.aif *.aiff) + Soubory AIFF (*.aif *.aiff) + + + + AU-Files (*.au) + AU soubory (*.au) + + + + RAW-Files (*.raw) + RAW soubory (*.raw) + + + + SampleTCOView + + + double-click to select sample + poklepáním vyberte sampl + + + + Delete (middle mousebutton) + Smazat (prostřední tlačítko myši) + + + + Cut + Vyjmout + + + + Copy + Kopírovat + + + + Paste + Vložit + + + + Mute/unmute (<%1> + middle click) + Ztlumit/Odtlumit (<%1> + prostřední tlačítko) + + + + SampleTrack + + + Volume + Hlasitost + + + + Panning + Panoráma + + + + + Sample track + Stopa samplů + + + + SampleTrackView + + + Track volume + Hlasitost stopy + + + + Channel volume: + Hlasitost kanálu: + + + + VOL + HLA + + + + Panning + Panoráma + + + + Panning: + Panoráma: + + + + PAN + PAN + + + + SetupDialog + + + Setup LMMS + Nastavení LMMS + + + + + General settings + Hlavní nastavení + + + + BUFFER SIZE + VELIKOST VYR. PAMĚTI + + + + + Reset to default-value + Nastavit výchozí hodnoty + + + + MISC + JINÉ + + + + Enable tooltips + Zapnout bublinovou nápovědu + + + + Show restart warning after changing settings + Zobrazit výzvu k restartu po změně nastavení + + + + Display volume as dBFS + Zobrazit hlasitost v dBFS + + + + Compress project files per default + Komprimovat soubory s projekty + + + + One instrument track window mode + Režim jedné stopy pro nástroje + + + + HQ-mode for output audio-device + HQ režim pro výstup audio zařízení + + + + Compact track buttons + Malá tlačítka u stop + + + + Sync VST plugins to host playback + Synchronizace VST pluginů s hostujícím přehráváním + + + + Enable note labels in piano roll + Povolit názvy tónů v Piano rollu + + + + Enable waveform display by default + Povolit zobrazení vlny ve výchozím nastavení + + + + Keep effects running even without input + Nechat efekty spuštěné i bez vstupu + + + + Create backup file when saving a project + Při ukládání projektu vytvořit záložní soubor + + + + Reopen last project on start + Po spuštění otevřít poslední projekt + + + + Use built-in NaN handler + Použít vestavěný NaN handler + + + + PLUGIN EMBEDDING + VLOŽENÍ PLUGINU + + + + No embedding + Nevkládat + + + + Embed using Qt API + Vložit pomocí rozhraní Qt + + + + Embed using native Win32 API + Vložit pomocí nativního rozhraní Win32 + + + + Embed using XEmbed protocol + Vložit pomocí protokolu XEmbed + + + + LANGUAGE + Jazyk + + + + + Paths + Cesty + + + + Directories + Adresáře + + + + LMMS working directory + Pracovní adresář LMMS + + + + Themes directory + Adresář pro témata + + + + Background artwork + Obrázek na pozadí + + + + VST-plugin directory + Adresář pro VST pluginy + + + + GIG directory + Adresář pro GIG + + + + SF2 directory + Adresář pro SF2 + + + + LADSPA plugin directories + Adresář pro LADSPA pluginy + + + + STK rawwave directory + Adresář pro STK rawwave + + + + Default Soundfont File + Výchozí Soundfont soubor + + + + + Performance settings + Nastavení výkonu + + + + Auto save + Automatické ukládání + + + + Enable auto-save + Povolit automatické ukládání + + + + Allow auto-save while playing + Povolit automatické ukládání během přehrávání + + + + UI effects vs. performance + Efekty uživatelského rozhraní vs. výkon + + + + Smooth scroll in Song Editor + Plynulé posouvání v Song Editoru + + + + Show playback cursor in AudioFileProcessor + Zobrazit přehrávací kurzor v AudioFileProcessoru + + + + + Audio settings + Audio nastavení + + + + AUDIO INTERFACE + AUDIO ROZHRANÍ + + + + + MIDI settings + MIDI nastavení + + + + MIDI INTERFACE + MIDI ROZHRANÍ + + + + OK + OK + + + + Cancel + Zrušit + + + + Restart LMMS + Restartovat LMMS + + + + Please note that most changes won't take effect until you restart LMMS! + Mnohé změny nastavení se projeví až po restartu LMMS! + + + + Frames: %1 +Latency: %2 ms + Rámce: %1 +Zpoždění %2 ms + + + + Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. + Zde můžete nastavit interní velikost vyrovnávací paměti, která je užívána LMMS. Nízké hodnoty vedou k menšímu zpoždění, ale také způsobují nepoužitelný zvuk nebo špatný výkon, zejména na starých počítačích či systémech s jádrem nepodporujícím real time. + + + + Choose LMMS working directory + Vyberte pracovní adresář LMMS + + + + Choose your GIG directory + Vyberte svůj adresář pro GIG soubory + + + + Choose your SF2 directory + Vyberte svůj adresář pro SF2 soubory + + + + Choose your VST-plugin directory + Vyberte adresář pro VST pluginy + + + + Choose artwork-theme directory + Vyberte adresář s tématy + + + + Choose LADSPA plugin directory + Vyberte adresář pro LADSPA pluginy + + + + Choose STK rawwave directory + Vyberte adresář pro STK rawwave + + + + Choose default SoundFont + Vyberte výchozí SoundFont + + + + Choose background artwork + Vyberte obrázek na pozadí + + + + minutes + minut + + + + minute + minuta + + + + Disabled + Vypnuto + + + + Auto-save interval: %1 + Interval automatického ukládání: %1 + + + + Set the time between automatic backup to %1. +Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. + Nastavte čas mezi automatickým zálohováním na %1. +Nezapomeňte také svůj projekt uložit ručně. Můžete si vybrat, zda nechcete během přehrávání zakázat ukládání, což je problematické pro některé starší systémy. + + + + Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. + Zde vyberte preferované audio rozhraní. V závislosti na konfiguraci Vašeho systému při kompilaci můžete volit mezi ALSA, JACK, OSS a dalšími. Níže vidíte políčko, které nabízí možnost nastavení vybraného audio rozhraní. + + + + Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. + Zde vyberte preferované MIDI rozhraní. V závislosti na konfiguraci Vašeho systému při kompilaci můžete volit mezi ALSA OSS a dalšími. Níže vidíte políčko, které nabízí možnost nastavení vybraného MIDI rozhraní. + + + + Song + + + Tempo + Tempo + + + + Master volume + Hlavní hlasitost + + + + Master pitch + Transpozice + + + + LMMS Error report + Chybové hlášení LMMS + + + + Project saved + Projekt uložen + + + + The project %1 is now saved. + Projekt %1 je nyní uložen. + + + + Project NOT saved. + Projekt NENÍ uložen. + + + + The project %1 was not saved! + Projekt %1 nebyl uložen! + + + + Import file + Importovat soubor + + + + MIDI sequences + MIDI sekvence + + + + Hydrogen projects + Projekty Hydrogen + + + + All file types + Všechny typy souborů + + + + + Empty project + Prázdný projekt + + + + + This project is empty so exporting makes no sense. Please put some items into Song Editor first! + Tento projekt je prázdný, jeho exportování nemá smysl. Nejdříve prosím vložte nějaké položky do Editoru skladby! + + + + Select directory for writing exported tracks... + Vyberte adresář pro zápis exportovaných stop... + + + + + untitled + nepojmenovaný + + + + + Select file for project-export... + Vyberte soubor pro export projektu... + + + + Save project + Uložit projekt + + + + MIDI File (*.mid) + MIDI soubor (*.mid) + + + + The following errors occured while loading: + Během načítání se vyskytly tyto chyby: + + + + SongEditor + + + Could not open file + Nemohu otevřít soubor + + + + Could not open file %1. You probably have no permissions to read this file. + Please make sure to have at least read permissions to the file and try again. + Nelze otevřít soubor %1. Pravděpodobně nemáte oprávnění číst tento soubor. + Ujistěte se prosím, že máte oprávnění alespoň číst tento soubor a zkuste to znovu. + + + + Could not write file + Nemohu zapsat soubor + + + + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. + Nelze zapisovat do souboru %1. Pravděpodobně nemáte oprávnění zapisovat do tohoto souboru. Ujistěte se prosím, že máte oprávnění zapisovat do tohoto souboru a zkuse to znovu. + + + + Error in file + Chyba v souboru + + + + The file %1 seems to contain errors and therefore can't be loaded. + Soubor %1 pravděpodobně obsahuje chyby, a proto nemohl být načten. + + + + Version difference + Rozdíl verzí + + + + This %1 was created with LMMS %2. + %1 byl vytvořen v LMMS %2. + + + + template + šablona + + + + project + projekt + + + + Tempo + Tempo + + + + TEMPO/BPM + TEMPO/BPM + + + + tempo of song + tempo skladby + + + + The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). + Tempo skladby je uvedeno v úderech za minutu (BPM). Chcete-li změnit tempo skladby, změňte tuto hodnotu. Každý takt má čtyři doby (beats), takže tempo v BPM specifikuje kolik taktů / 4 bude za minutu přehráno (nebo kolik taktů bude přehráno ve čtyřech minutách). + + + + High quality mode + Režim vysoké kvality + + + + + Master volume + Hlavní hlasitost + + + + master volume + hlavní hlasitost + + + + + Master pitch + Transpozice + + + + master pitch + transpozice + + + + Value: %1% + Hodnota: %1% + + + + Value: %1 semitones + Hodnota: %1 půltónů + + + + SongEditorWindow + + + Song-Editor + Editor skladby + + + + Play song (Space) + Přehrát skladbu (mezerník) + + + + Record samples from Audio-device + Nahrát samply z audio zařízení + + + + Record samples from Audio-device while playing song or BB track + Nahrát samply z audio zařízení při přehrávání skladby nebo stopy bicích/basů + + + + Stop song (Space) + Zastavit přehrávání (mezerník) + + + + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. + Klepněte sem, pokud chcete přehrát celou skladbu. Přehrávání začne v místě kde se nalézá zelený označovač pozice, se kterým lze též při přehrávání pohybovat. + + + + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. + Klepněte sem, pokud chcete zastavit přehrávání skladby. Označovač pozice bude nastaven na začátek skladby. + + + + Track actions + Akce stopy + + + + Add beat/bassline + Přidat bicí/basy + + + + Add sample-track + Přidat stopu samplů + + + + Add automation-track + Přidat stopu automatizace + + + + Edit actions + Akce úprav + + + + Draw mode + Režim kreslení + + + + Edit mode (select and move) + Režim úprav (označit a přesunout) + + + + Timeline controls + Ovládání časové osy + + + + Zoom controls + Ovládání zvětšení + + + + SpectrumAnalyzerControlDialog + + + Linear spectrum + Lineární spektrum + + + + Linear Y axis + Lineární osa Y + + + + SpectrumAnalyzerControls + + + Linear spectrum + Lineární spektrum + + + + Linear Y axis + Lineární osa Y + + + + Channel mode + Režim kanálu + + + + SubWindow + + + Close + Zavřít + + + + Maximize + Maximalizovat + + + + Restore + Obnovit + + + + TabWidget + + + + Settings for %1 + Nastavení rpo %1 + + + + TempoSyncKnob + + + + Tempo Sync + Synchronizace tempa + + + + No Sync + Nesynchronizovat + + + + Eight beats + Osm dob + + + + Whole note + Celá nota + + + + Half note + Půlová nota + + + + Quarter note + Čtvrťová nota + + + + 8th note + Osminová nota + + + + 16th note + Šestnáctinová nota + + + + 32nd note + Dvaatřicetinová nota + + + + Custom... + Vlastní... + + + + Custom + Vlastní + + + + Synced to Eight Beats + Synchronizováno k osmi dobám + + + + Synced to Whole Note + Synchronizováno k celé notě + + + + Synced to Half Note + Synchronizováno k půlové notě + + + + Synced to Quarter Note + Synchronizováno ke čtvrťové notě + + + + Synced to 8th Note + Synchronizováno k osminové notě + + + + Synced to 16th Note + Synchronizováno k šestnáctinové notě + + + + Synced to 32nd Note + Synchronizováno k dvaatřicetinové notě + + + + TimeDisplayWidget + + + click to change time units + klepněte pro změnu časových jednotek + + + + MIN + MIN + + + + SEC + S + + + + MSEC + MS + + + + BAR + TAKT + + + + BEAT + DOBA + + + + TICK + TIK + + + + TimeLineWidget + + + Enable/disable auto-scrolling + Povolit/Zakázat automatický posun + + + + Enable/disable loop-points + Povolit/Zakázat body přehrávání ve smyčce + + + + After stopping go back to begin + Po skončení přetočit zpět na začátek + + + + After stopping go back to position at which playing was started + Po skončení přetočit zpět na pozici, ze které přehrávání začalo + + + + After stopping keep position + Po skončení zachovat pozici + + + + + Hint + Rada + + + + Press <%1> to disable magnetic loop points. + Stiskněte <%1> pro vypnutí magnetických bodů smyčky. + + + + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + Držte <Shift> pro přesouvání počátečního bodu smyčky; stiskněte <%1> pro vypnutí magnetických bodů smyčky. + + + + Track + + + Mute + Ztlumit + + + + Solo + Sólo + + + + TrackContainer + + + Couldn't import file + Nemohu importovat soubor + + + + Couldn't find a filter for importing file %1. +You should convert this file into a format supported by LMMS using another software. + Nemohu najít filtr pro import souboru %1. +Měli byste tento soubor převést do formátu podporovaného LMMS pomocí jiného software. + + + + Couldn't open file + Nemohu otevřít soubor + + + + Couldn't open file %1 for reading. +Please make sure you have read-permission to the file and the directory containing the file and try again! + Nemohu otevřít soubor %1 pro čtení. +Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslušného adresáře a zkuste to znovu! + + + + Loading project... + Načítám projekt... + + + + + Cancel + Zrušit + + + + + Please wait... + Prosím čekejte... + + + + Loading cancelled + Načítání zrušeno + + + + Project loading was cancelled. + Načítání projektu bylo zrušeno. + + + + Loading Track %1 (%2/Total %3) + Načítám Stopu %1 (%2/celkem %3) + + + + Importing MIDI-file... + Importuji MIDI soubor... + + + + TrackContentObject + + + Mute + Ztlumit + + + + TrackContentObjectView + + + Current position + Aktuální pozice + + + + + Hint + Rada + + + + Press <%1> and drag to make a copy. + K vytvoření kopie stiskněte <%1> a táhněte myší. + + + + Current length + Aktuální délka + + + + Press <%1> for free resizing. + Stiskněte <%1> pro volnou změnu velikosti. + + + + + %1:%2 (%3:%4 to %5:%6) + %1:%2 (%3:%4 do %5:%6) + + + + Delete (middle mousebutton) + Smazat (prostřední tlačítko myši) + + + + Cut + Vyjmout + + + + Copy + Kopírovat + + + + Paste + Vložit + + + + Mute/unmute (<%1> + middle click) + Ztlumit/Odtlumit (<%1> + prostřední tlačítko myši) + + + + TrackOperationsWidget + + + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Při klepnutí na úchop držte <%1> pro zkopírování přetahované stopy. + + + + Actions for this track + Akce pro tuto stopu + + + + Mute + Ztlumit + + + + + Solo + Sólo + + + + Mute this track + Ztlumit tuto stopu + + + + Clone this track + Klonovat tuto stopu + + + + Remove this track + Odstranit tuto stopu + + + + Clear this track + Smazat tuto stopu + + + + FX %1: %2 + Efekt %1: %2 + + + + Assign to new FX Channel + Přiřadit k novému efektovému kanálu + + + + Turn all recording on + Spustit všechna nahrávání + + + + Turn all recording off + Zastavit všechna nahrávání + + + + TripleOscillatorView + + + Use phase modulation for modulating oscillator 1 with oscillator 2 + Použít fázovou modulaci pro modulování oscilátoru 1 oscilátorem 2 + + + + Use amplitude modulation for modulating oscillator 1 with oscillator 2 + Použít amplitudovou modulaci pro modulování oscilátoru 1 oscilátorem 2 + + + + Mix output of oscillator 1 & 2 + Smíchat výstupy oscilátorů 1 a 2 + + + + Synchronize oscillator 1 with oscillator 2 + Synchronizovat oscilátor 1 oscilátorem 2 + + + + Use frequency modulation for modulating oscillator 1 with oscillator 2 + Použít frekvenční modulaci pro modulování oscilátoru 1 oscilátorem 2 + + + + Use phase modulation for modulating oscillator 2 with oscillator 3 + Použít fázovou modulaci pro modulování oscilátoru 2 oscilátorem 3 + + + + Use amplitude modulation for modulating oscillator 2 with oscillator 3 + Použít amplitudovou modulaci pro modulování oscilátoru 2 oscilátorem 3 + + + + Mix output of oscillator 2 & 3 + Smíchat výstupy oscilátorů 2 a 3 + + + + Synchronize oscillator 2 with oscillator 3 + Synchronizovat oscilátor 2 oscilátorem 3 + + + + Use frequency modulation for modulating oscillator 2 with oscillator 3 + Použít frekvenční modulaci pro modulování oscilátoru 2 oscilátorem 3 + + + + Osc %1 volume: + Osc %1 hlasitost: + + + + With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. + Tímto otočným ovladačem můžete nastavit hlasitost oscilátoru %1. Když nastavíte hodnotu 0, oscilátor bude vypnutý. Jinak uslyšíte oscilátor tak hlasitě, jak si ho zde nastavíte. + + + + Osc %1 panning: + Osc %1 panoráma: + + + + With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. + Tímto otočným ovladačem můžete nastavit panoráma oscilátoru %1. Hodnota -100 znamená maximálně doleva, zatímco hodnota 100 přesouvá výstup oscilátoru doprava. + + + + Osc %1 coarse detuning: + Osc %1 hrubé rozladění: + + + + semitones + půltónů + + + + With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. + Tímto otočným ovladačem můžete provést hrubé rozladění oscilátoru %1. Můžete oscilátor rozladit o 24 půltónů (2 oktávy) nahoru nebo dolů. To je dobré pro vytvoření zvuku v akordu. + + + + Osc %1 fine detuning left: + Osc %1 jemné rozladění vlevo: + + + + + cents + centů + + + + With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + Tímto otočným ovladačem můžete provést jemné rozladění oscilátoru %1 v levém kanálu. Rozsah jemného rozladění je mezi -100 a +100 centy. To je dobré pro vytvoření "tlustého" zvuku. + + + + Osc %1 fine detuning right: + Osc %1 jemné rozladění vpravo: + + + + With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + Tímto otočným ovladačem můžete provést jemné rozladění oscilátoru %1 v pravém kanálu. Rozsah jemného rozladění je mezi -100 a +100 centy. To je dobré pro vytvoření "tlustého" zvuku. + + + + Osc %1 phase-offset: + Osc %1 posun fáze: + + + + + degrees + stupňů + + + + With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + Tímto otočným ovladačem můžete nastavit fázový posun oscilátoru %1. To znamená, že můžete posunout bod, ve kterém oscilátor začne kmitat. Například pokud máte sinusovou vlnu s fázovým posunem 180 stupňů, vlna půjde nejdříve dolů. Totéž se stane u vlny pravoúhlé. + + + + Osc %1 stereo phase-detuning: + Osc %1 rozladění stereo fáze: + + + + With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. + Tímto otočným ovladačem můžete nastavit rozladění fáze oscilátoru %1. Rozladění stereo fáze určuje velikost rozdílu mezi fázovým posunem levého a pravého kanálu. To je velmi dobré pro vytvoření širokého stereo zvuku. + + + + Use a sine-wave for current oscillator. + Použít sinusovou vlnu pro aktuální oscilátor. + + + + Use a triangle-wave for current oscillator. + Použít trojúhelníkovou vlnu pro aktuální oscilátor. + + + + Use a saw-wave for current oscillator. + Použít pilovitou vlnu pro aktuální oscilátor. + + + + Use a square-wave for current oscillator. + Použít pravoúhlou vlnu pro aktuální oscilátor. + + + + Use a moog-like saw-wave for current oscillator. + Použít pilovitou vlnu typu Moog pro tento oscilátor. + + + + Use an exponential wave for current oscillator. + Použít exponenciální vlnu pro aktuální oscilátor. + + + + Use white-noise for current oscillator. + Použít bílý šum pro aktuální oscilátor. + + + + Use a user-defined waveform for current oscillator. + Použít vlastní vlnu pro aktuální oscilátor. + + + + VersionedSaveDialog + + + Increment version number + Zvýšit číslo verze + + + + Decrement version number + Snížení čísla verze + + + + already exists. Do you want to replace it? + již existuje. Přejete si jej přepsat? + + + + VestigeInstrumentView + + + Open other VST-plugin + Otevřít jiný VST plugin + + + + Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. + Klepněte sem, pokud chcete otevřít jiný VST plugin. Po klepnutí na toto tlačítko se objeví okno, ve kterém můžete soubor vybrat. + + + + Control VST-plugin from LMMS host + Ovládání VST pluginu hostitelským programem LMMS + + + + Click here, if you want to control VST-plugin from host. + Klepněte sem, pokud chcete ovládat VST plugin hostitelským programem. + + + + Open VST-plugin preset + Otevřít předvolbu VST pluginu + + + + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + Klepněte sem, chcete-li otevřít jinou *.fxp, *.fxb předvolbu VST pluginu. + + + + Previous (-) + Předchozí (-) + + + + + Click here, if you want to switch to another VST-plugin preset program. + Klepněte sem, chcete-li přepnout na jiný přednastavený VST program. + + + + Save preset + Uložit předvolbu + + + + Click here, if you want to save current VST-plugin preset program. + Klepněte sem, chcete-li uložit aktuální předvolbu programu VST pluginu. + + + + Next (+) + Další (+) + + + + Click here to select presets that are currently loaded in VST. + Klepněte sem, chcete-li vybrat předvolby, které jsou aktuálně nahrány ve VST. + + + + Show/hide GUI + Zobrazit/Skrýt grafické rozhraní + + + + Click here to show or hide the graphical user interface (GUI) of your VST-plugin. + Klepněte sem pro zobrazení nebo skrytí grafického rozhraní (GUI) pro vaše VST pluginy. + + + + Turn off all notes + Vypnout všechny noty + + + + Open VST-plugin + Otevřít jiný VST plugin + + + + DLL-files (*.dll) + DLL soubory (*.dll) + + + + EXE-files (*.exe) + EXE soubory (*.exe) + + + + No VST-plugin loaded + VST plugin není nahrán + + + + Preset + Předvolba + + + + by + od + + + + - VST plugin control + – ovládání VST pluginu + + + + VisualizationWidget + + + click to enable/disable visualization of master-output + klepněte pro zapnutí/vypnutí vizualizace hlavního výstupu + + + + Click to enable + Klepněte pro zapnutí + + + + VstEffectControlDialog + + + Show/hide + Ukázat/Skrýt + + + + Control VST-plugin from LMMS host + Ovládání VST pluginu hostitelským programem LMMS + + + + Click here, if you want to control VST-plugin from host. + Klepněte sem, pokud chcete ovládat VST plugin hostitelským programem. + + + + Open VST-plugin preset + Otevřít předvolbu VST pluginu + + + + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + Klepněte sem, chcete-li otevřít jinou *.fxp, *.fxb předvolbu VST pluginu. + + + + Previous (-) + Předchozí (-) + + + + + Click here, if you want to switch to another VST-plugin preset program. + Klepněte sem, chcete-li přepnout na jiný přednastavený VST program. + + + + Next (+) + Další (+) + + + + Click here to select presets that are currently loaded in VST. + Klepněte sem, chcete-li vybrat předvolby, které jsou aktuálně nahrány ve VST. + + + + Save preset + Uložit předvolbu + + + + Click here, if you want to save current VST-plugin preset program. + Klepněte sem, chcete-li uložit aktuální předvolbu programu VST pluginu. + + + + + Effect by: + Efekt od: + + + + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + + + + VstPlugin + + + + The VST plugin %1 could not be loaded. + VST plugin %1 nelze načíst. + + + + Open Preset + Otevřít předvolbu + + + + + Vst Plugin Preset (*.fxp *.fxb) + Předvolba VST pluginu (*.fxp *.fxb) + + + + : default + : výchozí + + + + " + " + + + + ' + ' + + + + Save Preset + Uložit předvolbu + + + + .fxp + .fxp + + + + .FXP + .FXP + + + + .FXB + .FXB + + + + .fxb + .fxb + + + + Loading plugin + Načítám plugin + + + + Please wait while loading VST plugin... + Počkejte prosím, než se načte VST plugin... + + + + WatsynInstrument + + + Volume A1 + Hlasitost A1 + + + + Volume A2 + Hlasitost A2 + + + + Volume B1 + Hlasitost B1 + + + + Volume B2 + Hlasitost B2 + + + + Panning A1 + Panoráma A1 + + + + Panning A2 + Panoráma A2 + + + + Panning B1 + Panoráma B1 + + + + Panning B2 + Panoráma B2 + + + + Freq. multiplier A1 + Násobič frekv. A1 + + + + Freq. multiplier A2 + Násobič frekv. A2 + + + + Freq. multiplier B1 + Násobič frekv. B1 + + + + Freq. multiplier B2 + Násobič frekv. B2 + + + + Left detune A1 + Rozladění vlevo A1 + + + + Left detune A2 + Rozladění vlevo A2 + + + + Left detune B1 + Rozladění vlevo B1 + + + + Left detune B2 + Rozladění vlevo B2 + + + + Right detune A1 + Rozladění vpravo A1 + + + + Right detune A2 + Rozladění vpravo A2 + + + + Right detune B1 + Rozladění vpravo B1 + + + + Right detune B2 + Rozladění vpravo B2 + + + + A-B Mix + Směšovač A-B + + + + A-B Mix envelope amount + Množství obálky směšovače A-B + + + + A-B Mix envelope attack + Náběh obálky směšovače A-B + + + + A-B Mix envelope hold + Množství zadržení směšovače A-B + + + + A-B Mix envelope decay + Pokles obálky směšovače A-B + + + + A1-B2 Crosstalk + Přeslech A1-B2 + + + + A2-A1 modulation + Modulace A1-B2 + + + + B2-B1 modulation + Modulace B2-B1 + + + + Selected graph + Zvolený graf + + + + WatsynView + + + + + + Volume + Hlasitost + + + + + + + Panning + Panoráma + + + + + + + Freq. multiplier + Násobič frekv. + + + + + + + Left detune + Rozladění vlevo + + + + + + + + + + + cents + centů + + + + + + + Right detune + Rozladění vpravo + + + + A-B Mix + Směšovač A-B + + + + Mix envelope amount + Množství obálky směšovače + + + + Mix envelope attack + Náběh obálky směšovače + + + + Mix envelope hold + Zadržení obálky směšovače + + + + Mix envelope decay + Pokles obálky směšovače + + + + Crosstalk + Přeslech + + + + Select oscillator A1 + Vybrat oscilátor A1 + + + + Select oscillator A2 + Vybrat oscilátor A2 + + + + Select oscillator B1 + Vybrat oscilátor B1 + + + + Select oscillator B2 + Vybrat oscilátor B2 + + + + Mix output of A2 to A1 + Přimíchat výstup A1 do A2 + + + + Modulate amplitude of A1 with output of A2 + Modulovat amplitudu A1 výstupem A2 + + + + Ring-modulate A1 and A2 + Kruhově modulovat A1 a A2 + + + + Modulate phase of A1 with output of A2 + Modulovat fázi A1 výstupem A2 + + + + Mix output of B2 to B1 + Přimíchat výstup B1 do B2 + + + + Modulate amplitude of B1 with output of B2 + Modulovat amplitudu B1 výstupem B2 + + + + Ring-modulate B1 and B2 + Kruhově modulovat B1 a B2 + + + + Modulate phase of B1 with output of B2 + Modulovat fázi B1 výstupem B2 + + + + + + + Draw your own waveform here by dragging your mouse on this graph. + Kreslení vlastní křivky tahem myši na tomto grafu. + + + + Load waveform + Načíst vlnu + + + + Click to load a waveform from a sample file + Klepněte pro načtení vlny ze souboru samplů + + + + Phase left + Fáze vlevo + + + + Click to shift phase by -15 degrees + Klepněte pro posun fáze o -15 stupňů + + + + Phase right + Fáze vpravo + + + + Click to shift phase by +15 degrees + Klepněte pro posun fáze o +15 stupňů + + + + Normalize + Normalizovat + + + + Click to normalize + Klepněte pro normalizaci + + + + Invert + Převrátit + + + + Click to invert + Klepněte pro převrácení + + + + Smooth + Uhladit + + + + Click to smooth + Klepněte pro vyhlazení + + + + Sine wave + Sinusová vlna + + + + Click for sine wave + Klepněte pro sinusovou vlnu + + + + + Triangle wave + Trojúhelníková vlna + + + + Click for triangle wave + Klepněte pro trojúhelníkovou vlnu + + + + Click for saw wave + Klepněte pro pilovitou vlnu + + + + Square wave + Pravoúhlá vlna + + + + Click for square wave + Klepněte pro pravoúhlou vlnu + + + + ZynAddSubFxInstrument + + + Portamento + Portamento + + + + Filter Frequency + Frekvence filtru + + + + Filter Resonance + Rezonance filtru + + + + Bandwidth + Šířka pásma + + + + FM Gain + Zesílení FM + + + + Resonance Center Frequency + Střední frekvence rezonance + + + + Resonance Bandwidth + Šířka pásma rezonance + + + + Forward MIDI Control Change Events + Odesílat události MIDI Control Change + + + + ZynAddSubFxView + + + Portamento: + Portamento: + + + + PORT + PORT + + + + Filter Frequency: + Frekvence filtru: + + + + FREQ + FREKV + + + + Filter Resonance: + Rezonance filtru: + + + + RES + REZ + + + + Bandwidth: + Šířka pásma: + + + + BW + ŠP + + + + FM Gain: + Zesílení FM: + + + + FM GAIN + ZISK FM + + + + Resonance center frequency: + Střední frekvence rezonance: + + + + RES CF + SF REZ + + + + Resonance bandwidth: + Šířka pásma rezonance: + + + + RES BW + ŠP REZ + + + + Forward MIDI Control Changes + Odesílat MIDI Control Change + + + + Show GUI + Ukázar grafické rozhraní + + + + Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + Klepněte sem pro zobrazení nebo skrytí grafického uživatelského rozhraní (GUI) ZynAddSubFX. + + + + audioFileProcessor + + + Amplify + Zesílení + + + + Start of sample + Začátek samplu + + + + End of sample + Konec samplu + + + + Loopback point + Začátek smyčky + + + + Reverse sample + Přehrávat pozpátku + + + + Loop mode + Režim smyčky + + + + Stutter + Pokračování v přehrávání samplu při změně noty + + + + Interpolation mode + Režim interpolace + + + + None + Žádný + + + + Linear + Lineární + + + + Sinc + Sinusový + + + + Sample not found: %1 + Vzorek nenalezen: %1 + + + + bitInvader + + + Samplelength + Délka samplu + + + + bitInvaderView + + + Sample Length + Délka samplu + + + + Draw your own waveform here by dragging your mouse on this graph. + Kreslení vlastní křivky tahem myši na tomto grafu. + + + + Sine wave + Sinusová vlna + + + + Click for a sine-wave. + Klepněte sem pro sinusovou vlnu. + + + + Triangle wave + Trojúhelníková vlna + + + + Click here for a triangle-wave. + Klepněte sem pro trojúhelníkovou vlnu. + + + + Saw wave + Pilovitá vlna + + + + Click here for a saw-wave. + Klepněte sem pro pilovitou vlnu. + + + + Square wave + Pravoúhlá vlna + + + + Click here for a square-wave. + Klepněte sem pro pravoúhlou vlnu. + + + + White noise wave + Bílý šum + + + + Click here for white-noise. + Klepněte sem pro bílý šum. + + + + User defined wave + Vlna definovaná uživatelem + + + + Click here for a user-defined shape. + Klepněte sem pro uživatelem definovaný tvar. + + + + Smooth + Vyhladit + + + + Click here to smooth waveform. + Klepněte sem pro vyhlazení vlny. + + + + Interpolation + Interpolovat + + + + Normalize + Normalizovat + + + + dynProcControlDialog + + + INPUT + VSTUP + + + + Input gain: + Zesílení vstupu: + + + + OUTPUT + VÝSTUP + + + + Output gain: + Zesílení výstupu: + + + + ATTACK + NÁBĚH + + + + Peak attack time: + Délka náběhu špičky: + + + + RELEASE + UVOLNĚNÍ + + + + Peak release time: + Délka uvolnění špičky: + + + + Reset waveform + Obnovení vlny + + + + Click here to reset the wavegraph back to default + Klepněte sem pro obnovení zobrazení křivky zpět do výchozího stavu + + + + Smooth waveform + Vyhlazení vlny + + + + Click here to apply smoothing to wavegraph + Klepněte sem pro vyhlazení křivky + + + + Increase wavegraph amplitude by 1dB + Zvýšení amplitudy křivky o 1 dB + + + + Click here to increase wavegraph amplitude by 1dB + Klepněte sem pro zvýšení amplitudy křivky o 1 dB + + + + Decrease wavegraph amplitude by 1dB + Snížení amplitudy křivky o 1 dB + + + + Click here to decrease wavegraph amplitude by 1dB + Klepněte sem pro snížení amplitudy křivky o 1 dB + + + + Stereomode Maximum + Režim maximálního sterea + + + + Process based on the maximum of both stereo channels + Zpracování vycházející z maxima obou stereo kanálů + + + + Stereomode Average + Režim průměru sterea + + + + Process based on the average of both stereo channels + Zpracování vycházející z průměru obou stereo kanálů + + + + Stereomode Unlinked + Režim nepropojeného sterea + + + + Process each stereo channel independently + Zpracování každého stereo kanálu zvlášť + + + + dynProcControls + + + Input gain + Zesílení vstupu + + + + Output gain + Zesílení výstupu + + + + Attack time + Doba náběhu + + + + Release time + Délka doznění + + + + Stereo mode + Režim sterea + + + + fxLineLcdSpinBox + + + Assign to: + Přiřadit k: + + + + New FX Channel + Nový efektový kanál + + + + graphModel + + + Graph + Graf + + + + kickerInstrument + + + Start frequency + Počáteční frekvence + + + + End frequency + Konečná frekvence + + + + Length + Délka + + + + Distortion Start + Začátek zkreslení + + + + Distortion End + Konec zkreslení + + + + Gain + Zisk + + + + Envelope Slope + Sklon frekvence + + + + Noise + Šum + + + + Click + Klik + + + + Frequency Slope + Sklon frekvence + + + + Start from note + Začít od noty + + + + End to note + Skončit na notě + + + + kickerInstrumentView + + + Start frequency: + Počáteční frekvence: + + + + End frequency: + Konečná frekvence: + + + + Frequency Slope: + Sklon frekvence: + + + + Gain: + Zisk: + + + + Envelope Length: + Délka obálky: + + + + Envelope Slope: + Sklon obálky: + + + + Click: + Klik: + + + + Noise: + Šum: + + + + Distortion Start: + Začátek zkreslení: + + + + Distortion End: + Konec zkreslení: + + + + ladspaBrowserView + + + + Available Effects + Dostupné efekty + + + + + Unavailable Effects + Nedostupné efekty + + + + + Instruments + Nástroje + + + + + Analysis Tools + Analyzační nástroje + + + + + Don't know + Neznámé + + + + This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. + +Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. + +Unavailable Effects are those that were identified as effects, but either didn't have the same number of input and output channels or weren't real time capable. + +Instruments are plugins for which only output channels were identified. + +Analysis Tools are plugins for which only input channels were identified. + +Don't Knows are plugins for which no input or output channels were identified. + +Double clicking any of the plugins will bring up information on the ports. + Toto dialogové okno zobrazuje informace o všech LADSPA pluginech, které bylo LMMS schopno nalézt. Zásuvné moduly jsou rozděleny do pěti kategorií podle portů a názvů. + + +K dispozici jsou ty efekty, které mohou být použity v LMMS. Aby v LMMS bylo možné užít efektu, musí se o efekt skutečně jednat, to znamená, že musí mít oba vstupní a výstupní kanály. LMMS identifikuje vstupní kanál jako audio podle "n" v názvu. Výstupní kanály jsou identifikovány pole označení písmeny "out". Kromě toho efekt musí mít stejný počet vstupů a výstupů a být real time kompatibilní. + +Nedostupné efekty jsou ty, které byly identifikovány jako efekty, ale buď nemají stejný počet vstupních a výstupních kanálů nebo nejsou real time kompatibilní. + +Nástroje jsou pluginy u kterých byly identifikovány pouze výstupní kanály. + +Analyzační nástroje jsou pluginy u kterých byly identifikovány pouze vstupní kanály. + +Neznámé jsou pluginy, pro které nebyly identifikovány žádné vstupní nebo výstupní kanály. + +Poklepáním na kterýkoliv modul se zobrazí informace o portech. + + + + Type: + Typ: + + + + ladspaDescription + + + Plugins + Pluginy + + + + Description + Popis + + + + ladspaPortDialog + + + Ports + Porty + + + + Name + Název + + + + Rate + Druh + + + + Direction + Směr + + + + Type + Typ + + + + Min < Default < Max + Min < Výchozí < Max + + + + Logarithmic + Logaritmický + + + + SR Dependent + SR závislý + + + + Audio + Zvuk + + + + Control + Ovládání + + + + Input + Vstup + + + + Output + Výstup + + + + Toggled + Zapnuto + + + + Integer + Celočíselný + + + + Float + S plovoucí čárkou + + + + + Yes + Ano + + + + lb302Synth + + + VCF Cutoff Frequency + VCF frekvence vypnutí + + + + VCF Resonance + VCF rezonance + + + + VCF Envelope Mod + VCF modulace obálky + + + + VCF Envelope Decay + VCF útlum obálky + + + + Distortion + Zkreslení + + + Waveform Vlna - Slide Decay - Útlum sklouznutí + + Slide Decay + Útlum sklouznutí + + + + Slide + Sklouznutí + + + + Accent + Důraz + + + + Dead + Dead + + + + 24dB/oct Filter + Filtr 24dB/okt + + + + lb302SynthView + + + Cutoff Freq: + Frekvence odstřihnutí: + + + + Resonance: + Rezonance: + + + + Env Mod: + Modulace obálky: + + + + Decay: + Útlum: + + + + 303-es-que, 24dB/octave, 3 pole filter + 3pólový filtr 303-es-que, 24dB/okt + + + + Slide Decay: + Útlum sklouznutí: + + + + DIST: + Zkreslení: + + + + Saw wave + Pilovitá vlna + + + + Click here for a saw-wave. + Klepněte sem pro pilovitou vlnu. + + + + Triangle wave + Trojúhelníková vlna + + + + Click here for a triangle-wave. + Klepněte sem pro trojúhelníkovou vlnu. + + + + Square wave + Pravoúhlá vlna + + + + Click here for a square-wave. + Klepněte sem pro pravoúhlou vlnu. + + + + Rounded square wave + Oblá pravoúhlá vlna + + + + Click here for a square-wave with a rounded end. + Klepněte sem pro pravoúhlou vlnu s oblým zakončením. + + + + Moog wave + Vlna typu Moog + + + + Click here for a moog-like wave. + Klepněte sem pro vlnu typu Moog. + + + + Sine wave + Sinusová vlna + + + + Click for a sine-wave. + Klepněte sem pro sinusovou vlnu. + + + + + White noise wave + Bílý šum + + + + Click here for an exponential wave. + Klepněte sem pro exponenciální vlnu. + + + + Click here for white-noise. + Klepněte sem pro bílý šum. + + + + Bandlimited saw wave + Pásmově omezená pilovitá vlna + + + + Click here for bandlimited saw wave. + Klepněte sem pro pásmově omezenou pilovitou vlnu. + + + + Bandlimited square wave + Pásmově zúžená pravoúhlá vlna + + + + Click here for bandlimited square wave. + Klepněte sem pro pásmově zúženou pravoúhlou vlnu. + + + + Bandlimited triangle wave + Pásmově zúžená trojúhelníková vlna + + + + Click here for bandlimited triangle wave. + Klepněte sem pro pásmově zúženou trojúhelníkovou vlnu. + + + + Bandlimited moog saw wave + Pásmově zúžená pilovitá vlna typu Moog + + + + Click here for bandlimited moog saw wave. + Klepněte sem pro úzkopásmovou pilovitou vlnu typu Moog. + + + + malletsInstrument + + + Hardness + Tvrdost + + + + Position + Pozice + + + + Vibrato Gain + Zisk vibráta + + + + Vibrato Freq + Frekvence vibráta + + + + Stick Mix + Mix paliček + + + + Modulator + Modulátor + + + + Crossfade + Prolínání (crossfade) + + + + LFO Speed + LFO Rychlost + + + + LFO Depth + LFO Hloubka + + + + ADSR + ADSR + + + + Pressure + Tlak + + + + Motion + Pohyb + + + + Speed + Rychlost + + + + Bowed + Smyčcem + + + + Spread + Šíře + + + + Marimba + Marimba + + + + Vibraphone + Vibrafon + + + + Agogo + Agogo + + + + Wood1 + Dřevo1 + + + + Reso + Rezo + + + + Wood2 + Dřevo2 + + + + Beats + Údery + + + + Two Fixed + Dvě spojené + + + + Clump + Svazek + + + + Tubular Bells + Trubicové zvony + + + + Uniform Bar + Obyčejná tyč + + + + Tuned Bar + Laděná tyč + + + + Glass + Sklo + + + + Tibetan Bowl + Tibetská zpívající mísa + + + + malletsInstrumentView + + + Instrument + Nástroj + + + + Spread + Šíře + + + + Spread: + Šíře: - Slide - Sklouznutí + + Missing files + Chybějící soubory - Accent - Důraz + + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! + Zdá se, že instalace Stk není kompletní. Ujistěte se prosím, že je nainstalován celý balík Stk! - Dead - Dead + + Hardness + Tvrdost - 24dB/oct Filter - Filtr 24dB/okt + + Hardness: + Tvrdost: + + + + Position + Pozice + + + + Position: + Pozice: + + + + Vib Gain + Vib zisk + + + + Vib Gain: + Vib zisk: + + + + Vib Freq + Vib frekv + + + + Vib Freq: + Vib frekv: + + + + Stick Mix + Mix paliček + + + + Stick Mix: + Mix paliček: + + + + Modulator + Modulátor + + + + Modulator: + Modulátor: + + + + Crossfade + Prolínání (crossfade) + + + + Crossfade: + Prolínání (crossfade): + + + + LFO Speed + LFO Rychlost + + + + LFO Speed: + LFO Rychlost: + + + + LFO Depth + LFO Hloubka + + + + LFO Depth: + LFO Hloubka: + + + + ADSR + ADSR + + + + ADSR: + ADSR: + + + + Pressure + Tlak + + + + Pressure: + Tlak: + + + + Speed + Rychlost + + + + Speed: + Rychlost: - lb302SynthView + manageVSTEffectView - Cutoff Freq: - Frekvence odstřihnutí: + + - VST parameter control + - řízení parametrů VST - Resonance: - Rezonance: + + VST Sync + VST synch - Env Mod: - Modulace obálky: + + Click here if you want to synchronize all parameters with VST plugin. + Klepněte sem, chcete-li synchronizovat všechny parametry s VST pluginem. - Decay: - Útlum: + + + Automated + Automaticky - 303-es-que, 24dB/octave, 3 pole filter - 3pólový filtr 303-es-que, 24dB/okt + + Click here if you want to display automated parameters only. + Klepněte sem, pokud chcete pouze zobrazit parametry automatizace. - Slide Decay: - Útlum sklouznutí: + + Close + Zavřít - DIST: - Zkreslení: + + Close VST effect knob-controller window. + Zavřít okno otočných ovladačů VST efektu. + + + manageVestigeInstrumentView - Saw wave - Pilovitá vlna + + + - VST plugin control + - ovládání VST pluginu - Click here for a saw-wave. - Klepněte sem pro pilovitou vlnu. + + VST Sync + VST synch - Triangle wave - Trojúhelníková vlna + + Click here if you want to synchronize all parameters with VST plugin. + Klepněte sem, chcete-li synchronizovat všechny parametry s VST pluginem. - Click here for a triangle-wave. - Klepněte sem pro trojúhelníkovou vlnu. + + + Automated + Automaticky - Square wave - Pravoúhlá vlna + + Click here if you want to display automated parameters only. + Klepněte sem, pokud chcete pouze zobrazit parametry automatizace. - Click here for a square-wave. - Klepněte sem pro pravoúhlou vlnu. + + Close + Zavřít - Rounded square wave - Oblá pravoúhlá vlna + + Close VST plugin knob-controller window. + Zavřít okno otočných ovladačů VST pluginu. + + + opl2instrument - Click here for a square-wave with a rounded end. - Klepněte sem pro pravoúhlou vlnu s oblým zakončením. + + Patch + Patch - Moog wave - Vlna typu Moog + + Op 1 Attack + Op 1 náběh - Click here for a moog-like wave. - Klepněte sem pro vlnu typu Moog. + + Op 1 Decay + Op 1 útlum - Sine wave - Sinusová vlna + + Op 1 Sustain + Op 1 vydržení - Click for a sine-wave. - Klepněte sem pro sinusovou vlnu. + + Op 1 Release + Op 1 uvolnění - White noise wave - Bílý šum + + Op 1 Level + Op 1 úroveň - Click here for an exponential wave. - Klepněte sem pro exponenciální vlnu. + + Op 1 Level Scaling + Op 1 škálování úrovně - Click here for white-noise. - Klepněte sem pro bílý šum. + + Op 1 Frequency Multiple + Op 1 násobení frekvence - Bandlimited saw wave - Pásmově omezená pilovitá vlna + + Op 1 Feedback + Op 1 zpětná vazba - Click here for bandlimited saw wave. - Klepněte sem pro pásmově omezenou pilovitou vlnu. + + Op 1 Key Scaling Rate + Op 1 rychlost podle výšky klávesy - Bandlimited square wave - Pásmově zúžená pravoúhlá vlna + + Op 1 Percussive Envelope + Op 1 perkusivní obálka - Click here for bandlimited square wave. - Klepněte sem pro pásmově zúženou pravoúhlou vlnu. + + Op 1 Tremolo + Op 1 tremolo - Bandlimited triangle wave - Pásmově zúžená trojúhelníková vlna + + Op 1 Vibrato + Op 1 vibrato - Click here for bandlimited triangle wave. - Klepněte sem pro pásmově zúženou trojúhelníkovou vlnu. + + Op 1 Waveform + Op 1 vlna - Bandlimited moog saw wave - Pásmově zúžená pilovitá vlna typu Moog + + Op 2 Attack + Op 2 náběh - Click here for bandlimited moog saw wave. - Klepněte sem pro úzkopásmovou pilovitou vlnu typu Moog. + + Op 2 Decay + Op 2 útlum + + + + Op 2 Sustain + Op 2 vydržení + + + + Op 2 Release + Op 2 uvolnění + + + + Op 2 Level + Op 2 úroveň + + + + Op 2 Level Scaling + Op 2 škálování úrovně + + + + Op 2 Frequency Multiple + Op 2 násobení frekvence + + + + Op 2 Key Scaling Rate + Op 2 rychlost podle výšky klávesy + + + + Op 2 Percussive Envelope + Op 2 perkusivní obálka + + + + Op 2 Tremolo + Op 2 tremolo + + + + Op 2 Vibrato + Op 2 vibrato + + + + Op 2 Waveform + Op 2 tvar vlny + + + + FM + FM + + + + Vibrato Depth + Hloubka vibráta + + + + Tremolo Depth + Hloubka tremola - malletsInstrument + opl2instrumentView - Hardness - Tvrdost + + + Attack + Náběh - Position - Pozice + + + Decay + Útlum - Modulator - Modulátor + + + Release + Doznění - Crossfade - Prolínání (crossfade) + + + Frequency multiplier + Násobič frekvence + + + organicInstrument - ADSR - ADSR + + Distortion + Zkreslení - Pressure - Tlak + + Volume + Hlasitost + + + organicInstrumentView - Motion - Pohyb + + Distortion: + Zkreslení: - Speed - Rychlost + + The distortion knob adds distortion to the output of the instrument. + Otočný ovladač zkreslení přidá zkreslení k výstupu nástroje. - Bowed - Smyčcem + + Volume: + Hlasitost: + + + + The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. + Otočný ovladač hlasitosti ovládá hlasitost výstupu nástroje. Sčítá se s ovládáním hlasitosti okna nástroje. + + + + Randomise + Nastavit náhodně + + + + The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. + Tlačítko Randomize náhodně nastaví všechny ovladače kromě ovladače harmonických, hlavní hlasitosti a zkreslení. + + + + + Osc %1 waveform: + Osc %1 vlna: + + + + Osc %1 volume: + Osc %1 hlasitost: + + + + Osc %1 panning: + Osc %1 panoráma: - Spread - Šíře + + Osc %1 stereo detuning + Osc %1 rozladění sterea - Marimba - Marimba + + cents + centů - Vibraphone - Vibrafon + + Osc %1 harmonic: + Osc %1 harmonické: + + + FreeBoyInstrument - Agogo - Agogo + + Sweep time + Trvání sweepu - Reso - Rezo + + Sweep direction + Směr sweepu - Beats - Údery + + Sweep RtShift amount + Úroveň pro změnu frekvence sweepu - Clump - Svazek + + + Wave Pattern Duty + Pracovní cyklus vlnového patternu - Glass - Sklo + + Channel 1 volume + Hlasitost kanálu 1 - Vibrato gain - + + + + Volume sweep direction + Směr hlasitosti sweepu - Vibrato frequency - + + + + Length of each step in sweep + Délka každého kroku ve sweepu - Stick mix - + + Channel 2 volume + Hlasitost kanálu 2 - LFO speed - Rychlost LFO + + Channel 3 volume + Hlasitost kanálu 3 - LFO depth - + + Channel 4 volume + Hlasitost kanálu 4 - Wood 1 - + + Shift Register width + Posun šířky registru - Wood 2 - + + Right Output level + Úroveň pravého výstupu - Two fixed - + + Left Output level + Úroveň levého výstupu - Tubular bells - + + Channel 1 to SO2 (Left) + Kanál 1 do SO2 (pravý) - Uniform bar - + + Channel 2 to SO2 (Left) + Kanál 2 do SO2 (pravý) - Tuned bar - + + Channel 3 to SO2 (Left) + Kanál 3 do SO2 (pravý) - Tibetan bowl - + + Channel 4 to SO2 (Left) + Kanál 4 do SO2 (pravý) - - - malletsInstrumentView - Instrument - Nástroj + + Channel 1 to SO1 (Right) + Kanál 1 do SO1 (pravý) - Spread - Šíře + + Channel 2 to SO1 (Right) + Kanál 2 do SO1 (pravý) - Spread: - Šíře: + + Channel 3 to SO1 (Right) + Kanál 3 do SO1 (pravý) - Hardness - Tvrdost + + Channel 4 to SO1 (Right) + Kanál 4 do SO1 (pravý) - Hardness: - Tvrdost: + + Treble + Výšky - Position - Pozice + + Bass + Basy + + + FreeBoyInstrumentView - Position: - Pozice: + + Sweep Time: + Trvání sweepu: - Modulator - Modulátor + + Sweep Time + Trvání sweepu - Modulator: - Modulátor: + + The amount of increase or decrease in frequency + Množství zvýšení nebo snížení frekvence - Crossfade - Prolínání (crossfade) + + Sweep RtShift amount: + Úroveň pro změnu frekvence sweepu: - Crossfade: - Prolínání (crossfade): + + Sweep RtShift amount + Úroveň pro změnu frekvence sweepu - ADSR - ADSR + + The rate at which increase or decrease in frequency occurs + Úroveň, při které dojde ke zvýšení nebo snížení frekvence - ADSR: - ADSR: + + + Wave pattern duty: + Pracovní cyklus vlnového patternu: - Pressure - Tlak + + Wave Pattern Duty + Pracovní cyklus vlnového patternu - Pressure: - Tlak: + + + The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. + Pracovní cyklus je poměr mezi dobou trvání (časem), kdy je signál zapnut, a celkovou délkou signálu. - Speed - Rychlost + + + Square Channel 1 Volume: + Hlasitost pulzního kanálu 1: - Speed: - Rychlost: + + Square Channel 1 Volume + Hlasitost pulzního kanálu 1 - Missing files - Chybějící soubory + + + + Length of each step in sweep: + Délka každého kroku ve sweepu: - Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! - Zdá se, že instalace Stk není kompletní. Ujistěte se prosím, že je nainstalován celý balík Stk! + + + + Length of each step in sweep + Délka každého kroku ve sweepu - Vibrato gain - + + + + The delay between step change + Zpoždění mezi změnou kroku - Vibrato gain: - + + Wave pattern duty + Pracovní cyklus vlnového patternu - Vibrato frequency - + + Square Channel 2 Volume: + Hlasitost pulzního kanálu 2: - Vibrato frequency: - + + + Square Channel 2 Volume + Hlasitost pulzního kanálu 2 - Stick mix - + + Wave Channel Volume: + Hlasitost vlnového kanálu: - Stick mix: - + + + Wave Channel Volume + Hlasitost vlnového kanálu - LFO speed - Rychlost LFO + + Noise Channel Volume: + Hlasitost šumového kanálu: - LFO speed: - Rychlost LFO: + + + Noise Channel Volume + Hlasitost šumového kanálu - LFO depth - + + SO1 Volume (Right): + Hlasitost SO1 (pravý): - LFO depth: - + + SO1 Volume (Right) + Hlasitost SO1 (pravý) - - - manageVSTEffectView - - VST parameter control - - řízení parametrů VST + + SO2 Volume (Left): + Hlasitost SO2 (levý): - Automated - Automaticky + + SO2 Volume (Left) + Hlasitost SO2 (levý) - Close - Zavřít + + Treble: + Výšky: - VST sync - + + Treble + Výšky - - - manageVestigeInstrumentView - - VST plugin control - - ovládání VST pluginu + + Bass: + Basy: - VST Sync - VST synch + + Bass + Basy - Automated - Automaticky + + Sweep Direction + Směr sweepu - Close - Zavřít + + + + + + Volume Sweep Direction + Směr hlasitosti sweepu - - - organicInstrument - Distortion - Zkreslení + + Shift Register Width + Posun šířky registru - Volume - Hlasitost + + Channel1 to SO1 (Right) + Kanál 1 do SO1 (pravý) - - - organicInstrumentView - Distortion: - Zkreslení: + + Channel2 to SO1 (Right) + Kanál 2 do SO1 (pravý) - Volume: - Hlasitost: + + Channel3 to SO1 (Right) + Kanál 3 do SO1 (pravý) - Randomise - Nastavit náhodně + + Channel4 to SO1 (Right) + Kanál 4 do SO1 (pravý) - Osc %1 waveform: - Osc %1 vlna: + + Channel1 to SO2 (Left) + Kanál 1 do SO2 (levý) - Osc %1 volume: - Osc %1 hlasitost: + + Channel2 to SO2 (Left) + Kanál 2 do SO2 (levý) - Osc %1 panning: - Osc %1 panoráma: + + Channel3 to SO2 (Left) + Kanál 3 do SO2 (levý) - cents - centů + + Channel4 to SO2 (Left) + Kanál 4 do SO2 (levý) - Osc %1 stereo detuning - Osc %1 rozladění sterea + + Wave Pattern + Vlnový pattern - Osc %1 harmonic: - Osc %1 harmonické: + + Draw the wave here + Nakreslete vlnu zde patchesDialog + Qsynth: Channel Preset Qsynth: Předvolba kanálu + Bank selector Výběr banky + Bank Banka + Program selector Výběr programu + Patch Patch + Name Název + OK OK + Cancel Zrušit @@ -4310,182 +11747,231 @@ pluginBrowser - Incomplete monophonic imitation tb303 - Nekompletní monofonní imitace tb303 + + no description + bez popisu - Plugin for freely manipulating stereo output - Plugin pro volné úpravy stereo výstupu + + A native amplifier plugin + Nativní plugin zesilovače - Plugin for controlling knobs with sound peaks - Plugin pro řízení otočných ovladačů zvukovými špičkami + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + Jednoduchý sampler s bohatým nastavením pro používání samplů (např. bicích nástrojů) v nástrojové stopě - Plugin for enhancing stereo separation of a stereo input file - Plugin pro zlepšení stereo separace vstupních stereo souborů + + Boost your bass the fast and simple way + Zesílení vašeho basu rychlým a snadným způsobem - List installed LADSPA plugins - Seznam nainstalovaných LADSPA pluginů + + Customizable wavetable synthesizer + Upravitelný tabulkový syntezátor - GUS-compatible patch instrument - GUS kompatibilní patch instrument + + An oversampling bitcrusher + Bitcrusher založený na převzorkování - Additive Synthesizer for organ-like sounds - Aditivní syntezátor pro zvuky podobné varhanám + + Carla Patchbay Instrument + Nástroj Carla Patchbay - Tuneful things to bang on - Melodické bicí nástroje + + Carla Rack Instrument + Nástroj Carla Rack - VST-host for using VST(i)-plugins within LMMS - VST host pro užití VST(i) pluginů v LMMS + + A 4-band Crossover Equalizer + 4 pásmový crossover ekvalizér - Vibrating string modeler - Vibrační modelátor strun + + A native delay plugin + Nativní plugin delay - plugin for using arbitrary LADSPA-effects inside LMMS. - plugin pro užití libovolných LADSPA efektů uvnitř LMMS. + + A Dual filter plugin + Plugin duální filtr - Filter for importing MIDI-files into LMMS - Filtr pro import MIDI souborů do LMMS + + plugin for processing dynamics in a flexible way + plugin pro flexibilní práci s dynamikou - Emulation of the MOS6581 and MOS8580 SID. -This chip was used in the Commodore 64 computer. - Emulace MOS6581 a MOS8580 SID. -Tento čip byl používán v počítačích Commodore 64. + + A native eq plugin + Nativní plugin ekvalizér - Player for SoundFont files - Přehrávač SoundFont souborů + + A native flanger plugin + Nativní plugin flanger - Emulation of GameBoy (TM) APU - Emulace APU GameBoye (TM) + + Player for GIG files + Přehrávač GIG souborů - Customizable wavetable synthesizer - Upravitelný tabulkový syntezátor + + Filter for importing Hydrogen files into LMMS + Filtr pro import souborů Hydrogen do LMMS - Embedded ZynAddSubFX - Vestavěný ZynAddSubFX + + Versatile drum synthesizer + Univerzální syntezátor bicích nástrojů + + + + List installed LADSPA plugins + Seznam nainstalovaných LADSPA pluginů + + + + plugin for using arbitrary LADSPA-effects inside LMMS. + plugin pro užití libovolných LADSPA efektů uvnitř LMMS. - 2-operator FM Synth - 2 operátorová FM syntéza + + Incomplete monophonic imitation tb303 + Nekompletní monofonní imitace tb303 - Filter for importing Hydrogen files into LMMS - Filtr pro import souborů Hydrogen do LMMS + + Filter for exporting MIDI-files from LMMS + Filtr pro export souborů MIDI z LMMS - LMMS port of sfxr - LMMS port sfxr + + Filter for importing MIDI-files into LMMS + Filtr pro import MIDI souborů do LMMS + Monstrous 3-oscillator synth with modulation matrix 3oscilátorový syntezátor Monstrous s modulační matricí - Three powerful oscillators you can modulate in several ways - 3 silné oscilátory, které můžete různými způsoby modulovat + + A multitap echo delay plugin + Plugin multi-tap delay - A native amplifier plugin - Nativní plugin zesilovače + + A NES-like synthesizer + Syntetizér typu NES - Carla Rack Instrument - Nástroj Carla Rack + + 2-operator FM Synth + 2 operátorová FM syntéza - 4-oscillator modulatable wavetable synth - 4oscilátorový modulovatelný tabulkový syntezátor + + Additive Synthesizer for organ-like sounds + Aditivní syntezátor pro zvuky podobné varhanám - plugin for waveshaping - plugin pro tvarování vln + + Emulation of GameBoy (TM) APU + Emulace APU GameBoye (TM) - Boost your bass the fast and simple way - Zesílení vašeho basu rychlým a snadným způsobem + + GUS-compatible patch instrument + GUS kompatibilní patch instrument - Versatile drum synthesizer - Univerzální syntezátor bicích nástrojů + + Plugin for controlling knobs with sound peaks + Plugin pro řízení otočných ovladačů zvukovými špičkami - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - Jednoduchý sampler s bohatým nastavením pro používání samplů (např. bicích nástrojů) v nástrojové stopě + + Reverb algorithm by Sean Costello + Algoritmus dozvuku od Seana Costello - plugin for processing dynamics in a flexible way - plugin pro flexibilní práci s dynamikou + + Player for SoundFont files + Přehrávač SoundFont souborů - Carla Patchbay Instrument - Nástroj Carla Patchbay + + LMMS port of sfxr + LMMS port sfxr - plugin for using arbitrary VST effects inside LMMS. - Plugin pro použití libovolného VST efektu v LMMS. + + Emulation of the MOS6581 and MOS8580 SID. +This chip was used in the Commodore 64 computer. + Emulace MOS6581 a MOS8580 SID. +Tento čip byl používán v počítačích Commodore 64. + Graphical spectrum analyzer plugin Plugin pro grafickou analýzu spektra - A NES-like synthesizer - Syntetizér typu NES - - - A native delay plugin - Nativní plugin delay + + Plugin for enhancing stereo separation of a stereo input file + Plugin pro zlepšení stereo separace vstupních stereo souborů - Player for GIG files - Přehrávač GIG souborů + + Plugin for freely manipulating stereo output + Plugin pro volné úpravy stereo výstupu - A multitap echo delay plugin - Plugin multi-tap delay + + Tuneful things to bang on + Melodické bicí nástroje - A native flanger plugin - Nativní plugin flanger + + Three powerful oscillators you can modulate in several ways + 3 silné oscilátory, které můžete různými způsoby modulovat - An oversampling bitcrusher - Bitcrusher založený na převzorkování + + VST-host for using VST(i)-plugins within LMMS + VST host pro užití VST(i) pluginů v LMMS - A native eq plugin - Nativní plugin ekvalizér + + Vibrating string modeler + Vibrační modelátor strun - A 4-band Crossover Equalizer - 4 pásmový crossover ekvalizér + + plugin for using arbitrary VST effects inside LMMS. + Plugin pro použití libovolného VST efektu v LMMS. - A Dual filter plugin - Plugin duální filtr + + 4-oscillator modulatable wavetable synth + 4oscilátorový modulovatelný tabulkový syntezátor - Filter for exporting MIDI-files from LMMS - Filtr pro export souborů MIDI z LMMS + + plugin for waveshaping + plugin pro tvarování vln - Reverb algorithm by Sean Costello - Algoritmus dozvuku od Seana Costello + + Embedded ZynAddSubFX + Vestavěný ZynAddSubFX Mathematical expression parser @@ -4495,264 +11981,400 @@ Tento čip byl používán v počítačích Commodore 64. sf2Instrument + Bank Banka + Patch Patch + Gain Zisk + Reverb Dozvuk - Chorus - Chorus + + Reverb Roomsize + Velikost dozvukového prostoru - A soundfont %1 could not be loaded. - Soundfont %1 nelze načíst. + + Reverb Damping + Útlum dozvuku - Reverb room size - + + Reverb Width + Délka dozvuku - Reverb damping - + + Reverb Level + Úroveň dozvuku - Reverb width - + + Chorus + Chorus - Reverb level - + + Chorus Lines + Počet linií chorusu - Chorus voices - + + Chorus Level + Úroveň chorusu - Chorus level - + + Chorus Speed + Rychlost chorusu - Chorus speed - + + Chorus Depth + Hloubka chorusu - Chorus depth - + + A soundfont %1 could not be loaded. + Soundfont %1 nelze načíst. sf2InstrumentView + + Open other SoundFont file + Otevřít jiný SoundFont soubor + + + + Click here to open another SF2 file + Klepněte sem pro otevření jiného SF2 souboru + + + + Choose the patch + Vybrat patch + + + + Gain + Zesílení + + + Apply reverb (if supported) Použít dozvuk (je-li podporován) - Apply chorus (if supported) - Použít chorus (je-li podporován) + + This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. + Tímto tlačítkem zapnete efekt dozvuk (reverb). Ten lze použít pro výborné efekty, ale funguje pouze se soubory, které jej podporují. - Open SoundFont file - Otevřít SoundFont soubor + + Reverb Roomsize: + Velikost dozvukového prostoru: - Choose patch - + + Reverb Damping: + Útlum dozvuku: - Gain: - + + Reverb Width: + Délka dozvuku: + + + + Reverb Level: + Úroveň dozvuku: - Room size: - + + Apply chorus (if supported) + Použít chorus (je-li podporován) - Damping: - + + This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. + Tímto tlačítkem zapnete efekt chorus. Ten lze použít pro výborné echo efekty, ale funguje pouze se soubory, které jej podporují. - Width: - Šířka: + + Chorus Lines: + Počet linií chorusu: - Level: - + + Chorus Level: + Úroveň chorusu: - Voices: - + + Chorus Speed: + Rychlost chorusu: - Speed: - Rychlost: + + Chorus Depth: + Hloubka chorusu: - Depth: - Hloubka: + + Open SoundFont file + Otevřít SoundFont soubor - SoundFont Files (*.sf2 *.sf3) - + + SoundFont2 Files (*.sf2) + Soubory SoundFont2 (*.sf2) sfxrInstrument - Wave - + + Wave Form + Vlna sidInstrument + + Cutoff + Oříznutí + + + Resonance Rezonance + Filter type Typ filtru + Voice 3 off Vypnout hlas 3 + Volume Hlasitost + Chip model Model čipu - - Cutoff frequency - Frekvence oříznutí - sidInstrumentView + Volume: Hlasitost: + Resonance: Rezonance: + + Cutoff frequency: Frekvence oříznutí: + + High-Pass filter + Filtr typu horní propust + + + + Band-Pass filter + Filtr typu pásmová propust + + + + Low-Pass filter + Filtr typu dolní propust + + + + Voice3 Off + Vypnout hlas 3 + + + MOS6581 SID MOS6581 SID + MOS8580 SID MOS8580 SID + + Attack: Náběh: + + Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. + Rychlost náběhu určuje, jak rychle výstup hlasu %1 stoupne z nuly na špičkovou amplitudu. + + + + Decay: Útlum: + + Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. + Rychlost útlumu (decay) určuje, jak rychle poklesne výstup ze špičky na zvolenou úroveň vydržení (sustain). + + + Sustain: Vydržení: + + Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. + Výstup hlasu %1 zůstane na zvolené úrovni Vydržení po celou dobu, kdy bude nota držena. + + + + Release: Uvolnění: + + The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. + Výstup hlasu %1 poklesne z úrovně vydržení (sustain) na nulovou amplitudu zvolenou rychlostí uvolnění (release). + + + + Pulse Width: Délka pulzu: + + The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. + Rozlišení šířky pulsu umožňuje plynulé vyhlazení šířky, aby nebylo rozeznatelné krokování. Pulzní vlna na oscilátoru %1 musí být zvolena tak, aby měla slyšitelný efekt. + + + Coarse: Ladění: - Noise - Šum + + The Coarse detuning allows to detune Voice %1 one octave up or down. + Hrubé rozladění umožní rozladit hlas %1 až o jednu oktávu nahoru nebo dolů. - Sync - Synch + + Pulse Wave + Pulzní vlna - Filtered - Filtrování + + Triangle Wave + Trojúhelníková vlna - Test - Test + + SawTooth + Pilovitá vlna - High-pass filter - + + Noise + Šum - Band-pass filter - + + Sync + Synch - Low-pass filter - + + Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. + Synchronizace synchronizuje základní frekvenci oscilátoru %1 se základní frekvencí oscilátoru %2 pomocí efektu pevné (Hard Sync) synchronizace. - Voice 3 off - + + Ring-Mod + Kruhová modulace - Pulse wave - + + Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. + Kruhová modulace nahradí výstup trojúhelníkové vlny na oscilátoru %1 "kruhově modulovanou" kombinací oscilátorů %1 a %2. - Triangle wave - Trojúhelníková vlna + + Filtered + Filtrování - Saw wave - Pilovitá vlna + + When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. + Pokud je zapnuto filtrování, hlas %1 bude zpracován filtrem. Pokud je filtrování vypnuto, hlas %1 se objeví přímo na výstupu a filtr na něj nebude mít žádný efekt. - Ring modulation - + + Test + Test - Pulse width: - + + Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. + Test, když je nastaven, resetuje a zablokuje oscilátor %1 na nule, dokud se test nevypne. stereoEnhancerControlDialog - Width: - Šířka: + + WIDE + ŠÍŘKA - WIDTH - + + Width: + Šířka: stereoEnhancerControls + Width Šířka @@ -4760,18 +12382,22 @@ Tento čip byl používán v počítačích Commodore 64. stereoMatrixControlDialog + Left to Left Vol: Levý do levého – hlasitost: + Left to Right Vol: Levý do pravého – hlasitost: + Right to Left Vol: Pravý do levého – hlasitost: + Right to Right Vol: Pravý do pravého – hlasitost: @@ -4779,18 +12405,22 @@ Tento čip byl používán v počítačích Commodore 64. stereoMatrixControls + Left to Left Levý do levého + Left to Right Levý do pravého + Right to Left Pravý do levého + Right to Right Pravý do pravého @@ -4798,191 +12428,373 @@ Tento čip byl používán v počítačích Commodore 64. vestigeInstrument + Loading plugin Načítám plugin - Please wait while loading the VST plugin... - + + Please wait while loading VST-plugin... + Počkejte prosím, než se načte VST plugin... vibed + String %1 volume Hlasitost struny %1 + String %1 stiffness Tvrdost struny %1 + Pick %1 position Místo drnknutí %1 + Pickup %1 position Umístění snímače %1 - Impulse %1 - Impulz %1 + + Pan %1 + Pan %1 - String %1 panning - + + Detune %1 + Rozladění %1 - String %1 detune - + + Fuzziness %1 + Roztřepení %1 - String %1 fuzziness - + + Length %1 + Délka %1 - String %1 length - + + Impulse %1 + Impulz %1 - String %1 - + + Octave %1 + Oktáva %1 vibedView + + Volume: + Hlasitost: + + + + The 'V' knob sets the volume of the selected string. + Otočný ovladač "V" nastavuje hlasitost vybrané struny. + + + String stiffness: Tvrdost struny: + + The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. + Otočný ovladač "S" nastavuje tvrdost vybrané struny. Tvrdost struny ovlivňuje délku doznívání struny. Čím nižší hodnota, tím déle bude struna znít. + + + Pick position: Místo drnknutí: + + The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. + Otočný ovladač "P" nastavuje místo, ve kterém se na vybrané struně drnkne. Nižší nastavení znamená drnknutí blíže ke kobylce. + + + Pickup position: Pozice snímače: + + The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. + Otočný ovladač "PU" nastavuje umístění snímače pro vybranou strunu. Nižší nastavení znamená snímač blíže u kobylky. + + + + Pan: + Panoráma: + + + + The Pan knob determines the location of the selected string in the stereo field. + Otočný ovladač "Pan" určuje pozici vybrané struny ve stereo prostoru. + + + + Detune: + Rozladění: + + + + The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. + Otočný ovladač "Detune" mění ladění vybrané struny. Hodnoty nižší než nula způsobí plochý zvuk, hodnoty vyšší než nula způsobí ostřejší zvuk. + + + + Fuzziness: + Roztřepení: + + + + The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. + Otočný ovladač "Slap" přidává ke zvuku vybrané struny jemné roztřepení, které je nejvíce patrné při náběhu tónu, ačkoliv lze také použít pro vytvoření více "kovového" zvuku struny. + + + + Length: + Délka: + + + + The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. + Otočný ovladač "Lenght" nastavuje délku vybrané struny. Delší struny budou znít déle a jasněji, nicméně však spotřebují více CPU cyklů. + + + + Impulse or initial state + Impulz nebo výchozí stav + + + + The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. + Přepínač "IMP" určuje, zda vlna v grafu bude považována za impulz přenášený na strunu drnknutím nebo za počáteční stav struny. + + + Octave Oktáva + + The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. + Volič "Octave" se používá k výběru harmonického tónu, na kterém bude struna znít. Například "-2" znamená, že struna bude znít dvě oktávy pod základním tónem, "F" znamená, že zní základní tón a "6" znamená, že struna bude znít šest oktáv nad základním tónem. + + + Impulse Editor Editor impulzu + + The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. + +The waveform can also be drawn in the graph. + +The 'S' button will smooth the waveform. + +The 'N' button will normalize the waveform. + Editor vlny poskytuje kontrolu nad výchozím stavem nebo impulzem, který je použit k rozvibrování struny. Tlačítka na pravé straně grafu inicializují vlnový průběh vybraného typu. Tlačítko "?" načte vlnu ze souboru – bude načteno pouze prvních 128 vzorků. + +Vlna může být také nakreslena v grafu. + +Tlačítko "S" vyhladí vlnu. + +Tlačítko "N" normalizuje vlnu. + + + + Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. + +The graph allows you to control the initial state or impulse used to set the string in motion. + +The 'V' knob controls the volume. The 'S' knob controls the string's stiffness. The 'P' knob controls the pick position. The 'PU' knob controls the pickup position. + +'Pan' and 'Detune' hopefully don't need explanation. The 'Slap' knob adds a bit of fuzz to the sound of the string. + +The 'Length' knob controls the length of the string. + +The LED in the lower right corner of the waveform editor determines whether the string is active in the current instrument. + Vibed simuluje až devět nezávisle vibrujících strun. Volič "String" vám umožní vybrat, kterou strunu budete upravovat. Pomocí voliče "Imp" vyberete, jestli graf představuje impulz nebo výchozí stav struny. Voličem "Octave" vyberete, na kterém harmonickém tónu má struna vibrovat. + +Graf vám umožňuje řízení výchozího stavu nebo impulzu použitého pro nastavení pohybu struny. + +Otočný ovladač "V" řídí hlasitost. Ovladač "S" nastavuje tvrdost struny. Ovladač "P" určuje pozici drnknutí. Ovladač "PU" nastavuje pozici snímače. + +"Pan" a "Detune" snad není třeba vysvětlovat. Ovladač "Slap" přidá ke zvuku struny jemné rozostření. + +Ovladač "Lenght" určuje délku struny. + +LED v pravém dolním rohu editoru vlny určuje, jestli bude struna v aktuálním nástroji aktivní. + + + Enable waveform Zapnout vlnu + + Click here to enable/disable waveform. + Klepněte sem pro zapnutí/vypnutí vlny. + + + String Struna + + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + Volič strun se užívá k výběru struny, které bude upravována. Nástroj Vibed může obsahovat maximálně devět nezávisle vibrujících strun. LED v pravém dolním rohu editoru tvaru vlny indikuje, zda je vybraná struna aktivní. + + + Sine wave Sinusová vlna + + Use a sine-wave for current oscillator. + Použít sinusovou vlnu pro aktuální oscilátor. + + + Triangle wave Trojúhelníková vlna - Saw wave - Pilovitá vlna + + Use a triangle-wave for current oscillator. + Použít trojúhelníkovou vlnu pro aktuální oscilátor. - Square wave - Pravoúhlá vlna + + Saw wave + Pilovitá vlna - String volume: - + + Use a saw-wave for current oscillator. + Použít pilovitou vlnu pro aktuální oscilátor. - String panning: - + + Square wave + Pravoúhlá vlna - String detune: - + + Use a square-wave for current oscillator. + Použít pravoúhlou vlnu pro aktuální oscilátor. - String fuzziness: - + + White noise wave + Bílý šum - String length: - + + Use white-noise for current oscillator. + Použít bílý šum pro aktuální oscilátor. - Impulse - + + User defined wave + Vlna definovaná uživatelem - Enable/disable string - + + Use a user-defined waveform for current oscillator. + Použít vlastní vlnu pro aktuální oscilátor. - White noise - Bílý šum + + Smooth + Vyhladit - User-defined wave - + + Click here to smooth waveform. + Klepněte sem pro vyhlazení vlny. - Smooth waveform - + + Normalize + Normalizovat - Normalize waveform - + + Click here to normalize waveform. + Klepněte sem pro normalizaci vlny. voiceObject + Voice %1 pulse width Hlas %1 šířka pulzu + Voice %1 attack Hlas %1 náběh + Voice %1 decay Hlas %1 útlum + Voice %1 sustain Hlas %1 vydržení + Voice %1 release Hlas %1 uvolnění + Voice %1 coarse detuning Hlas %1 hrubé ladění + Voice %1 wave shape Hlas %1 tvar vlny + Voice %1 sync Hlas %1 synchronizace + Voice %1 ring modulate Hlas %1 kruhová modulace + Voice %1 filtered Hlas %1 filtrování + Voice %1 test Hlas %1 test @@ -4990,53 +12802,85 @@ Tento čip byl používán v počítačích Commodore 64. waveShaperControlDialog + INPUT VSTUP + Input gain: Zesílení vstupu: + OUTPUT VÝSTUP + Output gain: Zesílení výstupu: - Clip input - Vstup klipu + + Reset waveform + Obnovení vlny + + + + Click here to reset the wavegraph back to default + Klepněte sem pro obnovení zobrazení křivky zpět do výchozího stavu - Reset wavegraph - + + Smooth waveform + Vyhlazení vlny + + + + Click here to apply smoothing to wavegraph + Klepněte sem pro vyhlazení křivky + + + + Increase graph amplitude by 1dB + Zvýši amplitudu grafu o 1dB + + + + Click here to increase wavegraph amplitude by 1dB + Klepněte sem pro zvýšení amplitudy křivky o 1 dB - Smooth wavegraph - + + Decrease graph amplitude by 1dB + Snížit amplitudu grafu o 1dB - Increase wavegraph amplitude by 1 dB - + + Click here to decrease wavegraph amplitude by 1dB + Klepněte sem pro snížení amplitudy křivky o 1 dB - Decrease wavegraph amplitude by 1 dB - + + Clip input + Ořezat vstup - Clip input signal to 0 dB - + + Clip input signal to 0dB + Vstupní úroveň klipu 0dB waveShaperControls + Input gain Zesílení vstupu + Output gain Zesílení výstupu diff --git a/data/locale/en.ts b/data/locale/en.ts index 1c9f2ee8f1e..f20bfaac27c 100644 --- a/data/locale/en.ts +++ b/data/locale/en.ts @@ -1,37 +1,114 @@ + + AboutDialog + + + About LMMS + + + + + LMMS + + + + + Version %1 (%2/%3, Qt %4, %5). + + + + + About + + + + + LMMS - easy music production for everyone. + + + + + Copyright © %1. + + + + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#33cc33;">https://lmms.io</span></a></p></body></html> + + + + + Authors + + + + + Involved + + + + + Contributors ordered by number of commits: + + + + + Translation + + + + + Current language not translated (or native English). +If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! + + + + + License + + + AmplifierControlDialog + VOL + Volume: + PAN + Panning: + LEFT + Left gain: + RIGHT + Right gain: @@ -39,2764 +116,9036 @@ AmplifierControls + Volume + Panning + Left gain + Right gain + + AudioAlsaSetupWidget + + + DEVICE + + + + + CHANNELS + + + AudioFileProcessorView + Open sample + Reverse sample + Disable loop + Enable loop + + Enable ping-pong loop + + + + Continue sample playback across notes + Amplify: + Start point: + End point: + Loopback point: - - Enable ping-pong loop - - AudioFileProcessorWaveView + Sample length: - BassBoosterControlDialog + AudioJack - FREQ + + JACK client restarted - Frequency: + + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. - GAIN + + JACK server down - Gain: + + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. - RATIO + + CLIENT-NAME - Ratio: + + CHANNELS - BassBoosterControls + AudioOss - Frequency + + DEVICE - Gain + + CHANNELS + + + AudioPortAudio::setupWidget - Ratio + + BACKEND + + + + + DEVICE - BitcrushControlDialog + AudioPulseAudio - IN + + DEVICE - OUT + + CHANNELS + + + AudioSdl::setupWidget - GAIN + + DEVICE + + + AudioSndio - Input gain: + + DEVICE - NOISE + + CHANNELS + + + AudioSoundIo::setupWidget - Input noise: + + BACKEND - Output gain: + + DEVICE + + + AutomatableModel - CLIP + + &Reset (%1%2) - Output clip: + + &Copy value (%1%2) - Rate enabled + + &Paste value (%1%2) - Enable sample-rate crushing + + &Paste value - Depth enabled + + Edit song-global automation - Enable bit-depth crushing + + Remove song-global automation - FREQ + + Remove all linked controls - Sample rate: + + Connected to %1 - STEREO + + Connected to controller - Stereo difference: + + Edit connection... - QUANT + + Remove connection - Levels: + + Connect to controller... - BitcrushControls - - Input gain - - + AutomationEditor - Input noise + + Please open an automation pattern with the context menu of a control! - Output gain + + Values copied - Output clip + + All selected values were copied to the clipboard. + + + AutomationEditorWindow - Sample rate + + Play/pause current pattern (Space) - Stereo difference + + Stop playing of current pattern (Space) - Levels + + Edit actions - Rate enabled + + Draw mode (Shift+D) - Depth enabled + + Erase mode (Shift+E) - - - CarlaInstrumentView - Show GUI + + Flip vertically - - - CrossoverEQControlDialog - Band 1/2 crossover: + + Flip horizontally - Band 2/3 crossover: + + Interpolation controls - Band 3/4 crossover: + + Discrete progression - Band 1 gain + + Linear progression - Band 1 gain: + + Cubic Hermite progression - Band 2 gain + + Tension value for spline - Band 2 gain: + + Tension: - Band 3 gain + + Cut selected values (%1+X) - Band 3 gain: + + Copy selected values (%1+C) - Band 4 gain + + Paste values from clipboard (%1+V) - Band 4 gain: + + Zoom controls - Band 1 mute + + Horizontal zooming - Mute band 1 + + Vertical zooming - Band 2 mute + + Quantization controls - Mute band 2 + + Quantization - Band 3 mute + + + Automation Editor - no pattern - Mute band 3 + + + Automation Editor - %1 - Band 4 mute + + Model is already connected to this pattern. + + + AutomationPattern - Mute band 4 + + Drag a control while pressing <%1> - DelayControls + AutomationPatternView - Delay samples + + Open in Automation editor - Feedback + + Clear - LFO frequency + + Reset name - LFO amount + + Change name - Output gain + + Set/clear record - - - DelayControlsDialog - DELAY + + Flip Vertically (Visible) - Delay time + + Flip Horizontally (Visible) - FDBK + + %1 Connections - Feedback amount + + Disconnect "%1" - RATE + + Model is already connected to this pattern. + + + AutomationTrack - LFO frequency + + Automation track + + + BBEditor - AMNT + + Beat+Bassline Editor - LFO amount + + Play/pause current beat/bassline (Space) - Out gain + + Stop playback of current beat/bassline (Space) - Gain + + Beat selector - - - DualFilterControlDialog - FREQ + + Track and step actions - Cutoff frequency + + Add beat/bassline - RESO + + Add sample-track - Resonance + + Add automation-track - GAIN + + Remove steps - Gain + + Add steps - MIX + + Clone Steps + + + BBTCOView - Mix + + Open in Beat+Bassline-Editor - Filter 1 enabled + + Reset name - Filter 2 enabled + + Change name - Enable/disable filter 1 + + Change color - Enable/disable filter 2 + + Reset color to default - DualFilterControls + BBTrack - Filter 1 enabled + + Beat/Bassline %1 - Filter 1 type + + Clone of %1 + + + BassBoosterControlDialog - Cutoff frequency 1 + + FREQ - Q/Resonance 1 + + Frequency: - Gain 1 + + GAIN - Mix + + Gain: - Filter 2 enabled + + RATIO - Filter 2 type + + Ratio: + + + BassBoosterControls - Cutoff frequency 2 + + Frequency - Q/Resonance 2 + + Gain - Gain 2 + + Ratio + + + BitcrushControlDialog - Low-pass + + IN - Hi-pass + + OUT - Band-pass csg + + + GAIN - Band-pass czpg + + Input gain: - Notch + + NOISE - All-pass + + Input noise: - Moog + + Output gain: - 2x Low-pass + + CLIP - RC Low-pass 12 dB/oct + + Output clip: - RC Band-pass 12 dB/oct + + Rate enabled - RC High-pass 12 dB/oct + + Enable sample-rate crushing - RC Low-pass 24 dB/oct + + Depth enabled - RC Band-pass 24 dB/oct + + Enable bit-depth crushing - RC High-pass 24 dB/oct + + FREQ - Vocal Formant + + Sample rate: - 2x Moog + + STEREO - SV Low-pass + + Stereo difference: - SV Band-pass + + QUANT - SV High-pass + + Levels: + + + BitcrushControls - SV Notch + + Input gain + + + + + Input noise + + + + + Output gain + + + + + Output clip + + + + + Sample rate + + + + + Stereo difference + + + + + Levels + + + + + Rate enabled + + + + + Depth enabled + + + + + CarlaInstrumentView + + + Show GUI + + + + + Controller + + + Controller %1 + + + + + ControllerConnectionDialog + + + Connection Settings + + + + + MIDI CONTROLLER + + + + + Input channel + + + + + CHANNEL + + + + + Input controller + + + + + CONTROLLER + + + + + + Auto Detect + + + + + MIDI-devices to receive MIDI-events from + + + + + USER CONTROLLER + + + + + MAPPING FUNCTION + + + + + OK + + + + + Cancel + + + + + LMMS + + + + + Cycle Detected. + + + + + ControllerRackView + + + Controller Rack + + + + + Add + + + + + Confirm Delete + + + + + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. + + + + + ControllerView + + + Controls + + + + + Rename controller + + + + + Enter the new name for this controller + + + + + LFO + + + + + &Remove this controller + + + + + Re&name this controller + + + + + CrossoverEQControlDialog + + + Band 1/2 crossover: + + + + + Band 2/3 crossover: + + + + + Band 3/4 crossover: + + + + + Band 1 gain + + + + + Band 1 gain: + + + + + Band 2 gain + + + + + Band 2 gain: + + + + + Band 3 gain + + + + + Band 3 gain: + + + + + Band 4 gain + + + + + Band 4 gain: + + + + + Band 1 mute + + + + + Mute band 1 + + + + + Band 2 mute + + + + + Mute band 2 + + + + + Band 3 mute + + + + + Mute band 3 + + + + + Band 4 mute + + + + + Mute band 4 + + + + + DelayControls + + + Delay samples + + + + + Feedback + + + + + LFO frequency + + + + + LFO amount + + + + + Output gain + + + + + DelayControlsDialog + + + DELAY + + + + + Delay time + + + + + FDBK + + + + + Feedback amount + + + + + RATE + + + + + LFO frequency + + + + + AMNT + + + + + LFO amount + + + + + Out gain + + + + + Gain + + + + + DualFilterControlDialog + + + + FREQ + + + + + + Cutoff frequency + + + + + + RESO + + + + + + Resonance + + + + + + GAIN + + + + + + Gain + + + + + MIX + + + + + Mix + + + + + Filter 1 enabled + + + + + Filter 2 enabled + + + + + Enable/disable filter 1 + + + + + Enable/disable filter 2 + + + + + DualFilterControls + + + Filter 1 enabled + + + + + Filter 1 type + + + + + Cutoff frequency 1 + + + + + Q/Resonance 1 + + + + + Gain 1 + + + + + Mix + + + + + Filter 2 enabled + + + + + Filter 2 type + + + + + Cutoff frequency 2 + + + + + Q/Resonance 2 + + + + + Gain 2 + + + + + + Low-pass + + + + + + Hi-pass + + + + + + Band-pass csg + + + + + + Band-pass czpg + + + + + + Notch + + + + + + All-pass + + + + + + Moog + + + + + + 2x Low-pass + + + + + + RC Low-pass 12 dB/oct + + + + + + RC Band-pass 12 dB/oct + + + + + + RC High-pass 12 dB/oct + + + + + + RC Low-pass 24 dB/oct + + + + + + RC Band-pass 24 dB/oct + + + + + + RC High-pass 24 dB/oct + + + + + + Vocal Formant + + + + + + 2x Moog + + + + + + SV Low-pass + + + + + + SV Band-pass + + + + + + SV High-pass + + + + + + SV Notch + + + + + + Fast Formant + + + + + + Tripole + + + + + Editor + + + Transport controls + + + + + Play (Space) + + + + + Stop (Space) + + + + + Record + + + + + Record while playing + + + + + Toggle Step Recording + + + + + Effect + + + Effect enabled + + + + + Wet/Dry mix + + + + + Gate + + + + + Decay + + + + + EffectChain + + + Effects enabled + + + + + EffectRackView + + + EFFECTS CHAIN + + + + + Add effect + + + + + EffectSelectDialog + + + Add effect + + + + + + Name + + + + + Type + + + + + Description + + + + + Author + + + + + EffectView + + + On/Off + + + + + W/D + + + + + Wet Level: + + + + + DECAY + + + + + Time: + + + + + GATE + + + + + Gate: + + + + + Controls + + + + + Move &up + + + + + Move &down + + + + + &Remove this plugin + + + + + EnvelopeAndLfoParameters + + + Env pre-delay + + + + + Env attack + + + + + Env hold + + + + + Env decay + + + + + Env sustain + + + + + Env release + + + + + Env mod amount + + + + + LFO pre-delay + + + + + LFO attack + + + + + LFO frequency + + + + + LFO mod amount + + + + + LFO wave shape + + + + + LFO frequency x 100 + + + + + Modulate env amount + + + + + EnvelopeAndLfoView + + + + DEL + + + + + + Pre-delay: + + + + + + ATT + + + + + + Attack: + + + + + HOLD + + + + + Hold: + + + + + DEC + + + + + Decay: + + + + + SUST + + + + + Sustain: + + + + + REL + + + + + Release: + + + + + + AMT + + + + + + Modulation amount: + + + + + SPD + + + + + Frequency: + + + + + FREQ x 100 + + + + + Multiply LFO frequency by 100 + + + + + MODULATE ENV AMOUNT + + + + + Control envelope amount by this LFO + + + + + ms/LFO: + + + + + Hint + + + + + Drag and drop a sample into this window. + + + + + EqControls + + + Input gain + + + + + Output gain + + + + + Low-shelf gain + + + + + Peak 1 gain + + + + + Peak 2 gain + + + + + Peak 3 gain + + + + + Peak 4 gain + + + + + High-shelf gain + + + + + HP res + + + + + Low-shelf res + + + + + Peak 1 BW + + + + + Peak 2 BW + + + + + Peak 3 BW + + + + + Peak 4 BW + + + + + High-shelf res + + + + + LP res + + + + + HP freq + + + + + Low-shelf freq + + + + + Peak 1 freq + + + + + Peak 2 freq + + + + + Peak 3 freq + + + + + Peak 4 freq + + + + + High-shelf freq + + + + + LP freq + + + + + HP active + + + + + Low-shelf active + + + + + Peak 1 active + + + + + Peak 2 active + + + + + Peak 3 active + + + + + Peak 4 active + + + + + High-shelf active + + + + + LP active + + + + + LP 12 + + + + + LP 24 + + + + + LP 48 + + + + + HP 12 + + + + + HP 24 + + + + + HP 48 + + + + + Low-pass type + + + + + High-pass type + + + + + Analyse IN + + + + + Analyse OUT + + + + + EqControlsDialog + + + HP + + + + + Low-shelf + + + + + Peak 1 + + + + + Peak 2 + + + + + Peak 3 + + + + + Peak 4 + + + + + High-shelf + + + + + LP + + + + + Input gain + + + + + + + Gain + + + + + Output gain + + + + + Bandwidth: + + + + + Octave + + + + + Resonance : + + + + + Frequency: + + + + + LP group + + + + + HP group + + + + + EqHandle + + + Reso: + + + + + BW: + + + + + + Freq: + + + + + ExportProjectDialog + + + Export project + + + + + Export as loop (remove extra bar) + + + + + Export between loop markers + + + + + Render Looped Section: + + + + + time(s) + + + + + File format settings + + + + + File format: + + + + + Sampling rate: + + + + + 44100 Hz + + + + + 48000 Hz + + + + + 88200 Hz + + + + + 96000 Hz + + + + + 192000 Hz + + + + + Bit depth: + + + + + 16 Bit integer + + + + + 24 Bit integer + + + + + 32 Bit float + + + + + Stereo mode: + + + + + Mono + + + + + Stereo + + + + + Joint stereo + + + + + Compression level: + + + + + Bitrate: + + + + + 64 KBit/s + + + + + 128 KBit/s + + + + + 160 KBit/s + + + + + 192 KBit/s + + + + + 256 KBit/s + + + + + 320 KBit/s + + + + + Use variable bitrate + + + + + Quality settings + + + + + Interpolation: + + + + + Zero order hold + + + + + Sinc worst (fastest) + + + + + Sinc medium (recommended) + + + + + Sinc best (slowest) + + + + + Oversampling: + + + + + 1x (None) + + + + + 2x + + + + + 4x + + + + + 8x + + + + + Start + + + + + Cancel + + + + + Could not open file + + + + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + + + + + Export project to %1 + + + + + ( Fastest - biggest ) + + + + + ( Slowest - smallest ) + + + + + Error + + + + + Error while determining file-encoder device. Please try to choose a different output format. + + + + + Rendering: %1% + + + + + Fader + + + + Set value + + + + + + Please enter a new value between %1 and %2: + + + + + FileBrowser + + + Browser + + + + + Search + + + + + Refresh list + + + + + FileBrowserTreeWidget + + + Send to active instrument-track + + + + + Open in new instrument-track/Song Editor + + + + + Open in new instrument-track/B+B Editor + + + + + Loading sample + + + + + Please wait, loading sample for preview... + + + + + Error + + + + + does not appear to be a valid + + + + + file + + + + + --- Factory files --- + + + + + FlangerControls + + + Delay samples + + + + + LFO frequency + + + + + Seconds + + + + + Regen + + + + + Noise + + + + + Invert + + + + + FlangerControlsDialog + + + DELAY + + + + + Delay time: + + + + + RATE + + + + + Period: + + + + + AMNT + + + + + Amount: + + + + + FDBK + + + + + Feedback amount: + + + + + NOISE + + + + + White noise amount: + + + + + Invert + + + + + FreeBoyInstrument + + + Sweep time + + + + + Sweep direction + + + + + Sweep rate shift amount + + + + + + Wave pattern duty cycle + + + + + Channel 1 volume + + + + + + + Volume sweep direction + + + + + + + Length of each step in sweep + + + + + Channel 2 volume + + + + + Channel 3 volume + + + + + Channel 4 volume + + + + + Shift Register width + + + + + Right output level + + + + + Left output level + + + + + Channel 1 to SO2 (Left) + + + + + Channel 2 to SO2 (Left) + + + + + Channel 3 to SO2 (Left) + + + + + Channel 4 to SO2 (Left) + + + + + Channel 1 to SO1 (Right) + + + + + Channel 2 to SO1 (Right) + + + + + Channel 3 to SO1 (Right) + + + + + Channel 4 to SO1 (Right) + + + + + Treble + + + + + Bass + + + + + FreeBoyInstrumentView + + + Sweep time: + + + + + Sweep time + + + + + Sweep rate shift amount: + + + + + Sweep rate shift amount + + + + + + Wave pattern duty cycle: + + + + + + Wave pattern duty cycle + + + + + Square channel 1 volume: + + + + + Square channel 1 volume + + + + + + + Length of each step in sweep: + + + + + + + Length of each step in sweep + + + + + Square channel 2 volume: + + + + + Square channel 2 volume + + + + + Wave pattern channel volume: + + + + + Wave pattern channel volume + + + + + Noise channel volume: + + + + + Noise channel volume + + + + + SO1 volume (Right): + + + + + SO1 volume (Right) + + + + + SO2 volume (Left): + + + + + SO2 volume (Left) + + + + + Treble: + + + + + Treble + + + + + Bass: + + + + + Bass + + + + + Sweep direction + + + + + + + + + Volume sweep direction + + + + + Shift register width + + + + + Channel 1 to SO1 (Right) + + + + + Channel 2 to SO1 (Right) + + + + + Channel 3 to SO1 (Right) + + + + + Channel 4 to SO1 (Right) + + + + + Channel 1 to SO2 (Left) + + + + + Channel 2 to SO2 (Left) + + + + + Channel 3 to SO2 (Left) + + + + + Channel 4 to SO2 (Left) + + + + + Wave pattern graph + + + + + FxLine + + + Channel send amount + + + + + Move &left + + + + + Move &right + + + + + Rename &channel + + + + + R&emove channel + + + + + Remove &unused channels + + + + + FxLineLcdSpinBox + + + Assign to: + + + + + New FX Channel + + + + + FxMixer + + + Master + + + + + + + FX %1 + + + + + Volume + + + + + Mute + + + + + Solo + + + + + FxMixerView + + + FX-Mixer + + + + + FX Fader %1 + + + + + Mute + + + + + Mute this FX channel + + + + + Solo + + + + + Solo FX channel + + + + + FxRoute + + + + Amount to send from channel %1 to channel %2 + + + + + GigInstrument + + + Bank + + + + + Patch + + + + + Gain + + + + + GigInstrumentView + + + + Open GIG file + + + + + Choose patch + + + + + Gain: + + + + + GIG Files (*.gig) + + + + + GuiApplication + + + Working directory + + + + + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. + + + + + Preparing UI + + + + + Preparing song editor + + + + + Preparing mixer + + + + + Preparing controller rack + + + + + Preparing project notes + + + + + Preparing beat/bassline editor + + + + + Preparing piano roll + + + + + Preparing automation editor + + + + + InstrumentFunctionArpeggio + + + Arpeggio + + + + + Arpeggio type + + + + + Arpeggio range + + + + + Cycle steps + + + + + Skip rate + + + + + Miss rate + + + + + Arpeggio time + + + + + Arpeggio gate + + + + + Arpeggio direction + + + + + Arpeggio mode + + + + + Up + + + + + Down + + + + + Up and down + + + + + Down and up + + + + + Random + + + + + Free + + + + + Sort + + + + + Sync + + + + + InstrumentFunctionArpeggioView + + + ARPEGGIO + + + + + RANGE + + + + + Arpeggio range: + + + + + octave(s) + + + + + CYCLE + + + + + Cycle notes: + + + + + note(s) + + + + + SKIP + + + + + Skip rate: + + + + + + + % + + + + + MISS + + + + + Miss rate: + + + + + TIME + + + + + Arpeggio time: + + + + + ms + + + + + GATE + + + + + Arpeggio gate: + + + + + Chord: + + + + + Direction: + + + + + Mode: + + + + + InstrumentFunctionNoteStacking + + + octave + + + + + + Major + + + + + Majb5 + + + + + minor + + + + + minb5 + + + + + sus2 + + + + + sus4 + + + + + aug + + + + + augsus4 + + + + + tri + + + + + 6 + + + + + 6sus4 + + + + + 6add9 + + + + + m6 + + + + + m6add9 + + + + + 7 + + + + + 7sus4 + + + + + 7#5 + + + + + 7b5 + + + + + 7#9 + + + + + 7b9 + + + + + 7#5#9 + + + + + 7#5b9 + + + + + 7b5b9 + + + + + 7add11 + + + + + 7add13 + + + + + 7#11 + + + + + Maj7 + + + + + Maj7b5 + + + + + Maj7#5 + + + + + Maj7#11 + + + + + Maj7add13 + + + + + m7 + + + + + m7b5 + + + + + m7b9 + + + + + m7add11 + + + + + m7add13 + + + + + m-Maj7 + + + + + m-Maj7add11 + + + + + m-Maj7add13 + + + + + 9 + + + + + 9sus4 + + + + + add9 + + + + + 9#5 + + + + + 9b5 + + + + + 9#11 + + + + + 9b13 + + + + + Maj9 + + + + + Maj9sus4 + + + + + Maj9#5 + + + + + Maj9#11 + + + + + m9 + + + + + madd9 + + + + + m9b5 + + + + + m9-Maj7 + + + + + 11 + + + + + 11b9 + + + + + Maj11 + + + + + m11 + + + + + m-Maj11 + + + + + 13 + + + + + 13#9 + + + + + 13b9 + + + + + 13b5b9 + + + + + Maj13 + + + + + m13 + + + + + m-Maj13 + + + + + Harmonic minor + + + + + Melodic minor + + + + + Whole tone + + + + + Diminished + + + + + Major pentatonic + + + + + Minor pentatonic + + + + + Jap in sen + + + + + Major bebop + + + + + Dominant bebop + + + + + Blues + + + + + Arabic + + + + + Enigmatic + + + + + Neopolitan + + + + + Neopolitan minor + + + + + Hungarian minor + + + + + Dorian + + + + + Phrygian + + + + + Lydian + + + + + Mixolydian + + + + + Aeolian + + + + + Locrian + + + + + Minor + + + + + Chromatic + + + + + Half-Whole Diminished + + + + + 5 + + + + + Phrygian dominant + + + + + Persian + + + + + Chords + + + + + Chord type + + + + + Chord range + + + + + InstrumentFunctionNoteStackingView + + + STACKING + + + + + Chord: + + + + + RANGE + + + + + Chord range: + + + + + octave(s) + + + + + InstrumentMidiIOView + + + ENABLE MIDI INPUT + + + + + + CHANNEL + + + + + + VELOCITY + + + + + ENABLE MIDI OUTPUT + + + + + PROGRAM + + + + + NOTE + + + + + MIDI devices to receive MIDI events from + + + + + MIDI devices to send MIDI events to + + + + + CUSTOM BASE VELOCITY + + + + + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity. + + + + + BASE VELOCITY + + + + + InstrumentMiscView + + + MASTER PITCH + + + + + Enables the use of master pitch + + + + + InstrumentSoundShaping + + + VOLUME + + + + + Volume + + + + + CUTOFF + + + + + + Cutoff frequency + + + + + RESO + + + + + Resonance + + + + + Envelopes/LFOs + + + + + Filter type + + + + + Q/Resonance + + + + + Low-pass + + + + + Hi-pass + + + + + Band-pass csg + + + + + Band-pass czpg + + + + + Notch + + + + + All-pass + + + + + Moog + + + + + 2x Low-pass + + + + + RC Low-pass 12 dB/oct + + + + + RC Band-pass 12 dB/oct + + + + + RC High-pass 12 dB/oct + + + + + RC Low-pass 24 dB/oct + + + + + RC Band-pass 24 dB/oct + + + + + RC High-pass 24 dB/oct + + + + + Vocal Formant + + + + + 2x Moog + + + + + SV Low-pass + + + + + SV Band-pass + + + + + SV High-pass + + + + + SV Notch + + + + + Fast Formant + + + + + Tripole + + + + + InstrumentSoundShapingView + + + TARGET + + + + + FILTER + + + + + FREQ + + + + + Cutoff frequency: + + + + + Hz + + + + + Q/RESO + + + + + Q/Resonance: + + + + + Envelopes, LFOs and filters are not supported by the current instrument. + + + + + InstrumentTrack + + + With this knob you can set the volume of the opened channel. + + + + + + unnamed_track + + + + + Base note + + + + + Volume + + + + + Panning + + + + + Pitch + + + + + Pitch range + + + + + FX channel + + + + + Master pitch + + + + + + Default preset + + + + + InstrumentTrackView + + + Volume + + + + + Volume: + + + + + VOL + + + + + Panning + + + + + Panning: + + + + + PAN + + + + + MIDI + + + + + Input + + + + + Output + + + + + FX %1: %2 + + + + + InstrumentTrackWindow + + + GENERAL SETTINGS + + + + + Volume + + + + + Volume: + + + + + VOL + + + + + Panning + + + + + Panning: + + + + + PAN + + + + + Pitch + + + + + Pitch: + + + + + cents + + + + + PITCH + + + + + Pitch range (semitones) + + + + + RANGE + + + + + FX channel + + + + + FX + + + + + Save current instrument track settings in a preset file + + + + + SAVE + + + + + Envelope, filter & LFO + + + + + Chord stacking & arpeggio + + + + + Effects + + + + + MIDI + + + + + Miscellaneous + + + + + Save preset + + + + + XML preset file (*.xpf) + + + + + Plugin + + + + + Knob + + + Set linear + + + + + Set logarithmic + + + + + + Set value + + + + + Please enter a new value between -96.0 dBFS and 6.0 dBFS: + + + + + Please enter a new value between %1 and %2: + + + + + LadspaControl + + + Link channels + + + + + LadspaControlDialog + + + Link Channels + + + + + Channel + + + + + LadspaControlView + + + Link channels + + + + + Value: + + + + + LadspaEffect + + + Unknown LADSPA plugin %1 requested. + + + + + LcdSpinBox + + + Set value + + + + + Please enter a new value between %1 and %2: + + + + + LeftRightNav + + + + + Previous + + + + + + + Next + + + + + Previous (%1) + + + + + Next (%1) + + + + + LfoController + + + LFO Controller + + + + + Base value + + + + + Oscillator speed + + + + + Oscillator amount + + + + + Oscillator phase + + + + + Oscillator waveform + + + + + Frequency Multiplier + + + + + LfoControllerDialog + + + LFO + + + + + BASE + + + + + Base: + + + + + FREQ + + + + + LFO frequency: + + + + + AMNT + + + + + Modulation amount: + + + + + PHS + + + + + Phase offset: + + + + + degrees + + + + + Sine wave + + + + + Triangle wave + + + + + Saw wave + + + + + Square wave + + + + + Moog saw wave + + + + + Exponential wave + + + + + White noise + + + + + User-defined shape. +Double click to pick a file. + + + + + Mutliply modulation frequency by 1 + + + + + Mutliply modulation frequency by 100 + + + + + Divide modulation frequency by 100 + + + + + LmmsCore + + + Generating wavetables + + + + + Initializing data structures + + + + + Opening audio and midi devices + + + + + Launching mixer threads + + + + + MainWindow + + + Configuration file + + + + + Error while parsing configuration file at line %1:%2: %3 + + + + + Could not open file + + + + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + + + + + Project recovery + + + + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + + + + + + Recover + + + + + Recover the file. Please don't run multiple instances of LMMS when you do this. + + + + + + Discard + + + + + Launch a default session and delete the restored files. This is not reversible. + + + + + Version %1 + + + + + Preparing plugin browser + + + + + Preparing file browsers + + + + + My Projects + + + + + My Samples + + + + + My Presets + + + + + My Home + + + + + Root directory + + + + + Volumes + + + + + My Computer + + + + + Loading background artwork + + + + + &File + + + + + &New + + + + + New from template + + + + + &Open... + + + + + &Recently Opened Projects + + + + + &Save + + + + + Save &As... + + + + + Save as New &Version + + + + + Save as default template + + + + + Import... + + + + + E&xport... + + + + + E&xport Tracks... + + + + + Export &MIDI... + + + + + &Quit + + + + + &Edit + + + + + Undo + + + + + Redo + + + + + Settings + + + + + &View + + + + + &Tools + + + + + &Help + + + + + Online Help + + + + + Help + + + + + About + + + + + Create new project + + + + + Create new project from template + + + + + Open existing project + + + + + Recently opened projects + + + + + Save current project + + + + + Export current project + + + + + Metronome + + + + + + Song Editor + + + + + + Beat+Bassline Editor + + + + + + Piano Roll + + + + + + Automation Editor + + + + + + FX Mixer + + + + + Show/hide controller rack + + + + + Show/hide project notes + + + + + Untitled + + + + + Recover session. Please save your work! + + + + + LMMS %1 + + + + + Recovered project not saved + + + + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + + + + + Project not saved + + + + + The current project was modified since last saving. Do you want to save it now? + + + + + Open Project + + + + + LMMS (*.mmp *.mmpz) + + + + + Save Project + + + + + LMMS Project + + + + + LMMS Project Template + + + + + Save project template + + + + + Overwrite default template? + + + + + This will overwrite your current default template. + + + + + Help not available + + + + + Currently there's no help available in LMMS. +Please visit http://lmms.sf.net/wiki for documentation on LMMS. + + + + + Controller Rack + + + + + Project Notes + + + + + Volume as dBFS + + + + + Smooth scroll + + + + + Enable note labels in piano roll + + + + + MIDI File (*.mid) + + + + + + untitled + + + + + + Select file for project-export... + + + + + Select directory for writing exported tracks... + + + + + Save project + + + + + Project saved + + + + + The project %1 is now saved. + + + + + Project NOT saved. + + + + + The project %1 was not saved! + + + + + Import file + + + + + MIDI sequences + + + + + Hydrogen projects + + + + + All file types + + + + + MeterDialog + + + + Meter Numerator + + + + + Meter numerator + + + + + + Meter Denominator + + + + + Meter denominator + + + + + TIME SIG + + + + + MeterModel + + + Numerator + + + + + Denominator + + + + + MidiController + + + MIDI Controller + + + + + unnamed_midi_controller + + + + + MidiImport + + + + Setup incomplete + + + + + You have not set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. + + + + + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. + + + + + Track + + + + + MidiJack + + + JACK server down + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) + + + + + The JACK server seems to be shuted down. + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) + + + + + MidiPort + + + Input channel + + + + + Output channel + + + + + Input controller + + + + + Output controller + + + + + Fixed input velocity + + + + + Fixed output velocity + + + + + Fixed output note + + + + + Output MIDI program + + + + + Base velocity + + + + + Receive MIDI-events + + + + + Send MIDI-events + + + + + MidiSetupWidget + + + DEVICE + + + + + MonstroInstrument + + + Osc 1 volume + + + + + Osc 1 panning + + + + + Osc 1 coarse detune + + + + + Osc 1 fine detune left + + + + + Osc 1 fine detune right + + + + + Osc 1 stereo phase offset + + + + + Osc 1 pulse width + + + + + Osc 1 sync send on rise + + + + + Osc 1 sync send on fall + + + + + Osc 2 volume + + + + + Osc 2 panning + + + + + Osc 2 coarse detune + + + + + Osc 2 fine detune left + + + + + Osc 2 fine detune right + + + + + Osc 2 stereo phase offset + + + + + Osc 2 waveform + + + + + Osc 2 sync hard + + + + + Osc 2 sync reverse + + + + + Osc 3 volume + + + + + Osc 3 panning + + + + + Osc 3 coarse detune + + + + + Osc 3 Stereo phase offset + + + + + Osc 3 sub-oscillator mix + + + + + Osc 3 waveform 1 + + + + + Osc 3 waveform 2 + + + + + Osc 3 sync hard + + + + + Osc 3 Sync reverse + + + + + LFO 1 waveform + + + + + LFO 1 attack + + + + + LFO 1 rate + + + + + LFO 1 phase + + + + + LFO 2 waveform + + + + + LFO 2 attack + + + + + LFO 2 rate + + + + + LFO 2 phase + + + + + Env 1 pre-delay + + + + + Env 1 attack + + + + + Env 1 hold + + + + + Env 1 decay + + + + + Env 1 sustain + + + + + Env 1 release + + + + + Env 1 slope + + + + + Env 2 pre-delay + + + + + Env 2 attack + + + + + Env 2 hold + + + + + Env 2 decay + + + + + Env 2 sustain + + + + + Env 2 release + + + + + Env 2 slope + + + + + Osc 2+3 modulation + + + + + Selected view + + + + + Osc 1 - Vol env 1 + + + + + Osc 1 - Vol env 2 + + + + + Osc 1 - Vol LFO 1 + + + + + Osc 1 - Vol LFO 2 + + + + + Osc 2 - Vol env 1 + + + + + Osc 2 - Vol env 2 + + + + + Osc 2 - Vol LFO 1 + + + + + Osc 2 - Vol LFO 2 + + + + + Osc 3 - Vol env 1 + + + + + Osc 3 - Vol env 2 + + + + + Osc 3 - Vol LFO 1 + + + + + Osc 3 - Vol LFO 2 + + + + + Osc 1 - Phs env 1 + + + + + Osc 1 - Phs env 2 + + + + + Osc 1 - Phs LFO 1 + + + + + Osc 1 - Phs LFO 2 + + + + + Osc 2 - Phs env 1 + + + + + Osc 2 - Phs env 2 + + + + + Osc 2 - Phs LFO 1 + + + + + Osc 2 - Phs LFO 2 + + + + + Osc 3 - Phs env 1 + + + + + Osc 3 - Phs env 2 + + + + + Osc 3 - Phs LFO 1 + + + + + Osc 3 - Phs LFO 2 + + + + + Osc 1 - Pit env 1 + + + + + Osc 1 - Pit env 2 + + + + + Osc 1 - Pit LFO 1 + + + + + Osc 1 - Pit LFO 2 + + + + + Osc 2 - Pit env 1 + + + + + Osc 2 - Pit env 2 + + + + + Osc 2 - Pit LFO 1 + + + + + Osc 2 - Pit LFO 2 + + + + + Osc 3 - Pit env 1 + + + + + Osc 3 - Pit env 2 + + + + + Osc 3 - Pit LFO 1 + + + + + Osc 3 - Pit LFO 2 + + + + + Osc 1 - PW env 1 + + + + + Osc 1 - PW env 2 + + + + + Osc 1 - PW LFO 1 + + + + + Osc 1 - PW LFO 2 + + + + + Osc 3 - Sub env 1 + + + + + Osc 3 - Sub env 2 + + + + + Osc 3 - Sub LFO 1 + + + + + Osc 3 - Sub LFO 2 + + + + + + Sine wave + + + + + Bandlimited Triangle wave + + + + + Bandlimited Saw wave + + + + + Bandlimited Ramp wave + + + + + Bandlimited Square wave + + + + + Bandlimited Moog saw wave + + + + + + Soft square wave + + + + + Absolute sine wave + + + + + + Exponential wave + + + + + White noise + + + + + Digital Triangle wave + + + + + Digital Saw wave + + + + + Digital Ramp wave + + + + + Digital Square wave + + + + + Digital Moog saw wave + + + + + Triangle wave + + + + + Saw wave + + + + + Ramp wave + + + + + Square wave + + + + + Moog saw wave + + + + + Abs. sine wave + + + + + Random + + + + + Random smooth + + + + + MonstroView + + + Operators view + + + + + Matrix view + + + + + + + Volume + + + + + + + Panning + + + + + + + Coarse detune + + + + + + + semitones + + + + + + Fine tune left + + + + + + + + cents + + + + + + Fine tune right + + + + + + + Stereo phase offset + + + + + + + + + deg + + + + + Pulse width - Fast Formant + + Send sync on pulse rise - Tripole + + Send sync on pulse fall + + + + + Hard sync oscillator 2 + + + + + Reverse sync oscillator 2 + + + + + Sub-osc mix + + + + + Hard sync oscillator 3 + + + + + Reverse sync oscillator 3 + + + + + + + + Attack + + + + + + Rate + + + + + + Phase + + + + + + Pre-delay + + + + + + Hold + + + + + + Decay + + + + + + Sustain + + + + + + Release + + + + + + Slope + + + + + Mix osc 2 with osc 3 + + + + + Modulate amplitude of osc 3 by osc 2 + + + + + Modulate frequency of osc 3 by osc 2 + + + + + Modulate phase of osc 3 by osc 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modulation amount - EqControls + MultitapEchoControlDialog - Input gain + + Length - Output gain + + Step length: - Low-shelf gain + + Dry - Peak 1 gain + + Dry gain: - Peak 2 gain + + Stages - Peak 3 gain + + Low-pass stages: - Peak 4 gain + + Swap inputs - High-shelf gain + + Swap left and right input channels for reflections + + + NesInstrument - HP res + + Channel 1 coarse detune - Low-shelf res + + Channel 1 volume - Peak 1 BW + + Channel 1 envelope length - Peak 2 BW + + Channel 1 duty cycle - Peak 3 BW + + Channel 1 sweep amount - Peak 4 BW + + Channel 1 sweep rate - High-shelf res + + Channel 2 Coarse detune - LP res + + Channel 2 Volume - HP freq + + Channel 2 envelope length - Low-shelf freq + + Channel 2 duty cycle - Peak 1 freq + + Channel 2 sweep amount - Peak 2 freq + + Channel 2 sweep rate - Peak 3 freq + + Channel 3 coarse detune - Peak 4 freq + + Channel 3 volume - High-shelf freq + + Channel 4 volume - LP freq + + Channel 4 envelope length - HP active + + Channel 4 noise frequency - Low-shelf active + + Channel 4 noise frequency sweep - Peak 1 active + + Master volume - Peak 2 active + + Vibrato + + + + + NesInstrumentView + + + + + + Volume - Peak 3 active + + + + Coarse detune - Peak 4 active + + + + Envelope length - High-shelf active + + Enable channel 1 + + + + + Enable envelope 1 + + + + + Enable envelope 1 loop + + + + + Enable sweep 1 + + + + + + Sweep amount + + + + + + Sweep rate + + + + + + 12.5% Duty cycle + + + + + + 25% Duty cycle + + + + + + 50% Duty cycle + + + + + + 75% Duty cycle + + + + + Enable channel 2 + + + + + Enable envelope 2 + + + + + Enable envelope 2 loop + + + + + Enable sweep 2 + + + + + Enable channel 3 + + + + + Noise Frequency + + + + + Frequency sweep + + + + + Enable channel 4 + + + + + Enable envelope 4 + + + + + Enable envelope 4 loop + + + + + Quantize noise frequency when using note frequency + + + + + Use note frequency for noise + + + + + Noise mode + + + + + Master volume + + + + + Vibrato + + + + + OpulenzInstrument + + + Patch - LP active + + Op 1 attack - LP 12 + + Op 1 decay - LP 24 + + Op 1 sustain - LP 48 + + Op 1 release - HP 12 + + Op 1 level - HP 24 + + Op 1 level scaling - HP 48 + + Op 1 frequency multiplier - Low-pass type + + Op 1 feedback - High-pass type + + Op 1 key scaling rate - Analyse IN + + Op 1 percussive envelope - Analyse OUT + + Op 1 tremolo - - - EqControlsDialog - HP + + Op 1 vibrato - Low-shelf + + Op 1 waveform - Peak 1 + + Op 2 attack - Peak 2 + + Op 2 decay - Peak 3 + + Op 2 sustain - Peak 4 + + Op 2 release - High-shelf + + Op 2 level - LP + + Op 2 level scaling - Input gain + + Op 2 frequency multiplier - Gain + + Op 2 key scaling rate - Output gain + + Op 2 percussive envelope - Bandwidth: + + Op 2 tremolo - Octave + + Op 2 vibrato - Resonance : + + Op 2 waveform - Frequency: + + FM - LP group + + Vibrato depth - HP group + + Tremolo depth - EqHandle + OpulenzInstrumentView - Reso: + + + Attack - BW: + + + Decay - Freq: + + + Release + + + + + + Frequency multiplier - FlangerControls + OscillatorObject - Delay samples + + Osc %1 waveform - LFO frequency + + Osc %1 harmonic - Seconds + + + Osc %1 volume - Regen + + + Osc %1 panning - Noise + + + Osc %1 fine detuning left - Invert + + Osc %1 coarse detuning - - - FlangerControlsDialog - DELAY + + Osc %1 fine detuning right - Delay time: + + Osc %1 phase-offset - RATE + + Osc %1 stereo phase-detuning - Period: + + Osc %1 wave shape - AMNT + + Modulation type %1 + + + PatchesDialog - Amount: + + Qsynth: Channel Preset - FDBK + + Bank selector - Feedback amount: + + Bank - NOISE + + Program selector - White noise amount: + + Patch - Invert + + Name - - - FreeBoyInstrument - Sweep time + + OK - Sweep direction + + Cancel + + + PatmanView - Sweep rate shift amount + + Open patch - Wave pattern duty cycle + + Loop - Channel 1 volume + + Loop mode - Volume sweep direction + + Tune - Length of each step in sweep + + Tune mode - Channel 2 volume + + No file selected - Channel 3 volume + + Open patch file - Channel 4 volume + + Patch-Files (*.pat) + + + PatternView - Shift Register width + + Open in piano-roll - Right output level + + Set as ghost in piano-roll - Left output level + + Clear all notes - Channel 1 to SO2 (Left) + + Reset name - Channel 2 to SO2 (Left) + + Change name - Channel 3 to SO2 (Left) + + Add steps - Channel 4 to SO2 (Left) + + Remove steps - Channel 1 to SO1 (Right) + + Clone Steps + + + PeakController - Channel 2 to SO1 (Right) + + Peak Controller - Channel 3 to SO1 (Right) + + Peak Controller Bug - Channel 4 to SO1 (Right) + + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. + + + PeakControllerDialog - Treble + + PEAK - Bass + + LFO Controller - FreeBoyInstrumentView + PeakControllerEffectControlDialog - Sweep time: + + BASE - Sweep time + + Base: - Sweep rate shift amount: + + AMNT - Sweep rate shift amount + + Modulation amount: - Wave pattern duty cycle: + + MULT - Wave pattern duty cycle + + Amount multiplicator: - Square channel 1 volume: + + ATCK - Square channel 1 volume + + Attack: - Length of each step in sweep: + + DCAY - Length of each step in sweep + + Release: - Square channel 2 volume: + + TRSH - Square channel 2 volume + + Treshold: - Wave pattern channel volume: + + Mute output - Wave pattern channel volume + + Absolute value + + + + + PeakControllerEffectControls + + + Base value - Noise channel volume: + + Modulation amount - Noise channel volume + + Attack - SO1 volume (Right): + + Release - SO1 volume (Right) + + Treshold - SO2 volume (Left): + + Mute output - SO2 volume (Left) + + Absolute value - Treble: + + Amount multiplicator + + + PianoRoll - Treble + + Note Velocity - Bass: + + Note Panning - Bass + + Mark/unmark current semitone - Sweep direction + + Mark/unmark all corresponding octave semitones - Volume sweep direction + + Mark current scale - Shift register width + + Mark current chord - Channel 1 to SO1 (Right) + + Unmark all - Channel 2 to SO1 (Right) + + Select all notes on this key - Channel 3 to SO1 (Right) + + Note lock - Channel 4 to SO1 (Right) + + Last note - Channel 1 to SO2 (Left) + + No scale - Channel 2 to SO2 (Left) + + No chord - Channel 3 to SO2 (Left) + + Velocity: %1% - Channel 4 to SO2 (Left) + + Panning: %1% left - Wave pattern graph + + Panning: %1% right - - - GigInstrument - Bank + + Panning: center - Patch + + Please open a pattern by double-clicking on it! - Gain + + + Please enter a new value between %1 and %2: - GigInstrumentView + PianoRollWindow - Open GIG file + + Play/pause current pattern (Space) - Choose patch + + Record notes from MIDI-device/channel-piano - Gain: + + Record notes from MIDI-device/channel-piano while playing song or BB track - GIG Files (*.gig) + + Record notes from MIDI-device/channel-piano, one step at the time - - - InstrumentTrack - Default preset + + Stop playing of current pattern (Space) - - - LadspaControlDialog - Link Channels + + Edit actions - Channel + + Draw mode (Shift+D) - - - LadspaEffect - Unknown LADSPA plugin %1 requested. + + Erase mode (Shift+E) - - - MidiImport - Setup incomplete + + Select mode (Shift+S) - You have not set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. + + Pitch Bend mode (Shift+T) - You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. + + Quantize - Track + + Copy paste controls - - - MonstroInstrument - Osc 1 volume + + Cut (%1+X) - Osc 1 panning + + Copy (%1+C) - Osc 1 coarse detune + + Paste (%1+V) - Osc 1 fine detune left + + Timeline controls - Osc 1 fine detune right + + Zoom and note controls - Osc 1 stereo phase offset + + Horizontal zooming - Osc 1 pulse width + + Quantization - Osc 1 sync send on rise + + Note length - Osc 1 sync send on fall + + Scale - Osc 2 volume + + Chord - Osc 2 panning + + Clear ghost notes - Osc 2 coarse detune + + + Piano-Roll - %1 - Osc 2 fine detune left + + + Piano-Roll - no pattern + + + PianoView - Osc 2 fine detune right + + Base note + + + Plugin - Osc 2 stereo phase offset + + Plugin not found - Osc 2 waveform + + The plugin "%1" wasn't found or could not be loaded! +Reason: "%2" - Osc 2 sync hard + + Error while loading plugin - Osc 2 sync reverse + + Failed to load plugin "%1"! + + + PluginBrowser - Osc 3 volume + + Instrument Plugins - Osc 3 panning + + Instrument browser - Osc 3 coarse detune + + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. + + + PluginFactory - Osc 3 Stereo phase offset + + Plugin not found. - Osc 3 sub-oscillator mix + + LMMS plugin %1 does not have a plugin descriptor named %2! + + + ProjectNotes - Osc 3 waveform 1 + + Project Notes - Osc 3 waveform 2 + + Enter project notes here - Osc 3 sync hard + + Edit Actions - Osc 3 Sync reverse + + &Undo - LFO 1 waveform + + %1+Z - LFO 1 attack + + &Redo - LFO 1 rate + + %1+Y - LFO 1 phase + + &Copy - LFO 2 waveform + + %1+C - LFO 2 attack + + Cu&t - LFO 2 rate + + %1+X - LFO 2 phase + + &Paste - Env 1 pre-delay + + %1+V - Env 1 attack + + Format Actions - Env 1 hold + + &Bold - Env 1 decay + + %1+B - Env 1 sustain + + &Italic - Env 1 release + + %1+I - Env 1 slope + + &Underline - Env 2 pre-delay + + %1+U - Env 2 attack + + &Left - Env 2 hold + + %1+L - Env 2 decay + + C&enter - Env 2 sustain + + %1+E - Env 2 release + + &Right - Env 2 slope + + %1+R - Osc 2+3 modulation + + &Justify - Selected view + + %1+J - Osc 1 - Vol env 1 + + &Color... + + + ProjectRenderer - Osc 1 - Vol env 2 + + WAV (*.wav) - Osc 1 - Vol LFO 1 + + FLAC (*.flac) - Osc 1 - Vol LFO 2 + + OGG (*.ogg) - Osc 2 - Vol env 1 + + MP3 (*.mp3) + + + QWidget - Osc 2 - Vol env 2 + + + + Name: - Osc 2 - Vol LFO 1 + + + Maker: - Osc 2 - Vol LFO 2 + + + Copyright: - Osc 3 - Vol env 1 + + + Requires Real Time: - Osc 3 - Vol env 2 + + + + + + + Yes - Osc 3 - Vol LFO 1 + + + + + + + No - Osc 3 - Vol LFO 2 + + + Real Time Capable: - Osc 1 - Phs env 1 + + + In Place Broken: - Osc 1 - Phs env 2 + + + Channels In: - Osc 1 - Phs LFO 1 + + + Channels Out: - Osc 1 - Phs LFO 2 + + File: %1 - Osc 2 - Phs env 1 + + File: + + + RenameDialog - Osc 2 - Phs env 2 + + Rename... + + + ReverbSCControlDialog - Osc 2 - Phs LFO 1 + + Input - Osc 2 - Phs LFO 2 + + Input gain: - Osc 3 - Phs env 1 + + Size - Osc 3 - Phs env 2 + + Size: - Osc 3 - Phs LFO 1 + + Color - Osc 3 - Phs LFO 2 + + Color: - Osc 1 - Pit env 1 + + Output - Osc 1 - Pit env 2 + + Output gain: + + + ReverbSCControls - Osc 1 - Pit LFO 1 + + Input gain - Osc 1 - Pit LFO 2 + + Size - Osc 2 - Pit env 1 + + Color - Osc 2 - Pit env 2 + + Output gain + + + SaControls - Osc 2 - Pit LFO 1 + + Pause - Osc 2 - Pit LFO 2 + + Reference freeze - Osc 3 - Pit env 1 + + Waterfall - Osc 3 - Pit env 2 + + Averaging - Osc 3 - Pit LFO 1 + + Stereo - Osc 3 - Pit LFO 2 + + Peak hold - Osc 1 - PW env 1 + + Logarithmic frequency - Osc 1 - PW env 2 + + Logarithmic amplitude - Osc 1 - PW LFO 1 + + Frequency range - Osc 1 - PW LFO 2 + + Amplitude range - Osc 3 - Sub env 1 + + FFT block size - Osc 3 - Sub env 2 + + FFT window type - Osc 3 - Sub LFO 1 + + + Full (auto) - Osc 3 - Sub LFO 2 + + + Audible - Sine wave + + Bass - Bandlimited Triangle wave + + Mids - Bandlimited Saw wave + + High - Bandlimited Ramp wave + + Extended - Bandlimited Square wave + + + Default - Bandlimited Moog saw wave + + Noise - Soft square wave + + (High time res.) - Absolute sine wave + + (High freq. res.) - Exponential wave + + Rectangular (Off) - White noise + + + Blackman-Harris (Default) - Digital Triangle wave + + Hamming - Digital Saw wave + + Hanning + + + SaControlsDialog - Digital Ramp wave + + Pause - Digital Square wave + + Pause data acquisition - Digital Moog saw wave + + Reference freeze - Triangle wave + + Freeze current input as a reference / disable falloff in peak-hold mode. - Saw wave + + Waterfall - Ramp wave + + Display real-time spectrogram - Square wave + + Averaging - Moog saw wave + + Enable exponential moving average - Abs. sine wave + + Stereo - Random + + Display stereo channels separately - Random smooth + + Peak hold - - - MonstroView - Operators view + + Display envelope of peak values - Matrix view + + Logarithmic frequency - Volume + + Switch between logarithmic and linear frequency scale - Panning + + + Frequency range - Coarse detune + + Logarithmic amplitude - semitones + + Switch between logarithmic and linear amplitude scale - Fine tune left + + + Amplitude range - cents + + FFT block bize - Fine tune right + + FFT block size - Stereo phase offset + + + FFT window type + + + SampleBuffer - deg + + Fail to open file - Pulse width + + Audio files are limited to %1 MB in size and %2 minutes of playing time - Send sync on pulse rise + + Open audio file - Send sync on pulse fall + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - Hard sync oscillator 2 + + Wave-Files (*.wav) - Reverse sync oscillator 2 + + OGG-Files (*.ogg) - Sub-osc mix + + DrumSynth-Files (*.ds) - Hard sync oscillator 3 + + FLAC-Files (*.flac) - Reverse sync oscillator 3 + + SPEEX-Files (*.spx) - Attack + + VOC-Files (*.voc) - Rate + + AIFF-Files (*.aif *.aiff) - Phase + + AU-Files (*.au) - Pre-delay + + RAW-Files (*.raw) + + + SampleTCOView - Hold + + Double-click to open sample - Decay + + Delete (middle mousebutton) - Sustain + + Cut - Release + + Copy - Slope + + Paste - Mix osc 2 with osc 3 + + Mute/unmute (<%1> + middle click) + + + SampleTrack - Modulate amplitude of osc 3 by osc 2 + + Volume - Modulate frequency of osc 3 by osc 2 + + Panning - Modulate phase of osc 3 by osc 2 + + FX channel - Modulation amount + + + Sample track - MultitapEchoControlDialog - - Length - - + SampleTrackView - Step length: + + Track volume - Dry + + Channel volume: - Dry gain: + + VOL - Stages + + Panning - Low-pass stages: + + Panning: - Swap inputs + + PAN - Swap left and right input channels for reflections + + FX %1: %2 - NesInstrument + SampleTrackWindow - Channel 1 coarse detune + + GENERAL SETTINGS - Channel 1 volume + + Sample volume - Channel 1 envelope length + + Volume: - Channel 1 duty cycle + + VOL - Channel 1 sweep amount + + Panning - Channel 1 sweep rate + + Panning: - Channel 2 Coarse detune + + PAN - Channel 2 Volume + + FX channel - Channel 2 envelope length + + FX + + + SaveOptionsWidget - Channel 2 duty cycle + + Discard MIDI connections + + + SetupDialog - Channel 2 sweep amount + + Setup LMMS - Channel 2 sweep rate + + + General settings - Channel 3 coarse detune + + BUFFER SIZE - Channel 3 volume + + + Reset to default value - Channel 4 volume + + MISC - Channel 4 envelope length + + Use built-in NaN handler - Channel 4 noise frequency + + PLUGIN EMBEDDING - Channel 4 noise frequency sweep + + No embedding - Master volume + + Embed using Qt API - Vibrato + + Embed using native Win32 API - - - NesInstrumentView - Volume + + Embed using XEmbed protocol - Coarse detune + + Keep plugin windows on top when not embedded - Envelope length + + LANGUAGE - Enable channel 1 + + + Paths - Enable envelope 1 + + Directories - Enable envelope 1 loop + + + Performance settings - Enable sweep 1 + + Auto save - Sweep amount + + Enable auto-save - Sweep rate + + Allow auto-save while playing - 12.5% Duty cycle + + UI effects vs. performance - 25% Duty cycle + + Smooth scroll in Song Editor - 50% Duty cycle + + Show playback cursor in AudioFileProcessor - 75% Duty cycle + + + Audio settings - Enable channel 2 + + AUDIO INTERFACE - Enable envelope 2 + + + MIDI settings - Enable envelope 2 loop + + MIDI INTERFACE - Enable sweep 2 + + OK - Enable channel 3 + + Cancel - Noise Frequency + + Restart LMMS - Frequency sweep + + Please note that most changes won't take effect until you restart LMMS! - Enable channel 4 + + Frames: %1 +Latency: %2 ms - Enable envelope 4 + + Choose LMMS working directory - Enable envelope 4 loop + + Choose your GIG directory - Quantize noise frequency when using note frequency + + Choose your SF2 directory - Use note frequency for noise + + Choose your VST-plugin directory - Noise mode + + Choose artwork-theme directory - Master volume + + Choose LADSPA plugin directory - Vibrato + + Choose STK rawwave directory - - - OpulenzInstrument - Patch + + Choose default SoundFont - Op 1 attack + + Choose background artwork - Op 1 decay + + minutes - Op 1 sustain + + minute - Op 1 release + + Disabled - Op 1 level + + Auto-save interval: %1 + + + Song - Op 1 level scaling + + Tempo - Op 1 frequency multiplier + + Master volume - Op 1 feedback + + Master pitch - Op 1 key scaling rate + + LMMS Error report - Op 1 percussive envelope + + The following errors occured while loading: + + + SongEditor - Op 1 tremolo + + Could not open file - Op 1 vibrato + + Could not open file %1. You probably have no permissions to read this file. + Please make sure to have at least read permissions to the file and try again. - Op 1 waveform + + Could not write file - Op 2 attack + + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. - Op 2 decay + + Error in file - Op 2 sustain + + The file %1 seems to contain errors and therefore can't be loaded. - Op 2 release + + Version difference - Op 2 level + + This %1 was created with LMMS %2. - Op 2 level scaling + + template - Op 2 frequency multiplier + + project - Op 2 key scaling rate + + Tempo - Op 2 percussive envelope + + TEMPO - Op 2 tremolo + + Tempo in BPM - Op 2 vibrato + + High quality mode - Op 2 waveform + + + + Master volume - FM + + + + Master pitch - Vibrato depth + + Value: %1% - Tremolo depth + + Value: %1 semitones - OpulenzInstrumentView + SongEditorWindow - Attack + + Song-Editor - Decay + + Play song (Space) - Release + + Record samples from Audio-device - Frequency multiplier + + Record samples from Audio-device while playing song or BB track - - - OscillatorObject - Osc %1 waveform + + Stop song (Space) - Osc %1 harmonic + + Track actions - Osc %1 volume + + Add beat/bassline - Osc %1 panning + + Add sample-track - Osc %1 fine detuning left + + Add automation-track - Osc %1 coarse detuning + + Edit actions - Osc %1 fine detuning right + + Draw mode - Osc %1 phase-offset + + Edit mode (select and move) - Osc %1 stereo phase-detuning + + Timeline controls - Osc %1 wave shape + + Zoom controls - Modulation type %1 + + Horizontal zooming - PatchesDialog + StepRecorderWidget - Qsynth: Channel Preset + + Hint - Bank selector + + Move recording curser using <Left/Right> arrows + + + SubWindow - Bank + + Close - Program selector + + Maximize - Patch + + Restore + + + TabWidget - Name + + + Settings for %1 + + + TempoSyncKnob - OK + + + Tempo Sync - Cancel + + No Sync - - - PatmanView - Open patch + + Eight beats - Loop + + Whole note - Loop mode + + Half note - Tune + + Quarter note - Tune mode + + 8th note - No file selected + + 16th note - Open patch file + + 32nd note - Patch-Files (*.pat) + + Custom... - - - PeakControllerEffectControlDialog - BASE + + Custom - Base: + + Synced to Eight Beats - AMNT + + Synced to Whole Note - Modulation amount: + + Synced to Half Note - MULT + + Synced to Quarter Note - Amount multiplicator: + + Synced to 8th Note - ATCK + + Synced to 16th Note - Attack: + + Synced to 32nd Note + + + TimeDisplayWidget - DCAY + + Time units - Release: + + MIN - TRSH + + SEC - Treshold: + + MSEC - Mute output + + BAR - Absolute value + + BEAT + + + + + TICK - PeakControllerEffectControls + TimeLineWidget - Base value + + Auto scrolling - Modulation amount + + Loop points - Attack + + After stopping go back to begin - Release + + After stopping go back to position at which playing was started - Treshold + + After stopping keep position - Mute output + + + Hint - Absolute value + + Press <%1> to disable magnetic loop points. - Amount multiplicator + + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. - QWidget + Track - Name: + + Mute - Maker: + + Solo + + + TrackContainer - Copyright: + + Couldn't import file - Requires Real Time: + + Couldn't find a filter for importing file %1. +You should convert this file into a format supported by LMMS using another software. - Yes + + Couldn't open file - No + + Couldn't open file %1 for reading. +Please make sure you have read-permission to the file and the directory containing the file and try again! - Real Time Capable: + + Loading project... - In Place Broken: + + + Cancel - Channels In: + + + Please wait... - Channels Out: + + Loading cancelled - File: %1 + + Project loading was cancelled. - File: + + Loading Track %1 (%2/Total %3) + + + + + Importing MIDI-file... - ReverbSCControlDialog + TrackContentObject - Input + + Mute + + + TrackContentObjectView - Input gain: + + Current position - Size + + Current length - Size: + + + %1:%2 (%3:%4 to %5:%6) - Color + + Press <%1> and drag to make a copy. - Color: + + Press <%1> for free resizing. - Output + + Hint - Output gain: + + Delete (middle mousebutton) - - - ReverbSCControls - Input gain + + Cut - Size + + Copy - Color + + Paste - Output gain + + Mute/unmute (<%1> + middle click) - SpectrumAnalyzerControlDialog + TrackOperationsWidget - Linear spectrum + + Press <%1> while clicking on move-grip to begin a new drag'n'drop action. - Linear Y axis + + Actions - - - SpectrumAnalyzerControls - Linear spectrum + + + Mute - Linear Y axis + + + Solo - Channel mode + + Clone this track - - - TrackContainer - Cancel + + Remove this track - Please wait... + + Clear this track - Importing MIDI-file... + + FX %1: %2 + + + + + Assign to new FX Channel + + + + + Turn all recording on + + + + + Turn all recording off TripleOscillatorView + Modulate phase of oscillator 1 by oscillator 2 + Modulate amplitude of oscillator 1 by oscillator 2 + Mix output of oscillators 1 & 2 + Synchronize oscillator 1 with oscillator 2 + Modulate frequency of oscillator 1 by oscillator 2 + Modulate phase of oscillator 2 by oscillator 3 + Modulate amplitude of oscillator 2 by oscillator 3 + Mix output of oscillators 2 & 3 + Synchronize oscillator 2 with oscillator 3 + Modulate frequency of oscillator 2 by oscillator 3 + Osc %1 volume: + Osc %1 panning: + Osc %1 coarse detuning: + semitones + Osc %1 fine detuning left: + + cents + Osc %1 fine detuning right: + Osc %1 phase-offset: + + degrees + Osc %1 stereo phase-detuning: + Sine wave + Triangle wave + Saw wave + Square wave + Moog-like saw wave + Exponential wave + White noise + User-defined wave + + VersionedSaveDialog + + + Increment version number + + + + + Decrement version number + + + + + Save Options + + + + + already exists. Do you want to replace it? + + + VestigeInstrumentView + + Open VST plugin + Control VST plugin from LMMS host + Open VST plugin preset + Previous (-) + Save preset + Next (+) + Show/hide GUI + Turn off all notes + DLL-files (*.dll) + EXE-files (*.exe) + No VST plugin loaded + Preset + by + - VST plugin control + + VisualizationWidget + + + Oscilloscope + + + + + Click to enable + + + VstEffectControlDialog + Show/hide + Control VST plugin from LMMS host + Open VST plugin preset + Previous (-) + Next (+) + Save preset + + Effect by: + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> @@ -2804,54 +9153,69 @@ VstPlugin + + The VST plugin %1 could not be loaded. + Open Preset + + Vst Plugin Preset (*.fxp *.fxb) + : default + " + ' + Save Preset + .fxp + .FXP + .FXB + .fxb + Loading plugin + Please wait while loading VST plugin... @@ -2859,118 +9223,147 @@ WatsynInstrument + Volume A1 + Volume A2 + Volume B1 + Volume B2 + Panning A1 + Panning A2 + Panning B1 + Panning B2 + Freq. multiplier A1 + Freq. multiplier A2 + Freq. multiplier B1 + Freq. multiplier B2 + Left detune A1 + Left detune A2 + Left detune B1 + Left detune B2 + Right detune A1 + Right detune A2 + Right detune B1 + Right detune B2 + A-B Mix + A-B Mix envelope amount + A-B Mix envelope attack + A-B Mix envelope hold + A-B Mix envelope decay + A1-B2 Crosstalk + A2-A1 modulation + B2-B1 modulation + Selected graph @@ -2978,154 +9371,224 @@ WatsynView + + + + Volume + + + + Panning + + + + Freq. multiplier + + + + Left detune + + + + + + + + cents + + + + Right detune + A-B Mix + Mix envelope amount + Mix envelope attack + Mix envelope hold + Mix envelope decay + Crosstalk + Select oscillator A1 + Select oscillator A2 + Select oscillator B1 + Select oscillator B2 + Mix output of A2 to A1 + Modulate amplitude of A1 by output of A2 + Ring modulate A1 and A2 + Modulate phase of A1 by output of A2 + Mix output of B2 to B1 + Modulate amplitude of B1 by output of B2 + Ring modulate B1 and B2 + Modulate phase of B1 by output of B2 + + + + Draw your own waveform here by dragging your mouse on this graph. + Load waveform + Load a waveform from a sample file + Phase left + Shift phase by -15 degrees + Phase right + Shift phase by +15 degrees + + Normalize + + Invert + + Smooth + + Sine wave + + + Triangle wave + Saw wave + + Square wave @@ -3133,42 +9596,52 @@ Xpressive + Selected graph + A1 + A2 + A3 + W1 smoothing + W2 smoothing + W3 smoothing + Panning 1 + Panning 2 + Rel trans @@ -3176,98 +9649,130 @@ XpressiveView + Draw your own waveform here by dragging your mouse on this graph. + Select oscillator W1 + Select oscillator W2 + Select oscillator W3 + Select output O1 + Select output O2 + Open help window + + Sine wave + + Moog-saw wave + + Exponential wave + + Saw wave + + User-defined wave + + Triangle wave + + Square wave + + White noise + WaveInterpolate + ExpressionValid + General purpose 1: + General purpose 2: + General purpose 3: + O1 panning: + O2 panning: + Release transition: + Smoothness @@ -3275,34 +9780,42 @@ ZynAddSubFxInstrument + Portamento + Filter frequency + Filter resonance + Bandwidth + FM gain + Resonance center frequency + Resonance bandwidth + Forward MIDI control change events @@ -3310,66 +9823,82 @@ ZynAddSubFxView + Portamento: + PORT + Filter frequency: + FREQ + Filter resonance: + RES + Bandwidth: + BW + FM gain: + FM GAIN + Resonance center frequency: + RES CF + Resonance bandwidth: + RES BW + Forward MIDI control changes + Show GUI @@ -3377,50 +9906,62 @@ audioFileProcessor + Amplify + Start of sample + End of sample + Loopback point + Reverse sample + Loop mode + Stutter + Interpolation mode + None + Linear + Sinc + Sample not found: %1 @@ -3428,6 +9969,7 @@ bitInvader + Sample length @@ -3435,46 +9977,64 @@ bitInvaderView + Sample length + Draw your own waveform here by dragging your mouse on this graph. + + Sine wave + + Triangle wave + + Saw wave + + Square wave + + White noise + + User-defined wave + + Smooth waveform + Interpolation + Normalize @@ -3482,74 +10042,96 @@ dynProcControlDialog + INPUT + Input gain: + OUTPUT + Output gain: + ATTACK + Peak attack time: + RELEASE + Peak release time: + + Reset wavegraph + + Smooth wavegraph + + Increase wavegraph amplitude by 1 dB + + Decrease wavegraph amplitude by 1 dB + Stereo mode: maximum + Process based on the maximum of both stereo channels + Stereo mode: average + Process based on the average of both stereo channels + Stereo mode: unlinked + Process each stereo channel independently @@ -3557,73 +10139,98 @@ dynProcControls + Input gain + Output gain + Attack time + Release time + Stereo mode + + graphModel + + + Graph + + + kickerInstrument + Start frequency + End frequency + Length + Start distortion + End distortion + Gain + Envelope slope + Noise + Click + Frequency slope + Start from note + End to note @@ -3631,42 +10238,52 @@ kickerInstrumentView + Start frequency: + End frequency: + Frequency slope: + Gain: + Envelope length: + Envelope slope: + Click: + Noise: + Start distortion: + End distortion: @@ -3674,26 +10291,37 @@ ladspaBrowserView + + Available Effects + + Unavailable Effects + + Instruments + + Analysis Tools + + Don't know + Type: @@ -3701,10 +10329,12 @@ ladspaDescription + Plugins + Description @@ -3712,66 +10342,83 @@ ladspaPortDialog + Ports + Name + Rate + Direction + Type + Min < Default < Max + Logarithmic + SR Dependent + Audio + Control + Input + Output + Toggled + Integer + Float + + Yes @@ -3779,46 +10426,57 @@ lb302Synth + VCF Cutoff Frequency + VCF Resonance + VCF Envelope Mod + VCF Envelope Decay + Distortion + Waveform + Slide Decay + Slide + Accent + Dead + 24dB/oct Filter @@ -3826,122 +10484,153 @@ lb302SynthView + Cutoff Freq: + Resonance: + Env Mod: + Decay: + 303-es-que, 24dB/octave, 3 pole filter + Slide Decay: + DIST: + Saw wave + Click here for a saw-wave. + Triangle wave + Click here for a triangle-wave. + Square wave + Click here for a square-wave. + Rounded square wave + Click here for a square-wave with a rounded end. + Moog wave + Click here for a moog-like wave. + Sine wave + Click for a sine-wave. + + White noise wave + Click here for an exponential wave. + Click here for white-noise. + Bandlimited saw wave + Click here for bandlimited saw wave. + Bandlimited square wave + Click here for bandlimited square wave. + Bandlimited triangle wave + Click here for bandlimited triangle wave. + Bandlimited moog saw wave + Click here for bandlimited moog saw wave. @@ -3949,118 +10638,147 @@ malletsInstrument + Hardness + Position + Vibrato gain + Vibrato frequency + Stick mix + Modulator + Crossfade + LFO speed + LFO depth + ADSR + Pressure + Motion + Speed + Bowed + Spread + Marimba + Vibraphone + Agogo + Wood 1 + Reso + Wood 2 + Beats + Two fixed + Clump + Tubular bells + Uniform bar + Tuned bar + Glass + Tibetan bowl @@ -4068,118 +10786,147 @@ malletsInstrumentView + Instrument + Spread + Spread: + Missing files + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! + Hardness + Hardness: + Position + Position: + Vibrato gain + Vibrato gain: + Vibrato frequency + Vibrato frequency: + Stick mix + Stick mix: + Modulator + Modulator: + Crossfade + Crossfade: + LFO speed + LFO speed: + LFO depth + LFO depth: + ADSR + ADSR: + Pressure + Pressure: + Speed + Speed: @@ -4187,18 +10934,23 @@ manageVSTEffectView + - VST parameter control + VST sync + + Automated + Close @@ -4206,18 +10958,24 @@ manageVestigeInstrumentView + + - VST plugin control + VST Sync + + Automated + Close @@ -4225,10 +10983,12 @@ organicInstrument + Distortion + Volume @@ -4236,38 +10996,48 @@ organicInstrumentView + Distortion: + Volume: + Randomise + + Osc %1 waveform: + Osc %1 volume: + Osc %1 panning: + Osc %1 stereo detuning + cents + Osc %1 harmonic: @@ -4275,34 +11045,42 @@ patchesDialog + Qsynth: Channel Preset + Bank selector + Bank + Program selector + Patch + Name + OK + Cancel @@ -4310,242 +11088,306 @@ pluginBrowser + + no description + + + + A native amplifier plugin + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + Boost your bass the fast and simple way + Customizable wavetable synthesizer + An oversampling bitcrusher + Carla Patchbay Instrument + Carla Rack Instrument + A 4-band Crossover Equalizer + A native delay plugin + A Dual filter plugin + plugin for processing dynamics in a flexible way + A native eq plugin + A native flanger plugin + Emulation of GameBoy (TM) APU + Player for GIG files + Filter for importing Hydrogen files into LMMS + Versatile drum synthesizer + List installed LADSPA plugins + plugin for using arbitrary LADSPA-effects inside LMMS. + Incomplete monophonic imitation tb303 + Filter for exporting MIDI-files from LMMS + Filter for importing MIDI-files into LMMS + Monstrous 3-oscillator synth with modulation matrix + A multitap echo delay plugin + A NES-like synthesizer + 2-operator FM Synth + Additive Synthesizer for organ-like sounds + GUS-compatible patch instrument + Plugin for controlling knobs with sound peaks + Reverb algorithm by Sean Costello + Player for SoundFont files + LMMS port of sfxr + Emulation of the MOS6581 and MOS8580 SID. This chip was used in the Commodore 64 computer. - Graphical spectrum analyzer plugin - - - + Plugin for enhancing stereo separation of a stereo input file + Plugin for freely manipulating stereo output + Tuneful things to bang on + Three powerful oscillators you can modulate in several ways + VST-host for using VST(i)-plugins within LMMS + Vibrating string modeler + plugin for using arbitrary VST effects inside LMMS. + 4-oscillator modulatable wavetable synth + plugin for waveshaping + Mathematical expression parser + Embedded ZynAddSubFX + + + A graphical spectrum analyzer. + + sf2Instrument + Bank + Patch + Gain + Reverb + Reverb room size + Reverb damping + Reverb width + Reverb level + Chorus + Chorus voices + Chorus level + Chorus speed + Chorus depth + A soundfont %1 could not be loaded. @@ -4553,54 +11395,69 @@ This chip was used in the Commodore 64 computer. sf2InstrumentView + + Open SoundFont file + Choose patch + Gain: + Apply reverb (if supported) + Room size: + Damping: + Width: + + Level: + Apply chorus (if supported) + Voices: + Speed: + Depth: + SoundFont Files (*.sf2 *.sf3) @@ -4608,6 +11465,7 @@ This chip was used in the Commodore 64 computer. sfxrInstrument + Wave @@ -4615,26 +11473,32 @@ This chip was used in the Commodore 64 computer. sidInstrument + Cutoff frequency + Resonance + Filter type + Voice 3 off + Volume + Chip model @@ -4642,98 +11506,126 @@ This chip was used in the Commodore 64 computer. sidInstrumentView + Volume: + Resonance: + + Cutoff frequency: + High-pass filter + Band-pass filter + Low-pass filter + Voice 3 off + MOS6581 SID + MOS8580 SID + + Attack: + + Decay: + Sustain: + + Release: + Pulse Width: + Coarse: + Pulse wave + Triangle wave + Saw wave + Noise + Sync + Ring modulation + Filtered + Test + Pulse width: @@ -4741,10 +11633,12 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControlDialog + WIDTH + Width: @@ -4752,6 +11646,7 @@ This chip was used in the Commodore 64 computer. stereoEnhancerControls + Width @@ -4759,18 +11654,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControlDialog + Left to Left Vol: + Left to Right Vol: + Right to Left Vol: + Right to Right Vol: @@ -4778,29 +11677,52 @@ This chip was used in the Commodore 64 computer. stereoMatrixControls + Left to Left + Left to Right + Right to Left + Right to Right + + testcontext + + + + test string + + + + + + test plural %n + + + + + vestigeInstrument + Loading plugin + Please wait while loading the VST plugin... @@ -4808,42 +11730,52 @@ This chip was used in the Commodore 64 computer. vibed + String %1 volume + String %1 stiffness + Pick %1 position + Pickup %1 position + String %1 panning + String %1 detune + String %1 fuzziness + String %1 length + Impulse %1 + String %1 @@ -4851,90 +11783,120 @@ This chip was used in the Commodore 64 computer. vibedView + String volume: + String stiffness: + Pick position: + Pickup position: + String panning: + String detune: + String fuzziness: + String length: + Impulse + Octave + Impulse Editor + Enable waveform + Enable/disable string + String + + Sine wave + + Triangle wave + + Saw wave + + Square wave + + White noise + + User-defined wave + + Smooth waveform + + Normalize waveform @@ -4942,46 +11904,57 @@ This chip was used in the Commodore 64 computer. voiceObject + Voice %1 pulse width + Voice %1 attack + Voice %1 decay + Voice %1 sustain + Voice %1 release + Voice %1 coarse detuning + Voice %1 wave shape + Voice %1 sync + Voice %1 ring modulate + Voice %1 filtered + Voice %1 test @@ -4989,42 +11962,56 @@ This chip was used in the Commodore 64 computer. waveShaperControlDialog + INPUT + Input gain: + OUTPUT + Output gain: + + Reset wavegraph + + Smooth wavegraph + + Increase wavegraph amplitude by 1 dB + + Decrease wavegraph amplitude by 1 dB + Clip input + Clip input signal to 0 dB @@ -5032,10 +12019,12 @@ This chip was used in the Commodore 64 computer. waveShaperControls + Input gain + Output gain diff --git a/data/locale/ko.ts b/data/locale/ko.ts index 796ccb3c292..a6b450a9ee7 100644 --- a/data/locale/ko.ts +++ b/data/locale/ko.ts @@ -1,15 +1,74 @@ + + AboutDialog + + About LMMS + LMMS에 대하여 + + + LMMS + LMMS + + + About + 정보 + + + Authors + 개발자 + + + Involved + 기여자 + + + Contributors ordered by number of commits: + 기여자 (기여 순으로 정렬): + + + Translation + 번역 + + + License + 라이선스 + + + Version %1 (%2/%3, Qt %4, %5). + 버전 %1 (%2/%3, Qt %4, %5). + + + LMMS - easy music production for everyone. + LMMS - 누구나 쉽게 할 수 있는 음악 제작. + + + Copyright © %1. + Copyright © %1. + + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#33cc33;">https://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#33cc33;">https://lmms.io</span></a></p></body></html> + + + Current language not translated (or native English). +If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! + 송현진 (Hyunjin Song) <tteu.ingog@gmail.com> +방성범 (Bang Seongbeom) <bangseongbeom@gmail.com> + +LMMS를 다른 언어로 번역하고 싶다거나 기존 번역을 개선하고 싶다면 저희를 도와주세요! LMMS 관리자와의 연락을 통해 참여하실 수 있습니다. + + AmplifierControlDialog VOL - 볼륨 + 음량 Volume: - 볼륨: + 음량: PAN @@ -40,7 +99,7 @@ AmplifierControls Volume - 볼륨 + 음량 Panning @@ -56,18 +115,21 @@ - AudioFileProcessorView + AudioAlsaSetupWidget - Reverse sample - 샘플 역으로 + DEVICE + 장치 - Amplify: - 증폭: + CHANNELS + 채널 + + + AudioFileProcessorView - Continue sample playback across notes - 샘플을 여러 음표에 걸쳐 계속 재생 + Reverse sample + 샘플 역으로 Disable loop @@ -77,25 +139,33 @@ Enable loop 반복 활성화 + + Continue sample playback across notes + 샘플을 여러 음표에 걸쳐 계속 재생 + + + Amplify: + 증폭: + Loopback point: 루프 시작점: Open sample - + 샘플 열기 Enable ping-pong loop - + 양방향 반복 활성화 Start point: - + 시작점: End point: - + 끝점: @@ -106,1859 +176,1924 @@ - BassBoosterControlDialog + AudioJack - FREQ - 주파수 + JACK client restarted + JACK 클라이언트 다시 시작됨 - Frequency: - 주파수: + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. + 알 수 없는 이유로 인해 LMMS와 JACK과의 연결이 끊겼습니다. LMMS의 JACK 드라이버를 다시 시작합니다. 수동으로 연결을 시도할 수도 있습니다. - GAIN - 이득 + JACK server down + JACK 서버 다운됨 - Gain: - 이득: + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. + JACK 서버가 종료된 것 같습니다. 더 이상 작업을 진행할 수 없습니다. 프로젝트를 저장한 뒤 JACK과 LMMS를 다시 시작하세요. - RATIO - + CLIENT-NAME + 클라이언트 이름 - Ratio: - + CHANNELS + 채널 - BassBoosterControls - - Frequency - 주파수 - + AudioOss - Gain - 이득 + DEVICE + 장치 - Ratio - + CHANNELS + 채널 - BitcrushControlDialog - - IN - 입력 - - - OUT - 출력 - - - GAIN - 이득 - - - CLIP - - + AudioPortAudio::setupWidget - Sample rate: - 샘플 레이트: + BACKEND + 드라이버 - Stereo difference: - + DEVICE + 장치 + + + AudioPulseAudio - Levels: - + DEVICE + 장치 - NOISE - 잡음 + CHANNELS + 채널 + + + AudioSdl::setupWidget - FREQ - 주파수 + DEVICE + 장치 + + + AudioSndio - STEREO - 스테레오 + DEVICE + 장치 - QUANT - + CHANNELS + 채널 + + + AudioSoundIo::setupWidget - Input gain: - 입력 이득: + BACKEND + 드라이버 - Input noise: - + DEVICE + 장치 + + + AutomatableModel - Output gain: - 출력 이득: + &Reset (%1%2) + 초기화 (%1%2)(&R) - Output clip: - + &Copy value (%1%2) + 값 복사 (%1%2)(&C) - Rate enabled - + &Paste value (%1%2) + 값 붙여넣기 (%1%2)(&P) - Enable sample-rate crushing - + Edit song-global automation + 전역 오토메이션 편집 - Depth enabled - + Remove song-global automation + 전역 오토메이션 제거 - Enable bit-depth crushing - + Remove all linked controls + 연결 제거 - - - BitcrushControls - Input gain - 입력 이득 + Connected to %1 + %1에 연결됨 - Input noise - + Connected to controller + 컨트롤러에 연결됨 - Output gain - 출력 이득 + Edit connection... + 연결 편집... - Output clip - + Remove connection + 연결 제거 - Sample rate - + Connect to controller... + 컨트롤러에 연결... - Stereo difference - + &Paste value + 값 붙여넣기(&P) + + + AutomationEditor - Levels - + Please open an automation pattern with the context menu of a control! + 컨트롤의 컨텍스트 메뉴에서 오토메이션 패턴을 여시기 바랍니다! - Rate enabled - + Values copied + 값 복사됨 - Depth enabled - + All selected values were copied to the clipboard. + 선택한 모든 값이 클립보드에 복사되었습니다. - CarlaInstrumentView + AutomationEditorWindow - Show GUI - GUI 표시 + Play/pause current pattern (Space) + 현재 패턴 재생/일시정지 (Space) - - - CrossoverEQControlDialog - Band 1/2 crossover: - + Stop playing of current pattern (Space) + 현재 패턴 정지 (Space) - Band 2/3 crossover: - + Edit actions + 편집 동작 - Band 3/4 crossover: - + Draw mode (Shift+D) + 그리기 모드 (Shift+D) - Band 1 gain - + Erase mode (Shift+E) + 지우기 모드 (Shift+E) - Band 1 gain: - + Flip vertically + 상하 반전 - Band 2 gain - + Flip horizontally + 좌우 반전 - Band 2 gain: + Interpolation controls - Band 3 gain - + Discrete progression + 이산적 진행 - Band 3 gain: - + Linear progression + 선형 진행 - Band 4 gain - + Cubic Hermite progression + 3차 에르미트 진행 - Band 4 gain: + Tension value for spline - Band 1 mute - + Tension: + 장력: - Mute band 1 - + Cut selected values (%1+X) + 선택된 값 잘라내기 (%1+X) - Band 2 mute - + Copy selected values (%1+C) + 선택된 값 복사 (%1+C) - Mute band 2 - + Paste values from clipboard (%1+V) + 선택된 값 붙여넣기 (%1+V) - Band 3 mute + Zoom controls - Mute band 3 + Quantization controls - Band 4 mute + Quantization - Mute band 4 - + Automation Editor - no pattern + 오토메이션 편집기 - 패턴 없음 - - - DelayControls - Feedback - 피드백 + Automation Editor - %1 + 오토메이션 편집기 - %1 - Output gain - 출력 이득 + Model is already connected to this pattern. + 대상이 이미 패턴에 연결되어 있습니다. - Delay samples + Horizontal zooming - LFO frequency + Vertical zooming + + + AutomationPattern - LFO amount - + Drag a control while pressing <%1> + <%1> 키를 누른 채로 드래그 - DelayControlsDialog + AutomationPatternView - Gain - 이득 + Open in Automation editor + 오토메이션 편집기에서 열기 - DELAY - + Clear + 지우기 - FDBK - + Reset name + 이름 초기화 - RATE - + Change name + 이름 바꾸기 - AMNT - + Set/clear record + 녹음 설정/해제 - Delay time - + Flip Vertically (Visible) + 상하 반전 - Feedback amount - + Flip Horizontally (Visible) + 좌우 반전 - LFO frequency - + %1 Connections + %1개의 연결 - LFO amount - + Disconnect "%1" + "%1" 연결 해제 - Out gain - + Model is already connected to this pattern. + 대상이 이미 패턴과 연결되어 있습니다. - DualFilterControlDialog + AutomationTrack - Filter 1 enabled - 필터 1 활성화됨 + Automation track + 오토메이션 트랙 + + + BBEditor - Filter 2 enabled - 필터 2 활성화됨 + Beat+Bassline Editor + 비트/베이스 라인 편집기 - FREQ - 주파수 + Play/pause current beat/bassline (Space) + 현재 비트/베이스 라인 재생/일시정지 (Space) - Cutoff frequency - 차단 주파수 + Stop playback of current beat/bassline (Space) + 현재 비트/베이스 라인 정지 (Space) - RESO - 공명 + Beat selector + 비트 선택기 - Resonance - 공명 + Track and step actions + - GAIN - 이득 + Add beat/bassline + 비트/베이스 라인 추가 - Gain - 이득 + Add sample-track + 샘플 트랙 추가 - MIX - + Add automation-track + 오토메이션 트랙 추가 - Mix + Remove steps - Enable/disable filter 1 + Add steps - Enable/disable filter 2 + Clone Steps - DualFilterControls + BBTCOView - Filter 1 enabled - 필터 1 활성화됨 + Open in Beat+Bassline-Editor + 비트/베이스 라인 편집기에서 열기 - Filter 1 type - 필터 1 종류 + Reset name + 이름 초기화 - Q/Resonance 1 - + Change name + 이름 바꾸기 - Gain 1 - + Change color + 색상 바꾸기 - Mix - + Reset color to default + 색상을 기본값으로 되돌리기 + + + BBTrack - Filter 2 enabled - 필터 2 활성화됨 + Beat/Bassline %1 + 비트/베이스 라인 %1 - Filter 2 type - 필터 2 종류 + Clone of %1 + %1의 복제 + + + BassBoosterControlDialog - Q/Resonance 2 - + FREQ + 주파수 - Gain 2 - + Frequency: + 주파수: - Notch - + GAIN + 이득 - Moog - + Gain: + 이득: - 2x Moog - + RATIO + 비율 - SV Notch - + Ratio: + 비율: + + + BassBoosterControls - Fast Formant - + Frequency + 주파수 - Tripole - + Gain + 이득 - Cutoff frequency 1 - + Ratio + 비율 + + + BitcrushControlDialog - Cutoff frequency 2 - + IN + 입력 - Low-pass - + OUT + 출력 - Hi-pass - + GAIN + 이득 - Band-pass csg - + NOISE + 잡음 - Band-pass czpg - + CLIP + 클리핑 - All-pass - + FREQ + 주파수 - 2x Low-pass - + Sample rate: + 샘플 레이트: - RC Low-pass 12 dB/oct - + STEREO + 스테레오 - RC Band-pass 12 dB/oct - + Stereo difference: + 좌우 차이: - RC High-pass 12 dB/oct + QUANT - RC Low-pass 24 dB/oct - + Levels: + - RC Band-pass 24 dB/oct + Input gain: + 입력 이득: + + + Input noise: - RC High-pass 24 dB/oct + Output gain: + 출력 이득: + + + Output clip: - Vocal Formant + Rate enabled - SV Low-pass + Enable sample-rate crushing - SV Band-pass + Depth enabled - SV High-pass + Enable bit-depth crushing - EqControls + BitcrushControls Input gain 입력 이득 + + Input noise + + Output gain 출력 이득 - Peak 1 gain + Output clip - Peak 2 gain + Sample rate - Peak 3 gain + Stereo difference - Peak 4 gain + Levels - HP res + Rate enabled - Peak 1 BW + Depth enabled + + + CarlaInstrumentView - Peak 2 BW - + Show GUI + GUI 표시 + + + Controller - Peak 3 BW - + Controller %1 + 컨트롤러 %1 + + + ControllerConnectionDialog - Peak 4 BW - + Connection Settings + 연결 설정 - LP res - + MIDI CONTROLLER + MIDI 컨트롤러 - HP freq - + Input channel + 입력 채널 - Peak 1 freq - + CHANNEL + 채널 - Peak 2 freq - + Input controller + 입력 컨트롤러 - Peak 3 freq - + CONTROLLER + 컨트롤러 - Peak 4 freq - + Auto Detect + 자동 감지 - LP freq + MIDI-devices to receive MIDI-events from - HP active - + USER CONTROLLER + 사용자 지정 컨트롤러 - Peak 1 active - + MAPPING FUNCTION + 매핑 함수 - Peak 2 active - + OK + 확인 - Peak 3 active - + Cancel + 취소 - Peak 4 active - + LMMS + LMMS - LP active - + Cycle Detected. + 순환 연결이 감지되었습니다. + + + ControllerRackView - LP 12 - + Controller Rack + 컨트롤러 랙 - LP 24 - + Add + 추가 - LP 48 - + Confirm Delete + 삭제 확인 - HP 12 - + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. + 정말 삭제하시겠습니까? 이 컨트롤러와의 연결이 존재합니다. 이 동작은 취소할 수 없습니다. + + + ControllerView - HP 24 - + Controls + 컨트롤 - HP 48 - + Rename controller + 컨트롤러 이름 바꾸기 - Analyse IN - 입력 신호 분석 + Enter the new name for this controller + 컨트롤러의 새 이름을 입력하세요 - Analyse OUT - 출력 신호 분석 + LFO + LFO - Low-shelf gain - + &Remove this controller + 컨트롤러 제거(&R) - High-shelf gain - + Re&name this controller + 컨트롤러 이름 바꾸기(&N) + + + CrossoverEQControlDialog - Low-shelf res + Band 1/2 crossover: - High-shelf res + Band 2/3 crossover: - Low-shelf freq + Band 3/4 crossover: - High-shelf freq + Band 1 gain - Low-shelf active + Band 1 gain: - High-shelf active + Band 2 gain - Low-pass type + Band 2 gain: - High-pass type + Band 3 gain - - - EqControlsDialog - HP + Band 3 gain: - Peak 1 + Band 4 gain - Peak 2 + Band 4 gain: - Peak 3 + Band 1 mute - Peak 4 + Mute band 1 - LP + Band 2 mute - Gain - 이득 + Mute band 2 + - Bandwidth: + Band 3 mute - Resonance : - 공명: + Mute band 3 + - Frequency: - 주파수: + Band 4 mute + - Octave - 옥타브 - - - Low-shelf - - - - High-shelf + Mute band 4 + + + DelayControls - Input gain - 입력 이득 + Feedback + 피드백 Output gain - 출력 이득 + 출력 이득 - LP group + Delay samples - HP group + LFO frequency + LFO 주파수 + + + LFO amount - EqHandle - - Reso: - 공명: - + DelayControlsDialog - BW: - 대역폭: + DELAY + 지연 - Freq: - 주파수: + FDBK + 피드백 - - - FlangerControls - Seconds - + RATE + - Regen + AMNT - Noise - 잡음 + Gain + 이득 - Invert - 파형 반전 + Delay time + - Delay samples + Feedback amount LFO frequency - - - FlangerControlsDialog - DELAY + LFO amount - RATE - + Out gain + 출력 이득 + + + DualFilterControlDialog - AMNT - + FREQ + 주파수 - Amount: - + Cutoff frequency + 차단 주파수 - FDBK - + RESO + 공명 - NOISE - 잡음 + Resonance + 공명 - Invert - 파형 반전 + GAIN + 이득 - Period: + Gain + 이득 + + + MIX - Delay time: + Mix - Feedback amount: + Filter 1 enabled + 필터 1 활성화됨 + + + Filter 2 enabled + 필터 2 활성화됨 + + + Enable/disable filter 1 - White noise amount: + Enable/disable filter 2 - FreeBoyInstrument + DualFilterControls - Sweep time - + Filter 1 enabled + 필터 1 활성화됨 - Sweep direction - + Filter 1 type + 필터 1 종류 - Channel 1 volume - + Q/Resonance 1 + 필터 1 Q/공명 - Volume sweep direction - + Gain 1 + 이득 1 - Length of each step in sweep + Mix - Channel 2 volume - + Filter 2 enabled + 필터 2 활성화됨 - Channel 3 volume - + Filter 2 type + 필터 2 종류 - Channel 4 volume - + Q/Resonance 2 + Q/공명 2 - Channel 1 to SO2 (Left) - + Gain 2 + 이득 2 - Channel 2 to SO2 (Left) - + Notch + 노치 - Channel 3 to SO2 (Left) - + Moog + Moog - Channel 4 to SO2 (Left) - + 2x Moog + 2x Moog - Channel 1 to SO1 (Right) - + SV Notch + SV 노치 - Channel 2 to SO1 (Right) + Fast Formant - Channel 3 to SO1 (Right) + Tripole - Channel 4 to SO1 (Right) + Cutoff frequency 1 - Treble + Cutoff frequency 2 - Bass + Low-pass - Shift Register width + Hi-pass - Sweep rate shift amount + Band-pass csg - Wave pattern duty cycle + Band-pass czpg - Right output level + All-pass - Left output level + 2x Low-pass - - - FreeBoyInstrumentView - Length of each step in sweep: + RC Low-pass 12 dB/oct - Length of each step in sweep + RC Band-pass 12 dB/oct - Treble: + RC High-pass 12 dB/oct - Treble + RC Low-pass 24 dB/oct - Bass: + RC Band-pass 24 dB/oct - Bass + RC High-pass 24 dB/oct - Sweep time: + Vocal Formant - Sweep time + SV Low-pass - Sweep rate shift amount: + SV Band-pass - Sweep rate shift amount + SV High-pass + + + Editor - Wave pattern duty cycle: + Transport controls - Wave pattern duty cycle - + Play (Space) + 재생 (Space) - Square channel 1 volume: - + Stop (Space) + 정지 (Space) - Square channel 1 volume - + Record + 녹음 - Square channel 2 volume: - + Record while playing + 재생하면서 녹음 - Square channel 2 volume + Toggle Step Recording + + + Effect - Wave pattern channel volume: - + Effect enabled + 효과 활성화됨 - Wave pattern channel volume + Wet/Dry mix - Noise channel volume: - + Gate + 게이트 - Noise channel volume + Decay + + + EffectChain - SO1 volume (Right): - + Effects enabled + 효과 활성화됨 + + + EffectRackView - SO1 volume (Right) - + EFFECTS CHAIN + 효과 체인 - SO2 volume (Left): - + Add effect + 효과 추가 + + + EffectSelectDialog - SO2 volume (Left) - + Add effect + 효과 추가 - Sweep direction - + Name + 이름 - Volume sweep direction - + Type + 형태 - Shift register width - + Description + 요약 - Channel 1 to SO1 (Right) - + Author + 개발자 + + + EffectView - Channel 2 to SO1 (Right) - + On/Off + 켬/끔 - Channel 3 to SO1 (Right) + W/D - Channel 4 to SO1 (Right) + Wet Level: - Channel 1 to SO2 (Left) + DECAY - Channel 2 to SO2 (Left) + Time: - Channel 3 to SO2 (Left) - + GATE + 게이트 - Channel 4 to SO2 (Left) - + Gate: + 게이트: - Wave pattern graph - + Controls + 컨트롤 - - - GigInstrument - Bank - 뱅크 + Move &up + 위로 이동(&U) - Patch - 패치 + Move &down + 아래로 이동(&D) - Gain - 이득 + &Remove this plugin + 플러그인 제거(&R) - GigInstrumentView + EnvelopeAndLfoParameters - Open GIG file - GIG 파일 열기 + Env pre-delay + - GIG Files (*.gig) - GIG 파일 (*.gig) + Env attack + - Choose patch + Env hold - Gain: - 이득: + Env decay + - - - InstrumentTrack - Default preset - 기본 프리셋 + Env sustain + - - - LadspaControlDialog - Link Channels - 채널 링크 + Env release + - Channel - 채널 + Env mod amount + - - - LadspaEffect - Unknown LADSPA plugin %1 requested. - 알 수 없는 LADSPA 플러그인 %1이(가) 요청되었습니다. + LFO pre-delay + - - - MidiImport - Setup incomplete - 설정 불완전 + LFO attack + - You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. + LFO frequency - Track - 트랙 + LFO mod amount + - You have not set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. + LFO wave shape - - - MonstroInstrument - Osc 3 Stereo phase offset + LFO frequency x 100 - Selected view + Modulate env amount + + + EnvelopeAndLfoView - Sine wave - 사인파 + DEL + - Bandlimited Triangle wave + ATT - Bandlimited Saw wave + Attack: - Bandlimited Ramp wave + HOLD - Bandlimited Square wave + Hold: - Bandlimited Moog saw wave - + DEC + 감쇠 - Soft square wave - + Decay: + 감쇠: - Absolute sine wave + SUST - Exponential wave + Sustain: - White noise - 화이트 노이즈 + REL + - Digital Triangle wave - 삼각파 + Release: + - Digital Saw wave - 톱니파 + AMT + - Digital Ramp wave - 역톱니파 + Modulation amount: + - Digital Square wave - 사각파 + SPD + 속도 - Digital Moog saw wave - + FREQ x 100 + 주파수 x 100 - Triangle wave - 삼각파 + ms/LFO: + ms/LFO: - Saw wave - 톱니파 + Hint + - Ramp wave + Pre-delay: - Square wave - 사각파 + Frequency: + 주파수: - Moog saw wave + Multiply LFO frequency by 100 - Abs. sine wave + MODULATE ENV AMOUNT - Random - 무작위 + Control envelope amount by this LFO + - Random smooth + Drag and drop a sample into this window. + + + EqControls - Osc 1 volume - + Input gain + 입력 이득 - Osc 1 panning - + Output gain + 출력 이득 - Osc 1 coarse detune - + Peak 1 gain + 피크 1 이득 - Osc 1 fine detune left - + Peak 2 gain + 피크 2 이득 - Osc 1 fine detune right - + Peak 3 gain + 피크 3 이득 - Osc 1 stereo phase offset - + Peak 4 gain + 피크 4 이득 - Osc 1 pulse width - + HP res + 고역 필터 공명 - Osc 1 sync send on rise - + Peak 1 BW + 피크 1 대역폭 - Osc 1 sync send on fall - + Peak 2 BW + 피크 2 대역폭 - Osc 2 volume - + Peak 3 BW + 피크 3 대역폭 - Osc 2 panning - + Peak 4 BW + 피크 4 대역폭 - Osc 2 coarse detune - + LP res + 저역 필터 공명 - Osc 2 fine detune left - + HP freq + 고역 필터 주파수 - Osc 2 fine detune right - + Peak 1 freq + 피크 1 주파수 - Osc 2 stereo phase offset - + Peak 2 freq + 피크 2 주파수 - Osc 2 waveform - + Peak 3 freq + 피크 3 주파수 - Osc 2 sync hard - + Peak 4 freq + 피크 4 주파수 - Osc 2 sync reverse - + LP freq + 저역 필터 주파수 - Osc 3 volume + HP active - Osc 3 panning - + Peak 1 active + 피크 1 활성화 - Osc 3 coarse detune - + Peak 2 active + 피크 2 활성화 - Osc 3 sub-oscillator mix - + Peak 3 active + 피크 3 활성화 - Osc 3 waveform 1 - + Peak 4 active + 피크 4 활성화 - Osc 3 waveform 2 + LP active - Osc 3 sync hard - + LP 12 + LP 12 - Osc 3 Sync reverse - + LP 24 + LP 24 - LFO 1 waveform - + LP 48 + LP 48 - LFO 1 attack - + HP 12 + HP 12 - LFO 1 rate - + HP 24 + HP 24 - LFO 1 phase - + HP 48 + HP 48 - LFO 2 waveform - + Analyse IN + 입력 신호 분석 - LFO 2 attack - + Analyse OUT + 출력 신호 분석 - LFO 2 rate + Low-shelf gain - LFO 2 phase + High-shelf gain - Env 1 pre-delay + Low-shelf res - Env 1 attack + High-shelf res - Env 1 hold + Low-shelf freq - Env 1 decay + High-shelf freq - Env 1 sustain + Low-shelf active - Env 1 release + High-shelf active - Env 1 slope + Low-pass type - Env 2 pre-delay + High-pass type + + + EqControlsDialog - Env 2 attack + HP - Env 2 hold - + Peak 1 + 피크 1 - Env 2 decay - + Peak 2 + 피크 2 - Env 2 sustain - + Peak 3 + 피크 3 - Env 2 release - + Peak 4 + 피크 4 - Env 2 slope + LP - Osc 2+3 modulation - + Gain + 이득 - Osc 1 - Vol env 1 - + Bandwidth: + 대역폭: - Osc 1 - Vol env 2 - + Octave + 옥타브 - Osc 1 - Vol LFO 1 - + Resonance : + 공명 : - Osc 1 - Vol LFO 2 - + Frequency: + 주파수: - Osc 2 - Vol env 1 + Low-shelf - Osc 2 - Vol env 2 + High-shelf - Osc 2 - Vol LFO 1 - + Input gain + 입력 이득 - Osc 2 - Vol LFO 2 - + Output gain + 출력 이득 - Osc 3 - Vol env 1 + LP group - Osc 3 - Vol env 2 + HP group + + + EqHandle - Osc 3 - Vol LFO 1 - + Reso: + 공명: - Osc 3 - Vol LFO 2 - + BW: + 대역폭: - Osc 1 - Phs env 1 - + Freq: + 주파수: + + + ExportProjectDialog - Osc 1 - Phs env 2 - + Export project + 프로젝트 내보내기 - Osc 1 - Phs LFO 1 - + File format: + 파일 형식: - Osc 1 - Phs LFO 2 - + 44100 Hz + 44100 Hz - Osc 2 - Phs env 1 - + 48000 Hz + 48000 Hz - Osc 2 - Phs env 2 - + 88200 Hz + 88200 Hz - Osc 2 - Phs LFO 1 - + 96000 Hz + 96000 Hz - Osc 2 - Phs LFO 2 - + 192000 Hz + 192000 Hz - Osc 3 - Phs env 1 - + Stereo mode: + 스테레오 모드: - Osc 3 - Phs env 2 - + Stereo + 스테레오 - Osc 3 - Phs LFO 1 - + Mono + 모노 - Osc 3 - Phs LFO 2 - + Bitrate: + 비트 레이트: - Osc 1 - Pit env 1 - + 64 KBit/s + 64 KBit/s - Osc 1 - Pit env 2 - + 128 KBit/s + 128 KBit/s - Osc 1 - Pit LFO 1 - + 160 KBit/s + 160 KBit/s - Osc 1 - Pit LFO 2 - + 192 KBit/s + 192 KBit/s - Osc 2 - Pit env 1 - + 256 KBit/s + 256 KBit/s - Osc 2 - Pit env 2 - + 320 KBit/s + 320 KBit/s - Osc 2 - Pit LFO 1 - + Use variable bitrate + 가변 비트레이트 사용 - Osc 2 - Pit LFO 2 - + Quality settings + 품질 설정 - Osc 3 - Pit env 1 - + Interpolation: + 보간법: - Osc 3 - Pit env 2 - + 1x (None) + 1x (사용하지 않음) - Osc 3 - Pit LFO 1 - + 2x + 2x - Osc 3 - Pit LFO 2 - + 4x + 4x - Osc 1 - PW env 1 - + 8x + 8x - Osc 1 - PW env 2 - + Export between loop markers + 반복 마커 사이 구간만 내보내기 - Osc 1 - PW LFO 1 - + Start + 시작 - Osc 1 - PW LFO 2 - + Cancel + 취소 - Osc 3 - Sub env 1 - + Could not open file + 파일을 열 수 없음 - Osc 3 - Sub env 2 - + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + 파일 %1을(를) 쓰기 위하여 열 수 없습니다. +경로에 파일이 존재하고 파일에 쓸 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다! - Osc 3 - Sub LFO 1 - + Export project to %1 + %1(으)로 프로젝트 내보내기 - Osc 3 - Sub LFO 2 - + Error + 오류 - - - MonstroView - Operators view - + Error while determining file-encoder device. Please try to choose a different output format. + 파일 인코더를 결정하는 중 오류가 발생하였습니다. 다른 포맷을 선택하여 다시 시도해 보세요. - Matrix view + Rendering: %1% + 렌더링: %1% + + + Compression level: - Volume - 볼륨 + Export as loop (remove extra bar) + 루프 곡처럼 내보내기 (후반부 여백 제거) - Panning - 패닝 + Render Looped Section: + - Coarse detune + time(s) - semitones - 반음 + File format settings + - cents - 센트 + Sampling rate: + - Stereo phase offset + Bit depth: - deg - + 16 Bit integer + 16비트 정수 - Pulse width - 펄스 폭 + 24 Bit integer + 24비트 정수 - Send sync on pulse rise - + 32 Bit float + 32비트 실수 - Send sync on pulse fall + Joint stereo - Hard sync oscillator 2 + Zero order hold - Reverse sync oscillator 2 + Sinc worst (fastest) - Sub-osc mix + Sinc medium (recommended) - Hard sync oscillator 3 + Sinc best (slowest) - Reverse sync oscillator 3 + Oversampling: - Attack + ( Fastest - biggest ) - Rate - + ( Slowest - smallest ) + + + + Fader - Phase - 위상 + Please enter a new value between %1 and %2: + %1부터 %2까지의 값을 입력하세요: - Pre-delay - + Set value + 값 설정 + + + FileBrowser - Hold - + Browser + 탐색기 - Decay - + Search + 검색 - Sustain - + Refresh list + 목록 새로고침 + + + FileBrowserTreeWidget - Release - + Send to active instrument-track + 활성화된 악기 트랙에서 열기 - Slope - + Open in new instrument-track/Song Editor + 새로운 악기 트랙이나 노래 편집기에서 열기 - Modulation amount - + Open in new instrument-track/B+B Editor + 새로운 악기 트랙이나 비트/베이스 라인 편집기에서 열기 - Fine tune left - + Loading sample + 샘플을 로딩하는 중 - Fine tune right - + Please wait, loading sample for preview... + 미리보기를 위하여 샘플을 로딩하는 중입니다. 잠시 기다려 주세요... - Mix osc 2 with osc 3 - + Error + 오류 - Modulate amplitude of osc 3 by osc 2 + does not appear to be a valid - Modulate frequency of osc 3 by osc 2 - + file + 파일 - Modulate phase of osc 3 by osc 2 + --- Factory files --- - MultitapEchoControlDialog + FlangerControls - Length - 길이 + Seconds + - Step length: + Regen - Dry - + Noise + 잡음 - Stages - + Invert + 파형 반전 - Swap inputs + Delay samples - Dry gain: - + LFO frequency + LFO 주파수 + + + FlangerControlsDialog - Low-pass stages: - + DELAY + 지연 - Swap left and right input channels for reflections + RATE - - - NesInstrument - Channel 2 Coarse detune + Period: - Channel 2 Volume + AMNT - Master volume - 마스터 볼륨 + Amount: + - Vibrato - 비브라토 + FDBK + 피드백 - Channel 1 coarse detune - + NOISE + 잡음 - Channel 1 volume - + Invert + 파형 반전 - Channel 1 envelope length + Delay time: - Channel 1 duty cycle + Feedback amount: - Channel 1 sweep amount + White noise amount: + + + FreeBoyInstrument - Channel 1 sweep rate + Sweep time - Channel 2 envelope length + Sweep direction - Channel 2 duty cycle + Channel 1 volume - Channel 2 sweep amount + Volume sweep direction - Channel 2 sweep rate + Length of each step in sweep - Channel 3 coarse detune + Channel 2 volume @@ -1970,626 +2105,4726 @@ - Channel 4 envelope length + Shift Register width - Channel 4 noise frequency + Channel 1 to SO2 (Left) - Channel 4 noise frequency sweep + Channel 2 to SO2 (Left) - - + + Channel 3 to SO2 (Left) + + + + Channel 4 to SO2 (Left) + + + + Channel 1 to SO1 (Right) + + + + Channel 2 to SO1 (Right) + + + + Channel 3 to SO1 (Right) + + + + Channel 4 to SO1 (Right) + + + + Treble + + + + Bass + + + + Sweep rate shift amount + + + + Wave pattern duty cycle + + + + Right output level + + + + Left output level + + + + + FreeBoyInstrumentView + + Length of each step in sweep: + + + + Length of each step in sweep + + + + Treble: + + + + Treble + + + + Bass: + + + + Bass + + + + Sweep time: + + + + Sweep time + + + + Sweep rate shift amount: + + + + Sweep rate shift amount + + + + Wave pattern duty cycle: + + + + Wave pattern duty cycle + + + + Square channel 1 volume: + + + + Square channel 1 volume + + + + Square channel 2 volume: + + + + Square channel 2 volume + + + + Wave pattern channel volume: + + + + Wave pattern channel volume + + + + Noise channel volume: + + + + Noise channel volume + + + + SO1 volume (Right): + + + + SO1 volume (Right) + + + + SO2 volume (Left): + + + + SO2 volume (Left) + + + + Sweep direction + + + + Volume sweep direction + + + + Shift register width + + + + Channel 1 to SO1 (Right) + + + + Channel 2 to SO1 (Right) + + + + Channel 3 to SO1 (Right) + + + + Channel 4 to SO1 (Right) + + + + Channel 1 to SO2 (Left) + + + + Channel 2 to SO2 (Left) + + + + Channel 3 to SO2 (Left) + + + + Channel 4 to SO2 (Left) + + + + Wave pattern graph + + + + + FxLine + + Channel send amount + + + + Move &left + 왼쪽으로 이동(&L) + + + Move &right + 오른쪽으로 이동(&R) + + + Rename &channel + 채널 이름 바꾸기(&C) + + + R&emove channel + 채널 제거(&R) + + + Remove &unused channels + 사용하지 않는 채널 제거(&U) + + + + FxLineLcdSpinBox + + Assign to: + 채널 할당: + + + New FX Channel + 새 FX 채널 + + + + FxMixer + + Master + 마스터 + + + FX %1 + FX %1 + + + Volume + 음량 + + + Mute + 음소거 + + + Solo + 독주 + + + + FxMixerView + + FX-Mixer + FX-믹서 + + + FX Fader %1 + FX 페이더 %1 + + + Mute + 음소거 + + + Mute this FX channel + 이 채널 음소거 + + + Solo + 독주 + + + Solo FX channel + 이 채널 독주 + + + + FxRoute + + Amount to send from channel %1 to channel %2 + 채널 %1에서 채널 %2(으)로 보낼 양 + + + + GigInstrument + + Bank + 뱅크 + + + Patch + 패치 + + + Gain + 이득 + + + + GigInstrumentView + + Open GIG file + GIG 파일 열기 + + + GIG Files (*.gig) + GIG 파일 (*.gig) + + + Choose patch + + + + Gain: + 이득: + + + + GuiApplication + + Working directory + 작업 경로 + + + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. + LMMS 작업 경로 %1이(가) 존재하지 않습니다. 지금 만드시겠습니까? 나중에 편집 -> 설정에서 변경할 수 있습니다. + + + Preparing UI + UI 준비 + + + Preparing song editor + 노래 편집기 준비 + + + Preparing mixer + 믹서 준비 + + + Preparing controller rack + 컨트롤러 랙 준비 + + + Preparing project notes + 프로젝트 노트 준비 + + + Preparing beat/bassline editor + 비트/베이스 라인 편집기 준비 + + + Preparing piano roll + 피아노 롤 준비 + + + Preparing automation editor + 오토메이션 편집기 준비 + + + + InstrumentFunctionArpeggio + + Arpeggio + 아르페지오 + + + Arpeggio type + 아르페지오 형태 + + + Arpeggio range + 아르페지오 범위 + + + Cycle steps + + + + Skip rate + + + + Miss rate + + + + Arpeggio time + 아르페지오 시간 + + + Arpeggio gate + 아르페지오 게이트 + + + Arpeggio direction + 아르페지오 방향 + + + Arpeggio mode + 아르페지오 모드 + + + Up + 위로 + + + Down + 아래로 + + + Up and down + 위 다음 아래 + + + Down and up + 아래 다음 위 + + + Random + 무작위 + + + Free + 자유 + + + Sort + 정렬 + + + Sync + 동기화 + + + + InstrumentFunctionArpeggioView + + ARPEGGIO + 아르페지오 + + + RANGE + 범위 + + + Arpeggio range: + 아르페지오 범위: + + + octave(s) + 옥타브 + + + CYCLE + + + + Cycle notes: + + + + note(s) + + + + SKIP + + + + Skip rate: + + + + % + % + + + MISS + + + + Miss rate: + + + + TIME + 시간 + + + Arpeggio time: + 아르페지오 시간: + + + ms + ms + + + GATE + 게이트 + + + Arpeggio gate: + 아르페지오 게이트: + + + Chord: + 코드: + + + Direction: + 방향: + + + Mode: + 모드: + + + + InstrumentFunctionNoteStacking + + octave + 옥타브 + + + Major + + + + Majb5 + + + + minor + + + + minb5 + + + + sus2 + + + + sus4 + + + + aug + + + + augsus4 + + + + tri + + + + 6 + 6 + + + 6sus4 + 6sus4 + + + 6add9 + 6add9 + + + m6 + + + + m6add9 + + + + 7 + 7 + + + 7sus4 + 7sus4 + + + 7#5 + 7#5 + + + 7b5 + 7b5 + + + 7#9 + 7#9 + + + 7b9 + 7b9 + + + 7#5#9 + 7#5#9 + + + 7#5b9 + 7#5b9 + + + 7b5b9 + 7b5b9 + + + 7add11 + 7add11 + + + 7add13 + 7add13 + + + 7#11 + 7#11 + + + Maj7 + + + + Maj7b5 + + + + Maj7#5 + + + + Maj7#11 + + + + Maj7add13 + + + + m7 + + + + m7b5 + + + + m7b9 + + + + m7add11 + + + + m7add13 + + + + m-Maj7 + + + + m-Maj7add11 + + + + m-Maj7add13 + + + + 9 + 9 + + + 9sus4 + 9sus4 + + + add9 + add9 + + + 9#5 + 9#5 + + + 9b5 + 9b5 + + + 9#11 + 9#11 + + + 9b13 + 9b13 + + + Maj9 + + + + Maj9sus4 + + + + Maj9#5 + + + + Maj9#11 + + + + m9 + + + + madd9 + + + + m9b5 + + + + m9-Maj7 + + + + 11 + 11 + + + 11b9 + 11b9 + + + Maj11 + + + + m11 + + + + m-Maj11 + + + + 13 + 13 + + + 13#9 + 13#9 + + + 13b9 + 13b9 + + + 13b5b9 + 13b5b9 + + + Maj13 + + + + m13 + + + + m-Maj13 + + + + Harmonic minor + 화성 단음계 + + + Melodic minor + 가락 단음계 + + + Whole tone + + + + Diminished + + + + Major pentatonic + + + + Minor pentatonic + + + + Jap in sen + + + + Major bebop + + + + Dominant bebop + + + + Blues + + + + Arabic + + + + Enigmatic + + + + Neopolitan + + + + Neopolitan minor + + + + Hungarian minor + + + + Dorian + + + + Phrygian + + + + Lydian + + + + Mixolydian + + + + Aeolian + + + + Locrian + + + + Minor + + + + Chromatic + + + + Half-Whole Diminished + + + + 5 + 5 + + + Phrygian dominant + + + + Persian + + + + Chords + 코드 + + + Chord type + 코드 종류 + + + Chord range + 코드 범위 + + + + InstrumentFunctionNoteStackingView + + STACKING + 코드 쌓기 + + + Chord: + 코드: + + + RANGE + 범위 + + + Chord range: + 코드 범위: + + + octave(s) + 옥타브 + + + + InstrumentMidiIOView + + ENABLE MIDI INPUT + MIDI 입력 활성화 + + + CHANNEL + 채널 + + + VELOCITY + 벨로시티 + + + ENABLE MIDI OUTPUT + MIDI 출력 활성화 + + + PROGRAM + 프로그램 + + + NOTE + + + + MIDI devices to receive MIDI events from + + + + MIDI devices to send MIDI events to + + + + CUSTOM BASE VELOCITY + 사용자 지정 기준 벨로시티 + + + BASE VELOCITY + 기준 벨로시티 + + + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity. + + + + + InstrumentMiscView + + MASTER PITCH + 마스터 피치 + + + Enables the use of master pitch + 마스터 피치 사용 + + + + InstrumentSoundShaping + + VOLUME + 음량 + + + Volume + 음량 + + + CUTOFF + 컷오프 + + + Cutoff frequency + 차단 주파수 + + + RESO + 공명 + + + Resonance + 공명 + + + Envelopes/LFOs + 엔벨로프/LFO + + + Filter type + 필터 종류 + + + Q/Resonance + Q/공명 + + + Notch + 노치 + + + Moog + Moog + + + 2x Moog + 2x Moog + + + SV Notch + SV 노치 + + + Fast Formant + + + + Tripole + + + + Low-pass + + + + Hi-pass + + + + Band-pass csg + + + + Band-pass czpg + + + + All-pass + + + + 2x Low-pass + + + + RC Low-pass 12 dB/oct + + + + RC Band-pass 12 dB/oct + + + + RC High-pass 12 dB/oct + + + + RC Low-pass 24 dB/oct + + + + RC Band-pass 24 dB/oct + + + + RC High-pass 24 dB/oct + + + + Vocal Formant + + + + SV Low-pass + + + + SV Band-pass + + + + SV High-pass + + + + + InstrumentSoundShapingView + + TARGET + 대상 + + + FILTER + 필터 + + + FREQ + 주파수 + + + Hz + Hz + + + Envelopes, LFOs and filters are not supported by the current instrument. + 이 악기는 엔벨로프, LFO, 필터를 지원하지 않습니다. + + + Cutoff frequency: + 차단 주파수: + + + Q/RESO + Q/공명 + + + Q/Resonance: + Q/공명: + + + + InstrumentTrack + + With this knob you can set the volume of the opened channel. + 이 노브를 이용하여 트랙의 음량을 조절할 수 있습니다. + + + unnamed_track + 이름 없는 트랙 + + + Base note + 기준 음 + + + Volume + 음량 + + + Panning + 패닝 + + + Pitch + 피치 + + + Pitch range + 피치 범위 + + + FX channel + FX 채널 + + + Default preset + 기본 프리셋 + + + Master pitch + 마스터 피치 + + + + InstrumentTrackView + + Volume + 음량 + + + Volume: + 음량: + + + VOL + 음량 + + + Panning + 패닝 + + + Panning: + 패닝: + + + PAN + 패닝 + + + MIDI + MIDI + + + Input + 입력 + + + Output + 출력 + + + FX %1: %2 + FX %1: %2 + + + + InstrumentTrackWindow + + GENERAL SETTINGS + 일반 설정 + + + Volume: + 음량: + + + VOL + 음량 + + + Panning + 패닝 + + + Panning: + 패닝: + + + PAN + 패닝 + + + Pitch + 피치 + + + Pitch: + 피치: + + + cents + 센트 + + + PITCH + 피치 + + + Pitch range (semitones) + 피치 범위(반음) + + + RANGE + 범위 + + + FX channel + FX 채널 + + + FX + FX + + + Save current instrument track settings in a preset file + 프리셋 파일에 현재 악기 트랙의 설정 저장 + + + SAVE + 저장 + + + Envelope, filter & LFO + 엔벨로프, 필터 & LFO + + + Chord stacking & arpeggio + 코드 쌓기 & 아르페지오 + + + Effects + 효과 + + + Miscellaneous + 기타 + + + Save preset + 프리셋 저장 + + + XML preset file (*.xpf) + XML 프리셋 파일 (*.xpf) + + + Plugin + 플러그인 + + + Volume + 음량 + + + MIDI + MIDI + + + + Knob + + Set linear + 선형으로 설정 + + + Set logarithmic + 로그스케일로 설정 + + + Please enter a new value between -96.0 dBFS and 6.0 dBFS: + -96.0 dBFS부터 6.0 dBFS까지의 값을 입력하세요: + + + Please enter a new value between %1 and %2: + %1부터 %2까지의 값을 입력하세요: + + + Set value + 값 설정 + + + + LadspaControl + + Link channels + 채널 링크 + + + + LadspaControlDialog + + Link Channels + 채널 링크 + + + Channel + 채널 + + + + LadspaControlView + + Link channels + 채널 링크 + + + Value: + 값: + + + + LadspaEffect + + Unknown LADSPA plugin %1 requested. + 알 수 없는 LADSPA 플러그인 %1이(가) 요청되었습니다. + + + + LcdSpinBox + + Please enter a new value between %1 and %2: + %1부터 %2까지의 값을 입력하세요: + + + Set value + 값 설정 + + + + LeftRightNav + + Previous + 이전 + + + Next + 다음 + + + Previous (%1) + 이전 (%1) + + + Next (%1) + 다음 (%1) + + + + LfoController + + LFO Controller + LFO 컨트롤러 + + + Base value + 기준 값 + + + Oscillator speed + + + + Oscillator amount + + + + Oscillator phase + 오실레이터 위상 + + + Oscillator waveform + 오실레이터 파형 + + + Frequency Multiplier + + + + + LfoControllerDialog + + LFO + LFO + + + BASE + 기준 + + + AMNT + + + + Modulation amount: + + + + PHS + 위상 + + + Phase offset: + 위상: + + + Base: + + + + FREQ + 주파수 + + + LFO frequency: + + + + degrees + + + + Sine wave + 사인파 + + + Triangle wave + 삼각파 + + + Saw wave + 톱니파 + + + Square wave + 사각파 + + + Moog saw wave + Moog 톱니파 + + + Exponential wave + 지수형 파형 + + + White noise + 화이트 노이즈 + + + User-defined shape. +Double click to pick a file. + + + + Mutliply modulation frequency by 1 + + + + Mutliply modulation frequency by 100 + + + + Divide modulation frequency by 100 + + + + + LmmsCore + + Generating wavetables + + + + Initializing data structures + 자료 구조 초기화 중 + + + Opening audio and midi devices + 오디오 장치와 MIDI 장치를 여는 중 + + + Launching mixer threads + 믹서 스레드를 시작하는 중 + + + + MainWindow + + Configuration file + 설정 파일 + + + Error while parsing configuration file at line %1:%2: %3 + 설정 파일 분석 중 오류 발생 (행 %1:%2: %3) + + + Could not open file + 파일을 열 수 없음 + + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + 파일 %1을(를) 쓰기 위하여 열 수 없습니다. +경로에 파일이 존재하고 파일에 쓸 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다! + + + Project recovery + 프로젝트 복구 + + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + 복구 파일이 존재합니다. 이전에 LMMS가 비정상 종료되었거나 여러 개의 LMMS 인스턴스가 동시에 실행 중인 것 같습니다. 복구 파일로부터 프로젝트를 복구하시겠습니까? + + + Recover + 복구 + + + Recover the file. Please don't run multiple instances of LMMS when you do this. + 파일을 복구합니다. 다른 LMMS 인스턴스가 실행 중이지 않은 상태에서 선택하시기 바랍니다. + + + Discard + 저장하지 않음 + + + Launch a default session and delete the restored files. This is not reversible. + 복구 파일을 삭제하고 기본 프로젝트를 불러옵니다. 이 동작은 되돌릴 수 없습니다. + + + Version %1 + 버전 %1 + + + Preparing plugin browser + 플러그인 탐색기 준비 + + + Preparing file browsers + 파일 탐색기 준비 + + + My Projects + 내 프로젝트 + + + My Samples + 내 샘플 + + + My Presets + 내 사전 설정 + + + My Home + 내 홈 디렉터리 + + + Root directory + 최상위 디렉토리 + + + Volumes + 음량 + + + My Computer + 내 컴퓨터 + + + Loading background artwork + 배경 아트워크를 불러오는 중 + + + &File + 파일(&F) + + + &New + 새로 만들기(&N) + + + New from template + 템플릿에서 새 프로젝트 생성 + + + &Open... + 열기(&O)... + + + &Recently Opened Projects + 최근에 사용한 프로젝트(&R) + + + &Save + 저장(&S) + + + Save &As... + 다른 이름으로 저장(&A)... + + + Save as New &Version + 새로운 버전으로 저장(&V) + + + Save as default template + 기본 템플릿으로 저장 + + + Import... + 가져오기... + + + E&xport... + 내보내기(&X)... + + + E&xport Tracks... + 트랙 내보내기(&X)... + + + Export &MIDI... + MIDI 내보내기(&M)... + + + &Quit + 끝내기(&Q) + + + &Edit + 편집(&E) + + + Undo + 실행 취소 + + + Redo + 다시 실행 + + + Settings + 설정 + + + &View + 보기(&V) + + + &Tools + 도구(&T) + + + &Help + 도움말(&H) + + + Online Help + 온라인 도움말 + + + Help + 도움말 + + + About + 정보 + + + Create new project + 새 프로젝트 생성 + + + Create new project from template + 템플릿에서 새 프로젝트 생성 + + + Open existing project + 기존 프로젝트 열기 + + + Recently opened projects + 최근에 사용한 프로젝트 + + + Save current project + 현재 프로젝트 저장 + + + Export current project + 현재 프로젝트 내보내기 + + + Show/hide project notes + 프로젝트 노트 보이기/숨기기 + + + Show/hide controller rack + 컨트롤러 랙 보이기/숨기기 + + + Untitled + 제목 없음 + + + Recover session. Please save your work! + 복구 세션입니다. 프로젝트 파일을 저장해 주세요! + + + LMMS %1 + LMMS %1 + + + Recovered project not saved + 복구된 프로젝트가 저장되지 않음 + + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + 이 프로젝트는 이전 세션으로부터 복구되었지만 아직 저장되지 않았습니다. 저장하지 않을 경우 지금까지의 작업을 잃게 될 것입니다. 지금 저장하시겠습니까? + + + Project not saved + 프로젝트 저장되지 않음 + + + The current project was modified since last saving. Do you want to save it now? + 이 프로젝트는 마지막 저장 이후 수정되었습니다. 지금 저장하시겠습니까? + + + Open Project + 프로젝트 열기 + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + Save Project + 프로젝트 저장 + + + LMMS Project + LMMS 프로젝트 + + + LMMS Project Template + LMMS 프로젝트 템플릿 + + + Save project template + 프로젝트 템플릿 저장 + + + Overwrite default template? + 기본 템플릿을 덮어쓰시겠습니까? + + + This will overwrite your current default template. + 이 작업은 현재의 기본 템플릿을 덮어씁니다. + + + Help not available + 도움말 사용 불가 + + + Currently there's no help available in LMMS. +Please visit http://lmms.sf.net/wiki for documentation on LMMS. + + + + Song Editor + 노래 편집기 + + + Beat+Bassline Editor + 비트/베이스 라인 편집기 + + + Piano Roll + 피아노 롤 + + + Automation Editor + 오토메이션 편집기 + + + FX Mixer + FX 믹서 + + + Project Notes + 프로젝트 노트 + + + Controller Rack + 컨트롤러 랙 + + + Volume as dBFS + 음량을 dBFS 단위로 표시 + + + Smooth scroll + 부드러운 스크롤 + + + Enable note labels in piano roll + 피아노 롤에 음표 라벨 표시 + + + Metronome + 메트로놈 + + + MIDI File (*.mid) + MIDI 파일(*.mid) + + + untitled + 제목 없음 + + + Select file for project-export... + 프로젝트를 내보낼 파일 선택... + + + Select directory for writing exported tracks... + 내보낼 트랙 파일들을 저장할 경로 선택... + + + Save project + 프로젝트 저장 + + + Project saved + 프로젝트 저장됨 + + + The project %1 is now saved. + 프로젝트 %1이 저장되었습니다. + + + Project NOT saved. + 프로젝트가 저장되지 않았습니다. + + + The project %1 was not saved! + 프로젝트 %1이 저장되지 않았습니다! + + + Import file + 파일 가져오기 + + + MIDI sequences + MIDI 시퀀스 + + + Hydrogen projects + Hydrogen 프로젝트 + + + All file types + 모든 파일 + + + + MeterDialog + + Meter Numerator + 박자표 분자 + + + Meter Denominator + 박자표 분모 + + + TIME SIG + 박자 + + + Meter numerator + 박자표 분자 + + + Meter denominator + 박자표 분모 + + + + MeterModel + + Numerator + 분자 + + + Denominator + 분모 + + + + MidiController + + MIDI Controller + MIDI 컨트롤러 + + + unnamed_midi_controller + 이름 없는 MIDI 컨트롤러 + + + + MidiImport + + Setup incomplete + 설정 불완전 + + + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. + LMMS가 SoundFont2 플레이어 지원 없이 컴파일되었습니다. MIDI 파일에서 가져온 트랙은 기본적으로 SoundFont2 플레이어로 재생되므로 MIDI 파일을 가져온 뒤 재생하면 아무 소리도 재생되지 않을 것입니다. + + + Track + 트랙 + + + You have not set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. + + + + + MidiJack + + JACK server down + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) + JAK 서버 종료 + + + The JACK server seems to be shuted down. + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) + JACK 서버가 종료된 것 같습니다. + + + + MidiPort + + Input channel + 입력 채널 + + + Output channel + 출력 채널 + + + Input controller + 입력 컨트롤러 + + + Output controller + 출력 컨트롤러 + + + Fixed input velocity + 입력 벨로시티 고정값 + + + Fixed output velocity + 출력 벨로시티 고정값 + + + Fixed output note + 출력 음높이 고정값 + + + Output MIDI program + 출력 MIDI 프로그램 + + + Base velocity + 기준 벨로시티 + + + Receive MIDI-events + MIDI 이벤트 받기 + + + Send MIDI-events + MIDI 이벤트 보내기 + + + + MidiSetupWidget + + DEVICE + 장치 + + + + MonstroInstrument + + Osc 3 Stereo phase offset + + + + Selected view + + + + Sine wave + 사인파 + + + Bandlimited Triangle wave + 대역 제한 삼각파 + + + Bandlimited Saw wave + 대역 제한 톱니파 + + + Bandlimited Ramp wave + 대역 제한 역톱니파 + + + Bandlimited Square wave + 대역 제한 사각파 + + + Bandlimited Moog saw wave + 대역 제한 Moog 톱니파 + + + Soft square wave + + + + Absolute sine wave + + + + Exponential wave + 지수형 파형 + + + White noise + 화이트 노이즈 + + + Digital Triangle wave + 삼각파 + + + Digital Saw wave + 톱니파 + + + Digital Ramp wave + 역톱니파 + + + Digital Square wave + 사각파 + + + Digital Moog saw wave + Moog 톱니파 + + + Triangle wave + 삼각파 + + + Saw wave + 톱니파 + + + Ramp wave + 역톱니파 + + + Square wave + 사각파 + + + Moog saw wave + Moog 톱니파 + + + Abs. sine wave + + + + Random + 무작위 + + + Random smooth + + + + Osc 1 volume + 오실레이터 1 음량 + + + Osc 1 panning + 오실레이터 1 패닝 + + + Osc 1 coarse detune + + + + Osc 1 fine detune left + + + + Osc 1 fine detune right + + + + Osc 1 stereo phase offset + + + + Osc 1 pulse width + + + + Osc 1 sync send on rise + + + + Osc 1 sync send on fall + + + + Osc 2 volume + 오실레이터 2 음량 + + + Osc 2 panning + 오실레이터 2 패닝 + + + Osc 2 coarse detune + + + + Osc 2 fine detune left + + + + Osc 2 fine detune right + + + + Osc 2 stereo phase offset + + + + Osc 2 waveform + 오실레이터 2 파형 + + + Osc 2 sync hard + + + + Osc 2 sync reverse + + + + Osc 3 volume + 오실레이터 3 음량 + + + Osc 3 panning + 오실레이터 3 패닝 + + + Osc 3 coarse detune + + + + Osc 3 sub-oscillator mix + + + + Osc 3 waveform 1 + 오실레이터 3 파형 1 + + + Osc 3 waveform 2 + 오실레이터 3 파형 2 + + + Osc 3 sync hard + + + + Osc 3 Sync reverse + + + + LFO 1 waveform + + + + LFO 1 attack + + + + LFO 1 rate + + + + LFO 1 phase + + + + LFO 2 waveform + + + + LFO 2 attack + + + + LFO 2 rate + + + + LFO 2 phase + + + + Env 1 pre-delay + + + + Env 1 attack + + + + Env 1 hold + + + + Env 1 decay + + + + Env 1 sustain + + + + Env 1 release + + + + Env 1 slope + + + + Env 2 pre-delay + + + + Env 2 attack + + + + Env 2 hold + + + + Env 2 decay + + + + Env 2 sustain + + + + Env 2 release + + + + Env 2 slope + + + + Osc 2+3 modulation + + + + Osc 1 - Vol env 1 + + + + Osc 1 - Vol env 2 + + + + Osc 1 - Vol LFO 1 + + + + Osc 1 - Vol LFO 2 + + + + Osc 2 - Vol env 1 + + + + Osc 2 - Vol env 2 + + + + Osc 2 - Vol LFO 1 + + + + Osc 2 - Vol LFO 2 + + + + Osc 3 - Vol env 1 + + + + Osc 3 - Vol env 2 + + + + Osc 3 - Vol LFO 1 + + + + Osc 3 - Vol LFO 2 + + + + Osc 1 - Phs env 1 + + + + Osc 1 - Phs env 2 + + + + Osc 1 - Phs LFO 1 + + + + Osc 1 - Phs LFO 2 + + + + Osc 2 - Phs env 1 + + + + Osc 2 - Phs env 2 + + + + Osc 2 - Phs LFO 1 + + + + Osc 2 - Phs LFO 2 + + + + Osc 3 - Phs env 1 + + + + Osc 3 - Phs env 2 + + + + Osc 3 - Phs LFO 1 + + + + Osc 3 - Phs LFO 2 + + + + Osc 1 - Pit env 1 + + + + Osc 1 - Pit env 2 + + + + Osc 1 - Pit LFO 1 + + + + Osc 1 - Pit LFO 2 + + + + Osc 2 - Pit env 1 + + + + Osc 2 - Pit env 2 + + + + Osc 2 - Pit LFO 1 + + + + Osc 2 - Pit LFO 2 + + + + Osc 3 - Pit env 1 + + + + Osc 3 - Pit env 2 + + + + Osc 3 - Pit LFO 1 + + + + Osc 3 - Pit LFO 2 + + + + Osc 1 - PW env 1 + + + + Osc 1 - PW env 2 + + + + Osc 1 - PW LFO 1 + + + + Osc 1 - PW LFO 2 + + + + Osc 3 - Sub env 1 + + + + Osc 3 - Sub env 2 + + + + Osc 3 - Sub LFO 1 + + + + Osc 3 - Sub LFO 2 + + + + + MonstroView + + Operators view + + + + Matrix view + + + + Volume + 음량 + + + Panning + 패닝 + + + Coarse detune + + + + semitones + 반음 + + + cents + 센트 + + + Stereo phase offset + + + + deg + + + + Pulse width + 펄스 폭 + + + Send sync on pulse rise + + + + Send sync on pulse fall + + + + Hard sync oscillator 2 + + + + Reverse sync oscillator 2 + + + + Sub-osc mix + + + + Hard sync oscillator 3 + + + + Reverse sync oscillator 3 + + + + Attack + + + + Rate + + + + Phase + 위상 + + + Pre-delay + + + + Hold + + + + Decay + + + + Sustain + + + + Release + + + + Slope + + + + Modulation amount + + + + Fine tune left + + + + Fine tune right + + + + Mix osc 2 with osc 3 + + + + Modulate amplitude of osc 3 by osc 2 + + + + Modulate frequency of osc 3 by osc 2 + + + + Modulate phase of osc 3 by osc 2 + + + + + MultitapEchoControlDialog + + Length + 길이 + + + Step length: + + + + Dry + + + + Stages + + + + Swap inputs + 좌우 입력 바꾸기 + + + Dry gain: + + + + Low-pass stages: + + + + Swap left and right input channels for reflections + + + + + NesInstrument + + Channel 2 Coarse detune + + + + Channel 2 Volume + + + + Channel 4 Volume + + + + Master volume + 마스터 음량 + + + Vibrato + 비브라토 + + + Channel 1 coarse detune + + + + Channel 1 volume + + + + Channel 1 envelope length + + + + Channel 1 duty cycle + + + + Channel 1 sweep amount + + + + Channel 1 sweep rate + + + + Channel 2 envelope length + + + + Channel 2 duty cycle + + + + Channel 2 sweep amount + + + + Channel 2 sweep rate + + + + Channel 3 coarse detune + + + + Channel 3 volume + + + + Channel 4 volume + + + + Channel 4 envelope length + + + + Channel 4 noise frequency + + + + Channel 4 noise frequency sweep + + + + NesInstrumentView Volume - 볼륨 + 음량 + + + Coarse detune + + + + Envelope length + + + + Enable channel 1 + 채널 1 활성화 + + + Enable envelope 1 + 엔벨로프 1 활성화 + + + Enable envelope 1 loop + + + + Enable sweep 1 + + + + Sweep amount + + + + Sweep rate + + + + 12.5% Duty cycle + + + + 25% Duty cycle + + + + 50% Duty cycle + + + + 75% Duty cycle + + + + Enable channel 2 + 채널 2 활성화 + + + Enable envelope 2 + 엔벨로프 2 활성화 + + + Enable envelope 2 loop + + + + Enable sweep 2 + + + + Enable channel 3 + 채널 3 활성화 + + + Noise Frequency + + + + Frequency sweep + + + + Enable channel 4 + 채널 4 활성화 + + + Enable envelope 4 + 엔벨로프 4 활성화 + + + Enable envelope 4 loop + + + + Quantize noise frequency when using note frequency + + + + Use note frequency for noise + + + + Noise mode + + + + Vibrato + 비브라토 + + + Master volume + 마스터 음량 + + + + OpulenzInstrument + + Patch + 패치 + + + Op 1 attack + + + + Op 1 decay + + + + Op 1 sustain + + + + Op 1 release + + + + Op 1 level + + + + Op 1 level scaling + + + + Op 1 frequency multiplier + + + + Op 1 feedback + + + + Op 1 key scaling rate + + + + Op 1 percussive envelope + + + + Op 1 tremolo + + + + Op 1 vibrato + + + + Op 1 waveform + + + + Op 2 attack + + + + Op 2 decay + + + + Op 2 sustain + + + + Op 2 release + + + + Op 2 level + + + + Op 2 level scaling + + + + Op 2 frequency multiplier + + + + Op 2 key scaling rate + + + + Op 2 percussive envelope + + + + Op 2 tremolo + + + + Op 2 vibrato + + + + Op 2 waveform + + + + FM + FM + + + Vibrato depth + + + + Tremolo depth + + + + + OpulenzInstrumentView + + Attack + + + + Decay + + + + Release + + + + Frequency multiplier + + + + + OscillatorObject + + Osc %1 waveform + 오실레이터 %1 파형 + + + Osc %1 harmonic + + + + Osc %1 volume + 오실레이터 %1 음량 + + + Osc %1 panning + 오실레이터 %1 패닝 + + + Osc %1 fine detuning left + + + + Osc %1 coarse detuning + + + + Osc %1 fine detuning right + + + + Osc %1 phase-offset + 오실레이터 %1 위상 + + + Osc %1 stereo phase-detuning + 오실레이터 %1 좌우 위상차 + + + Osc %1 wave shape + 오실레이터 %1 파형 + + + Modulation type %1 + 변조 유형 %1 + + + + PatchesDialog + + Qsynth: Channel Preset + + + + Bank selector + + + + Bank + 뱅크 + + + Program selector + + + + Patch + 패치 + + + Name + 이름 + + + OK + 확인 + + + Cancel + 취소 + + + + PatmanView + + Loop + 루프 + + + Loop mode + 루프 모드 + + + Tune + + + + Tune mode + + + + No file selected + 파일이 선택되지 않음 + + + Open patch file + 패치 파일 열기 + + + Patch-Files (*.pat) + 패치 파일 (*.pat) + + + Open patch + + + + + PatternView + + Open in piano-roll + 피아노-롤에서 열기 + + + Clear all notes + 전체 음표 지우기 + + + Reset name + 이름 초기화 + + + Change name + 이름 바꾸기 + + + Add steps + + + + Remove steps + + + + Clone Steps + + + + Set as ghost in piano-roll + + + + + PeakController + + Peak Controller + 피크 컨트롤러 + + + Peak Controller Bug + 피크 컨트롤러 버그 + + + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. + 이전 버전 LMMS의 버그로 인해 피크 컨트롤러가 제대로 연결되지 않았을 수 있습니다. 피크 컨트롤러가 제대로 연결되었는지 확인 후 파일을 다시 저장해 주시기 바랍니다. 불편을 드려 죄송합니다. + + + + PeakControllerDialog + + PEAK + + + + LFO Controller + LFO 컨트롤러 + + + + PeakControllerEffectControlDialog + + BASE + 기준 + + + AMNT + + + + Modulation amount: + + + + MULT + + + + ATCK + + + + Attack: + + + + DCAY + + + + Release: + + + + TRSH + + + + Treshold: + + + + Base: + + + + Amount multiplicator: + + + + Mute output + 출력 음소거 + + + Absolute value + + + + + PeakControllerEffectControls + + Base value + 기준 값 + + + Modulation amount + + + + Attack + + + + Release + + + + Treshold + + + + Mute output + 출력 음소거 + + + Absolute value + 절댓값 + + + Amount multiplicator + + + + + PianoRoll + + Note Velocity + 음표 벨로시티 + + + Note Panning + 음표 패닝 + + + Mark/unmark current semitone + 현재 반음 표시 + + + Mark/unmark all corresponding octave semitones + + + + Mark current scale + + + + Mark current chord + + + + Unmark all + 모두 표시 해제 + + + Select all notes on this key + 이 음의 음표 모두 선택 + + + Note lock + 박자 잠금 + + + Last note + 마지막 박자 + + + No scale + 음계 없음 + + + No chord + 코드 없음 + + + Velocity: %1% + 벨로시티: %1% + + + Panning: %1% left + 패닝: %1% 왼쪽 + + + Panning: %1% right + 패닝: %1% 오른쪽 + + + Panning: center + 패닝: 가운데 + + + Please open a pattern by double-clicking on it! + 더블클릭하여 패턴을 열어주세요! + + + Please enter a new value between %1 and %2: + %1부터 %2까지의 값을 입력하세요: + + + + PianoRollWindow + + Play/pause current pattern (Space) + 현재 패턴 재생/일시정지 (Space) + + + Record notes from MIDI-device/channel-piano + + + + Record notes from MIDI-device/channel-piano while playing song or BB track + + + + Stop playing of current pattern (Space) + 현재 패턴 정지 (Space) + + + Edit actions + 편집 동작 + + + Draw mode (Shift+D) + 그리기 모드 (Shift+D) + + + Erase mode (Shift+E) + 지우기 모드 (Shift+E) + + + Select mode (Shift+S) + 선택 모드 (Shift+S) + + + Pitch Bend mode (Shift+T) + + + + Quantize + + + + Copy paste controls + 복사/붙여넣기 컨트롤 + + + Timeline controls + + + + Zoom and note controls + + + + Piano-Roll - %1 + 피아노-롤 - %1 + + + Piano-Roll - no pattern + 피아노-롤 - 패턴 없음 + + + Record notes from MIDI-device/channel-piano, one step at the time + + + + Cut (%1+X) + 잘라내기 (%1+X) + + + Copy (%1+C) + 복사 (%1+C) + + + Paste (%1+V) + 붙여넣기 (%1+V) + + + Horizontal zooming + + + + Quantization + + + + Note length + 음표 길이 + + + Scale + + + + Chord + + + + Clear ghost notes + + + + + PianoView + + Base note + 기준 음 + + + + Plugin + + Plugin not found + 플러그인을 찾을 수 없음 + + + The plugin "%1" wasn't found or could not be loaded! +Reason: "%2" + 플러그인 "%1"을(를) 찾을 수 없거나 읽어올 수 없습니다. +이유: %2 + + + Error while loading plugin + 플러그인 로딩 오류 + + + Failed to load plugin "%1"! + 플러그인 "%1"을(를) 로딩할 수 없습니다! + + + + PluginBrowser + + Instrument Plugins + 악기 플러그인 + + + Instrument browser + 악기 탐색기 + + + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. + 플러그인을 노래 편집기, 비트/베이스 라인 편집기, 이미 존재하는 악기 트랙 중 하나로 드래그하세요. + + + + PluginFactory + + Plugin not found. + 플러그인을 찾을 수 없습니다. + + + LMMS plugin %1 does not have a plugin descriptor named %2! + LMMS 플러그인 %1은(는) 이름이 %2인 플러그인 디스크립터를 가지고 있지 않습니다! + + + + ProjectNotes + + Edit Actions + 편집 동작 + + + &Undo + 실행 취소(&U) + + + %1+Z + %1+Z + + + &Redo + 다시 실행(&R) + + + %1+Y + %1+Y + + + &Copy + 복사(&C) + + + %1+C + %1+C + + + Cu&t + 잘라내기(&T) + + + %1+X + %1+X + + + &Paste + 붙여넣기(&P) + + + %1+V + %1+V + + + Format Actions + 서식 동작 + + + &Bold + 굵게(&B) + + + %1+B + %1+B + + + &Italic + 기울임꼴(&I) + + + %1+I + %1+I + + + &Underline + 밑줄(&U) + + + %1+U + %1+U + + + &Left + 왼쪽 정렬(&L) + + + %1+L + %1+L + + + C&enter + 가운데 정렬(&E) + + + %1+E + %1+E + + + &Right + 오른쪽 정렬(&R) + + + %1+R + %1+R + + + &Justify + 양쪽 정렬(&J) + + + %1+J + %1+J + + + &Color... + 색(&C)... + + + Project Notes + 프로젝트 노트 + + + Enter project notes here + 여기에 프로젝트 노트를 입력하세요 + + + + ProjectRenderer + + WAV (*.wav) + WAV (*.wav) + + + FLAC (*.flac) + FLAC (*.flac) + + + OGG (*.ogg) + OGG (*.ogg) + + + MP3 (*.mp3) + MP3 (*.mp3) + + + + QWidget + + Name: + 이름: + + + Maker: + 제작자: + + + Copyright: + 저작권: + + + Requires Real Time: + + + + Yes + + + + No + 아니오 + + + Real Time Capable: + 실제 시간 가능: + + + In Place Broken: + 깨진 곳에 위치: + + + Channels In: + 입력 채널: + + + Channels Out: + 출력 채널: + + + File: %1 + 파일: %1 + + + File: + 파일: + + + + RenameDialog + + Rename... + 이름 바꾸기... + + + + ReverbSCControlDialog + + Input + 입력 + + + Size + 크기 + + + Size: + 크기: + + + Color + 음색 + + + Color: + 음색: + + + Output + 출력 + + + Input gain: + 입력 이득: + + + Output gain: + 출력 이득: + + + + ReverbSCControls + + Size + 크기 + + + Color + 음색 + + + Input gain + 입력 이득 + + + Output gain + 출력 이득 + + + + SampleBuffer + + Fail to open file + 파일을 열 수 없음 + + + Audio files are limited to %1 MB in size and %2 minutes of playing time + 오디오 파일은 %1MB보다 작고 %2분보다 짧아야 합니다 + + + Open audio file + 오디오 파일 열기 + + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + 모든 오디오 파일 (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + + + Wave-Files (*.wav) + Wave 파일(*.wav) + + + OGG-Files (*.ogg) + OGG 파일(*.ogg) + + + DrumSynth-Files (*.ds) + DrumSynth 파일(*.ds) + + + FLAC-Files (*.flac) + FLAC 파일(*.flac) + + + SPEEX-Files (*.spx) + SPEEX 파일(*.spx) + + + VOC-Files (*.voc) + VOC 파일(*.voc) + + + AIFF-Files (*.aif *.aiff) + AIFF 파일 (*.aif *.aiff) + + + AU-Files (*.au) + AU 파일 (*.au) + + + RAW-Files (*.raw) + RAW 파일 (*.raw) + + + + SampleTCOView + + Delete (middle mousebutton) + 삭제(마우스 가운데 버튼) + + + Cut + 잘라내기 + + + Copy + 복사 + + + Paste + 붙여넣기 + + + Mute/unmute (<%1> + middle click) + 음소거/해제 (<%1> + 마우스 가운데 버튼) + + + Double-click to open sample + 더블클릭하여 샘플 열기 + + + + SampleTrack + + Volume + 음량 - Coarse detune + Panning + 패닝 + + + Sample track + 샘플 트랙 + + + FX channel + FX 채널 + + + + SampleTrackView + + Track volume + 트랙 음량 + + + Channel volume: + 채널 음량: + + + VOL + 음량 + + + Panning + 패닝 + + + Panning: + 패닝: + + + PAN + 패닝 + + + FX %1: %2 + FX %1: %2 + + + + SampleTrackWindow + + GENERAL SETTINGS + 일반 설정 + + + Sample volume + 샘플 음량 + + + Volume: + 음량: + + + VOL + 음량 + + + Panning + 패닝 + + + Panning: + 패닝: + + + PAN + 패닝 + + + FX channel + FX 채널 + + + FX + FX + + + + SaveOptionsWidget + + Discard MIDI connections + MIDI 연결 제거 + + + + SetupDialog + + Setup LMMS + LMMS 설정 + + + General settings + 일반 설정 + + + BUFFER SIZE + 버퍼 크기 + + + MISC + 기타 + + + Use built-in NaN handler - Envelope length + PLUGIN EMBEDDING - Enable channel 1 - 채널 1 활성화 + No embedding + - Enable envelope 1 - 엔벨로프 1 활성화 + Embed using Qt API + - Enable envelope 1 loop + Embed using native Win32 API - Enable sweep 1 + Embed using XEmbed protocol - Sweep amount - + LANGUAGE + 언어 + + + Paths + 경로 + + + Directories + 경로 + + + Performance settings + 성능 설정 + + + Auto save + 자동 저장 + + + Enable auto-save + 자동 저장 활성화 + + + Allow auto-save while playing + 재생 중 자동 저장 허용 - Sweep rate - + UI effects vs. performance + UI 효과 vs. 성능 - 12.5% Duty cycle - + Smooth scroll in Song Editor + 노래 편집기에서 부드러운 스크롤 사용 - 25% Duty cycle + Show playback cursor in AudioFileProcessor - 50% Duty cycle - + Audio settings + 오디오 설정 - 75% Duty cycle - + AUDIO INTERFACE + 오디오 인터페이스 - Enable channel 2 - 채널 2 활성화 + MIDI settings + MIDI 설정 - Enable envelope 2 - 엔벨로프 2 활성화 + MIDI INTERFACE + MIDI 인터페이스 - Enable envelope 2 loop - + OK + 확인 - Enable sweep 2 - + Cancel + 취소 - Enable channel 3 - 채널 3 활성화 + Restart LMMS + LMMS 다시 시작 - Noise Frequency + Please note that most changes won't take effect until you restart LMMS! - Frequency sweep - + Frames: %1 +Latency: %2 ms + 프레임: %1 +시간 지연: %2 ms - Enable channel 4 - 채널 4 활성화 + Choose LMMS working directory + LMMS 작업 경로 선택 - Enable envelope 4 - 엔벨로프 4 활성화 + Choose your GIG directory + GIG 경로 선택 - Enable envelope 4 loop - + Choose your SF2 directory + SF2 경로 선택 - Quantize noise frequency when using note frequency - + Choose your VST-plugin directory + VST 플러그인 경로 선택 - Use note frequency for noise - + Choose artwork-theme directory + 아트워크 경로 선택 - Noise mode + Choose LADSPA plugin directory + LADSPA 플러그인 경로 선택 + + + Choose STK rawwave directory - Vibrato - 비브라토 + Choose default SoundFont + 기본 사운드폰트 설정 - Master volume - 마스터 볼륨 + Choose background artwork + 배경 아트워크 선택 - - - OpulenzInstrument - Patch - 패치 + minutes + - Op 1 attack - + minute + - Op 1 decay - + Disabled + 비활성화됨 - Op 1 sustain - + Auto-save interval: %1 + 자동 저장 간격: %1 - Op 1 release + Reset to default value - Op 1 level + Keep plugin windows on top when not embedded + + + Song - Op 1 level scaling - + Tempo + 템포 - Op 1 frequency multiplier - + Master volume + 마스터 음량 - Op 1 feedback - + Master pitch + 마스터 피치 - Op 1 key scaling rate - + LMMS Error report + LMMS 오류 보고 - Op 1 percussive envelope - + The following errors occured while loading: + 로딩 중 다음과 같은 오류가 발생하였습니다: + + + SongEditor - Op 1 tremolo - + Could not open file + 파일을 열 수 없음 - Op 1 vibrato - + Could not open file %1. You probably have no permissions to read this file. + Please make sure to have at least read permissions to the file and try again. + 파일 %1을(를) 열 수 없습니다. 파일을 읽을 수 있는 권한이 없기 때문일 수 있습니다. 파일을 읽을 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다. - Op 1 waveform - + Could not write file + 파일을 쓸 수 없음 - Op 2 attack - + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. + 파일 %1을(를) 쓰기 위하여 열 수 없습니다. 파일을 쓸 수 있는 권한이 없기 때문일 수 있습니다. 파일에 쓸 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다. - Op 2 decay - + Error in file + 파일 오류 - Op 2 sustain - + The file %1 seems to contain errors and therefore can't be loaded. + 파일 %1에 오류가 있어 로딩에 실패하였습니다. - Op 2 release - + Version difference + 버전 차이 - Op 2 level - + This %1 was created with LMMS %2. + 이 %1은(는) LMMS %2에서 만들어졌습니다. - Op 2 level scaling - + template + 템플릿 - Op 2 frequency multiplier - + project + 프로젝트 - Op 2 key scaling rate - + Tempo + 템포 - Op 2 percussive envelope - + High quality mode + 고음질 모드 - Op 2 tremolo - + Master volume + 마스터 음량 - Op 2 vibrato - + Master pitch + 마스터 피치 - Op 2 waveform - + Value: %1% + 값: %1% - FM - + Value: %1 semitones + 값: %1반음 - Vibrato depth - + TEMPO + 템포 - Tremolo depth - + Tempo in BPM + BPM 단위의 템포 - OpulenzInstrumentView + SongEditorWindow - Attack - + Song-Editor + 노래 편집기 - Decay - + Play song (Space) + 노래 재생 (Space) - Release - + Record samples from Audio-device + 오디오 장치로부터 샘플 녹음 - Frequency multiplier - + Record samples from Audio-device while playing song or BB track + 노래 또는 비트/베이스 라인 트랙을 재생하는 동안 오디오 장치로부터 샘플 녹음 - - - OscillatorObject - Osc %1 volume - + Stop song (Space) + 노래 정지 (Space) - Osc %1 panning + Track actions - Osc %1 coarse detuning - + Add beat/bassline + 비트/베이스 라인 추가 - Osc %1 fine detuning left - + Add sample-track + 샘플 트랙 추가 - Osc %1 fine detuning right - + Add automation-track + 오토메이션 트랙 추가 - Osc %1 phase-offset - + Edit actions + 편집 동작 - Osc %1 stereo phase-detuning + Draw mode + 그리기 모드 + + + Edit mode (select and move) + 편집 모드 (선택 및 이동) + + + Timeline controls - Osc %1 wave shape + Zoom controls - Modulation type %1 + Horizontal zooming + + + SpectrumAnalyzerControlDialog - Osc %1 waveform - 오실레이터 %1 파형 + Linear spectrum + 선형 스펙트럼 - Osc %1 harmonic - + Linear Y axis + 선형 Y축 - PatchesDialog + SpectrumAnalyzerControls - Qsynth: Channel Preset - + Linear spectrum + 선형 스펙트럼 - Bank selector - + Linear Y axis + 선형 Y축 - Bank - 뱅크 + Channel mode + 채널 모드 + + + StepRecorderWidget - Program selector + Hint + + + + Move recording curser using <Left/Right> arrows + + + SubWindow - Patch - 패치 + Close + 닫기 - Name - 이름 + Maximize + 최대화 - OK - 확인 + Restore + 복원 + + + TabWidget - Cancel - 취소 + Settings for %1 + %1에 대한 설정 - PatmanView + TempoSyncKnob - Loop - 루프 + Tempo Sync + 템포 동기화 - Loop mode - 루프 모드 + No Sync + 동기화 없음 - Tune - + Eight beats + 여덟 박자 - Tune mode - + Whole note + 온음표 - No file selected - + Half note + 2분음표 - Open patch file - 패치 파일 열기 + Quarter note + 4분음표 - Patch-Files (*.pat) - 패치 파일 (*.pat) + 8th note + 8분음표 - Open patch - + 16th note + 16분음표 - - - PeakControllerEffectControlDialog - BASE - + 32nd note + 32분음표 - Modulation amount: - + Custom... + 사용자 지정... - Attack: - + Custom + 사용자 지정 - Release: - + Synced to Eight Beats + 여덟 박자에 동기화됨 - AMNT - + Synced to Whole Note + 온음표에 동기화됨 - MULT - + Synced to Half Note + 2분음표에 동기화됨 - ATCK - + Synced to Quarter Note + 4분음표에 동기화됨 - DCAY - + Synced to 8th Note + 8분음표에 동기화됨 - Treshold: - + Synced to 16th Note + 16분음표에 동기화됨 - TRSH - + Synced to 32nd Note + 32분음표에 동기화됨 + + + + TimeDisplayWidget + + MIN + - Base: - + SEC + - Amount multiplicator: - + MSEC + 밀리초 - Mute output - + BAR + 마디 - Absolute value - + BEAT + + + + TICK + + + + Time units + 시간 단위 - PeakControllerEffectControls + TimeLineWidget - Base value - + After stopping go back to begin + 정지한 뒤 시작점으로 이동 - Modulation amount - + After stopping go back to position at which playing was started + 정지한 뒤 재생을 시작한 점으로 이동 - Mute output - + After stopping keep position + 정지한 후 위치 유지 - Attack - + Hint + - Release - + Press <%1> to disable magnetic loop points. + <%1> 키를 눌러 반복 지점을 자유롭게 이동할 수 있습니다. - Treshold - + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + <Shift> 키를 누르면 반복 시작점을 움직일 수 있습니다; <%1> 키를 눌러 반복 지점을 자유롭게 움직일 수 있습니다. - - Absolute value - + + Auto scrolling + 자동 스크롤 - Amount multiplicator - + Loop points + 루프 지점 - QWidget + Track - Name: - 이름: + Mute + 음소거 - Maker: - 제작자: + Solo + 독주 + + + TrackContainer - Copyright: - 저작권: + Couldn't import file + 파일을 가져올 수 없음 - Requires Real Time: - + Couldn't find a filter for importing file %1. +You should convert this file into a format supported by LMMS using another software. + 파일 %1을(를) 가져오기 위한 필터를 찾을 수 없습니다. +이 파일을 가져오려면 다른 프로그램을 사용하여 LMMS가 지원하는 포맷으로 변환하시기 바랍니다. - Yes - + Couldn't open file + 파일을 열 수 없음 - No - 아니오 + Couldn't open file %1 for reading. +Please make sure you have read-permission to the file and the directory containing the file and try again! + 파일 %1을(를) 읽기 열 수 없습니다. 파일을 읽을 수 있는 권한이 있는지 확인 후 다시 시도하시기 바랍니다! - Real Time Capable: - 실제 시간 가능: + Loading project... + 프로젝트 로딩 중... - In Place Broken: - 깨진 곳에 위치: + Cancel + 취소 - Channels In: - 입력 채널: + Please wait... + 잠시만 기다려 주세요... - Channels Out: - 출력 채널: + Loading cancelled + 로딩 취소됨 - File: - 파일: + Project loading was cancelled. + 프로젝트 로딩이 취소되었습니다. - File: %1 - 파일: %1 + Loading Track %1 (%2/Total %3) + 트랙 %1 로딩 중 (%2/총 %3) + + + Importing MIDI-file... + MIDI 파일을 가져오는중... - ReverbSCControlDialog + TrackContentObject - Input - 입력 + Mute + 음소거 + + + TrackContentObjectView - Size - + Current position + 현재 위치 - Size: - + Hint + - Color - + Press <%1> and drag to make a copy. + <%1> 키를 누른 채 드래그하여 복사합니다. - Color: - + Current length + 현재 길이 - Output - 출력 + Press <%1> for free resizing. + <%1> 키를 눌러 크기를 자유롭게 조절할 수 있습니다. - Input gain: - 입력 이득: + %1:%2 (%3:%4 to %5:%6) + %1:%2 (%3:%4부터 %5:%6까지) - Output gain: - 출력 이득: + Delete (middle mousebutton) + 삭제(마우스 가운데 버튼) - - - ReverbSCControls - Size - + Cut + 잘라내기 - Color - + Copy + 복사 - Input gain - 입력 이득 + Paste + 붙여넣기 - Output gain - 출력 이득 + Mute/unmute (<%1> + middle click) + 음소거/해제 (<%1> + 마우스 가운데 버튼) - SpectrumAnalyzerControlDialog + TrackOperationsWidget - Linear spectrum - 선형 스펙트럼 + Mute + 음소거 - Linear Y axis - 선형 Y축 + Solo + 독주 - - - SpectrumAnalyzerControls - Linear spectrum - 선형 스펙트럼 + Clone this track + 트랙 복제 - Linear Y axis - 선형 Y축 + Remove this track + 트랙 제거 - Channel mode - 채널 모드 + Clear this track + 트랙 초기화 - - - TrackContainer - Cancel - 취소 + FX %1: %2 + FX %1: %2 - Please wait... - 잠시만 기다려 주세요... + Assign to new FX Channel + 새 FX 채널 할당 - Importing MIDI-file... - MIDI 파일을 가져오는중... + Turn all recording on + + + + Turn all recording off + + + + Press <%1> while clicking on move-grip to begin a new drag'n'drop action. + + + + Actions + @@ -2604,11 +6839,11 @@ Osc %1 volume: - 오실레이터 %1 볼륨: + 오실레이터 %1 음량: Osc %1 panning: - + 오실레이터 %1 패닝: Osc %1 coarse detuning: @@ -2676,55 +6911,58 @@ Sine wave - 사인파 + 사인파 Triangle wave - 삼각파 + 삼각파 Saw wave - 톱니파 + 톱니파 Square wave - 사각파 + 사각파 Moog-like saw wave - + Moog 톱니파 Exponential wave - + 지수형 파형 White noise - 화이트 노이즈 + 화이트 노이즈 User-defined wave - + 사용자 지정 파형 - VestigeInstrumentView + VersionedSaveDialog - Show/hide GUI - GUI 보이기/숨기기 + Increment version number + 버전 증가 - Turn off all notes - 모든 음 끄기 + Decrement version number + 버전 감소 - DLL-files (*.dll) - DLL 파일 (*.dll) + already exists. Do you want to replace it? + 이(가) 이미 존재합니다. 덮어쓰시겠습니까? - EXE-files (*.exe) - EXE 파일 (*.exe) + Save Options + 저장 옵션 + + + VestigeInstrumentView Previous (-) 이전 (-) @@ -2737,6 +6975,22 @@ Next (+) 다음 (+) + + Show/hide GUI + GUI 보이기/숨기기 + + + Turn off all notes + 모든 음 끄기 + + + DLL-files (*.dll) + DLL 파일 (*.dll) + + + EXE-files (*.exe) + EXE 파일 (*.exe) + Preset 프리셋 @@ -2766,6 +7020,17 @@ + + VisualizationWidget + + Click to enable + 클릭하여 활성화 + + + Oscilloscope + 오실로스코프 + + VstEffectControlDialog @@ -2804,8 +7069,8 @@ VstPlugin - Loading plugin - 플러그인 읽는 중 + The VST plugin %1 could not be loaded. + VST 플러그인 %1을 불러올 수 없습니다. Open Preset @@ -2848,31 +7113,31 @@ .fxb - Please wait while loading VST plugin... - VST 플러그인을 읽을 동안 잠시 기다려 주세요... + Loading plugin + 플러그인 읽는 중 - The VST plugin %1 could not be loaded. - VST 플러그인 %1을 불러올 수 없습니다. + Please wait while loading VST plugin... + VST 플러그인을 읽을 동안 잠시 기다려 주세요... WatsynInstrument Volume A1 - A1 볼륨 + A1 음량 Volume A2 - A2 볼륨 + A2 음량 Volume B1 - B1 볼륨 + B1 음량 Volume B2 - B2 볼륨 + B2 음량 Panning A1 @@ -2972,11 +7237,59 @@ Selected graph - + 선택된 그래프 WatsynView + + Volume + 음량 + + + Panning + 패닝 + + + Freq. multiplier + + + + Left detune + + + + cents + 센트 + + + Right detune + + + + A-B Mix + + + + Mix envelope amount + + + + Mix envelope attack + + + + Mix envelope hold + + + + Mix envelope decay + + + + Crosstalk + + Select oscillator A1 @@ -3041,54 +7354,6 @@ Square wave 사각파 - - Volume - 볼륨 - - - Panning - 패닝 - - - Freq. multiplier - - - - Left detune - - - - cents - 센트 - - - Right detune - - - - A-B Mix - - - - Mix envelope amount - - - - Mix envelope attack - - - - Mix envelope hold - - - - Mix envelope decay - - - - Crosstalk - - Modulate amplitude of A1 by output of A2 @@ -3127,14 +7392,14 @@ Saw wave - 톱니파 + 톱니파 Xpressive Selected graph - + 선택된 그래프 A1 @@ -3177,7 +7442,7 @@ XpressiveView Draw your own waveform here by dragging your mouse on this graph. - 드래그하여 원하는 파형을 그리세요. + 드래그하여 원하는 파형을 그리세요. Select oscillator W1 @@ -3205,7 +7470,7 @@ Sine wave - 사인파 + 사인파 Moog-saw wave @@ -3213,11 +7478,11 @@ Exponential wave - + 지수형 파형 Saw wave - 톱니파 + 톱니파 User-defined wave @@ -3225,15 +7490,15 @@ Triangle wave - 삼각파 + 삼각파 Square wave - 사각파 + 사각파 White noise - 화이트 노이즈 + 화이트 노이즈 WaveInterpolate @@ -3309,10 +7574,6 @@ ZynAddSubFxView - - Show GUI - GUI 표시 - Portamento: 포르타멘토: @@ -3343,7 +7604,7 @@ Resonance center frequency: - + 공명 중심 주파수: RES CF @@ -3351,12 +7612,16 @@ Resonance bandwidth: - + 공명 대역폭: RES BW + + Show GUI + GUI 표시 + Filter frequency: @@ -3388,22 +7653,22 @@ End of sample 샘플 끝 + + Loopback point + 루프 시작점 + Reverse sample 샘플 역으로 - Stutter - + Loop mode + 루프 모드 - Loopback point + Stutter - - Loop mode - 루프 모드 - Interpolation mode 보간법 @@ -3418,7 +7683,7 @@ Sinc - + Sinc Sample not found: %1 @@ -3429,11 +7694,15 @@ bitInvader Sample length - + 샘플 길이 bitInvaderView + + Draw your own waveform here by dragging your mouse on this graph. + 드래그하여 원하는 파형을 그리세요. + Sine wave 사인파 @@ -3458,25 +7727,21 @@ Normalize 규격화 - - Draw your own waveform here by dragging your mouse on this graph. - 드래그하여 원하는 파형을 그리세요. - Sample length - + 샘플 길이 White noise - 화이트 노이즈 + 화이트 노이즈 User-defined wave - + 사용자 지정 파형 Smooth waveform - 파형을 부드럽게 + 파형을 부드럽게 @@ -3515,15 +7780,15 @@ Process based on the maximum of both stereo channels - + 두 채널의 최댓값을 기준으로 효과 적용 Process based on the average of both stereo channels - + 두 채널의 평균을 기준으로 효과 적용 Process each stereo channel independently - + 각각의 채널에 독립적으로 효과 적용 Reset wavegraph @@ -3577,6 +7842,13 @@ 스테레오 모드 + + graphModel + + Graph + 그래프 + + kickerInstrument @@ -3587,14 +7859,14 @@ End frequency 끝 주파수 - - Gain - 이득 - Length 길이 + + Gain + 이득 + Noise 잡음 @@ -3605,11 +7877,11 @@ Start from note - + 음표 주파수에서 시작 End to note - + 음표 주파수에서 마침 Start distortion @@ -3648,7 +7920,7 @@ Noise: - + 잡음: Frequency slope: @@ -3656,7 +7928,7 @@ Envelope length: - + 엔벨로프 길이: Envelope slope: @@ -3664,11 +7936,11 @@ Start distortion: - + 디스토션 시작 값: End distortion: - + 디스토션 끝 값: @@ -3792,7 +8064,7 @@ VCF Envelope Decay - VCF 엔벨로프 감쇄 + VCF 엔벨로프 감쇠 Distortion @@ -3839,7 +8111,7 @@ Decay: - 감쇄: + 감쇠: 303-es-que, 24dB/octave, 3 pole filter @@ -3847,7 +8119,7 @@ Slide Decay: - 슬라이드 감쇄: + 슬라이드 감쇠: DIST: @@ -3887,11 +8159,11 @@ Moog wave - 무그 파형 + Moog 톱니파 Click here for a moog-like wave. - 클릭하여 무그 파형을 선택합니다. + 클릭하여 Moog 톱니파를 선택합니다. Sine wave @@ -3915,35 +8187,35 @@ Bandlimited saw wave - + 대역 제한 톱니파 Click here for bandlimited saw wave. - + 클릭하여 대역 제한 톱니파를 선택합니다. Bandlimited square wave - + 대역 제한 사각파 Click here for bandlimited square wave. - + 클릭하여 대역 제한 사각파를 선택합니다. Bandlimited triangle wave - + 대역 제한 삼각파 Click here for bandlimited triangle wave. - + 클릭하여 대역 제한 삼각파를 선택합니다. Bandlimited moog saw wave - + 대역 제한 Moog 톱니파 Click here for bandlimited moog saw wave. - + 클릭하여 대역 제한 Moog 톱니파를 선택합니다. @@ -3958,7 +8230,7 @@ Modulator - 모듈레이트 + 모듈레이터 Crossfade @@ -4014,7 +8286,7 @@ Glass - + 유리 Vibrato gain @@ -4030,7 +8302,7 @@ LFO speed - + LFO 속도 LFO depth @@ -4079,6 +8351,14 @@ Spread: + + Missing files + 없는 파일 + + + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! + Stk 설치가 불완전한 것 같습니다. 완전한 Stk 패키지가 설치되었는지 확인하시기 바랍니다! + Hardness @@ -4101,7 +8381,7 @@ Modulator: - + 모듈레이터: Crossfade @@ -4109,7 +8389,7 @@ Crossfade: - + 크로스페이드: ADSR @@ -4117,7 +8397,7 @@ ADSR: - + ADSR: Pressure @@ -4125,7 +8405,7 @@ Pressure: - + 압력: Speed @@ -4133,15 +8413,7 @@ Speed: - - - - Missing files - 없는 파일 - - - Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! - Stk 설치가 불완전한 것 같습니다. 완전한 Stk 패키지가 설치되었는지 확인하시기 바랍니다! + 속도: Vibrato gain @@ -4169,11 +8441,11 @@ LFO speed - + LFO 속도 LFO speed: - LFO 속도: + LFO 속도: LFO depth @@ -4196,11 +8468,11 @@ Close - 닫기 + 닫기 VST sync - + VST와 동기화 @@ -4211,7 +8483,7 @@ VST Sync - + VST와 동기화 Automated @@ -4219,7 +8491,7 @@ Close - 닫기 + 닫기 @@ -4230,7 +8502,7 @@ Volume - 볼륨 + 음량 @@ -4241,11 +8513,11 @@ Volume: - 볼륨: + 음량: Randomise - + 무작위 생성 Osc %1 waveform: @@ -4253,23 +8525,23 @@ Osc %1 volume: - 오실레이터 %1 볼륨: + 오실레이터 %1 음량: Osc %1 panning: + 오실레이터 %1 패닝: + + + Osc %1 stereo detuning cents 센트 - - Osc %1 stereo detuning - - Osc %1 harmonic: - + 오실레이터 %1 배음: @@ -4310,181 +8582,185 @@ pluginBrowser - Incomplete monophonic imitation tb303 - + no description + 설명 없음 - Plugin for freely manipulating stereo output + A native amplifier plugin + 내장 증폭기 플러그인 + + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - Plugin for controlling knobs with sound peaks + Boost your bass the fast and simple way - Plugin for enhancing stereo separation of a stereo input file + Customizable wavetable synthesizer - List installed LADSPA plugins - 설치된 LADSPA 플러그인 목록 + An oversampling bitcrusher + - GUS-compatible patch instrument + Carla Patchbay Instrument - Additive Synthesizer for organ-like sounds + Carla Rack Instrument - Tuneful things to bang on + A 4-band Crossover Equalizer - VST-host for using VST(i)-plugins within LMMS - LMMS의 VST(i) 플러그인 호스트 + A native delay plugin + 내장 딜레이 플러그인 - Vibrating string modeler + A Dual filter plugin - plugin for using arbitrary LADSPA-effects inside LMMS. - LMMS에서 LADSPA 이펙트를 이용하기 위한 플러그인. + plugin for processing dynamics in a flexible way + - Filter for importing MIDI-files into LMMS - 미디 파일을 LMMS로 읽어오기 위한 필터 + A native eq plugin + 내장 EQ 플러그인 - Emulation of the MOS6581 and MOS8580 SID. -This chip was used in the Commodore 64 computer. - + A native flanger plugin + 내장 플랜저 플러그인 - Player for SoundFont files - 사운드폰트 파일 플레이어 + Player for GIG files + GIG 파일 플레이어 - Emulation of GameBoy (TM) APU - + Filter for importing Hydrogen files into LMMS + Hydrogen 파일을 LMMS로 읽어오기 위한 필터 - Customizable wavetable synthesizer + Versatile drum synthesizer - Embedded ZynAddSubFX - + List installed LADSPA plugins + 설치된 LADSPA 플러그인 목록 - 2-operator FM Synth - + plugin for using arbitrary LADSPA-effects inside LMMS. + LMMS에서 LADSPA 이펙트를 이용하기 위한 플러그인. - Filter for importing Hydrogen files into LMMS + Incomplete monophonic imitation tb303 - LMMS port of sfxr - + Filter for exporting MIDI-files from LMMS + MIDI 파일을 LMMS에서 내보내기 위한 필터 + + + Filter for importing MIDI-files into LMMS + MIDI 파일을 LMMS로 읽어오기 위한 필터 Monstrous 3-oscillator synth with modulation matrix - Three powerful oscillators you can modulate in several ways + A multitap echo delay plugin - A native amplifier plugin + A NES-like synthesizer - Carla Rack Instrument + 2-operator FM Synth - 4-oscillator modulatable wavetable synth + Additive Synthesizer for organ-like sounds - plugin for waveshaping - + Emulation of GameBoy (TM) APU + GameBoy (TM) APU 에뮬레이션 - Boost your bass the fast and simple way + GUS-compatible patch instrument - Versatile drum synthesizer + Plugin for controlling knobs with sound peaks - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - + Reverb algorithm by Sean Costello + Sean Costello의 리버브 알고리즘 - plugin for processing dynamics in a flexible way - + Player for SoundFont files + 사운드폰트 파일 플레이어 - Carla Patchbay Instrument + LMMS port of sfxr - plugin for using arbitrary VST effects inside LMMS. + Emulation of the MOS6581 and MOS8580 SID. +This chip was used in the Commodore 64 computer. Graphical spectrum analyzer plugin - + 그래픽 스펙트럼 분석 플러그인 - A NES-like synthesizer + Plugin for enhancing stereo separation of a stereo input file - A native delay plugin + Plugin for freely manipulating stereo output - Player for GIG files + Tuneful things to bang on - A multitap echo delay plugin + Three powerful oscillators you can modulate in several ways - A native flanger plugin - + VST-host for using VST(i)-plugins within LMMS + LMMS의 VST(i) 플러그인 호스트 - An oversampling bitcrusher + Vibrating string modeler - A native eq plugin - 내장 EQ 플러그인 - - - A 4-band Crossover Equalizer - + plugin for using arbitrary VST effects inside LMMS. + LMMS에서 VST 이펙트를 이용하기 위한 플러그인. - A Dual filter plugin + 4-oscillator modulatable wavetable synth - Filter for exporting MIDI-files from LMMS + plugin for waveshaping - Reverb algorithm by Sean Costello - + Embedded ZynAddSubFX + 내장 ZynAddSubFX 플러그인 Mathematical expression parser @@ -4519,15 +8795,15 @@ This chip was used in the Commodore 64 computer. Reverb room size - + 리버브 공간 크기 Reverb damping - + 리버브 감쇠 Reverb width - + 리버브 너비 Reverb level @@ -4547,7 +8823,7 @@ This chip was used in the Commodore 64 computer. Chorus depth - + 코러스 깊이 @@ -4594,7 +8870,7 @@ This chip was used in the Commodore 64 computer. Speed: - + 속도: Depth: @@ -4609,7 +8885,7 @@ This chip was used in the Commodore 64 computer. sfxrInstrument Wave - + 파형 @@ -4628,7 +8904,7 @@ This chip was used in the Commodore 64 computer. Volume - 볼륨 + 음량 Chip model @@ -4636,14 +8912,14 @@ This chip was used in the Commodore 64 computer. Cutoff frequency - 차단 주파수 + 차단 주파수 sidInstrumentView Volume: - 볼륨: + 음량: Resonance: @@ -4655,11 +8931,11 @@ This chip was used in the Commodore 64 computer. MOS6581 SID - + MOS6581 SID MOS8580 SID - + MOS8580 SID Attack: @@ -4667,7 +8943,7 @@ This chip was used in the Commodore 64 computer. Decay: - 감쇄: + 감쇠: Sustain: @@ -4679,7 +8955,7 @@ This chip was used in the Commodore 64 computer. Pulse Width: - + 펄스 폭: Coarse: @@ -4719,15 +8995,15 @@ This chip was used in the Commodore 64 computer. Pulse wave - + 펄스파 Triangle wave - 삼각파 + 삼각파 Saw wave - 톱니파 + 톱니파 Ring modulation @@ -4735,7 +9011,7 @@ This chip was used in the Commodore 64 computer. Pulse width: - + 펄스 폭: @@ -4746,7 +9022,7 @@ This chip was used in the Commodore 64 computer. WIDTH - + 너비 @@ -4760,19 +9036,19 @@ This chip was used in the Commodore 64 computer. stereoMatrixControlDialog Left to Left Vol: - 왼쪽에서 왼쪽 볼륨: + 왼쪽에서 왼쪽 음량: Left to Right Vol: - 왼쪽에서 오른쪽 볼륨: + 왼쪽에서 오른쪽 음량: Right to Left Vol: - 오른쪽에서 왼쪽 볼륨: + 오른쪽에서 왼쪽 음량: Right to Right Vol: - 오른쪽에서 오른쪽 볼륨: + 오른쪽에서 오른쪽 음량: @@ -4794,6 +9070,19 @@ This chip was used in the Commodore 64 computer. 오른쪽에서 오른쪽 + + testcontext + + test string + + + + test plural %n + + + + + vestigeInstrument @@ -4802,14 +9091,14 @@ This chip was used in the Commodore 64 computer. Please wait while loading the VST plugin... - + VST 플러그인을 읽을 동안 잠시 기다려 주세요... vibed String %1 volume - %1번 스트링 볼륨 + %1번 현 음량 String %1 stiffness @@ -4821,7 +9110,7 @@ This chip was used in the Commodore 64 computer. Pickup %1 position - + 픽업 %1 위치 Impulse %1 @@ -4829,7 +9118,7 @@ This chip was used in the Commodore 64 computer. String %1 panning - + String %1 패닝 String %1 detune @@ -4841,11 +9130,11 @@ This chip was used in the Commodore 64 computer. String %1 length - + %1번 현 길이 String %1 - + %1번 현 @@ -4860,7 +9149,7 @@ This chip was used in the Commodore 64 computer. Pickup position: - + 픽업 위치: Octave @@ -4924,15 +9213,15 @@ This chip was used in the Commodore 64 computer. White noise - 화이트 노이즈 + 화이트 노이즈 User-defined wave - + 사용자 지정 파형 Smooth waveform - 파형을 부드럽게 + 파형을 부드럽게 Normalize waveform @@ -4943,7 +9232,7 @@ This chip was used in the Commodore 64 computer. voiceObject Voice %1 pulse width - + 소리 %1 펄스 폭 Voice %1 attack @@ -5006,15 +9295,15 @@ This chip was used in the Commodore 64 computer. Clip input - + 입력 신호 클리핑 Reset wavegraph - + 그래프 초기화 Smooth wavegraph - + 그래프를 부드럽게 Increase wavegraph amplitude by 1 dB diff --git a/data/locale/pl.ts b/data/locale/pl.ts index 5d9cc51cd40..4214718af38 100644 --- a/data/locale/pl.ts +++ b/data/locale/pl.ts @@ -3108,7 +3108,7 @@ Możesz usunąć i przenieść kanały FX w menu kontekstowym, które jest dost VELOCITY - GŁOŚNOŚĆ UDERZENIA + PRĘDKOŚĆ ENABLE MIDI OUTPUT @@ -10321,4 +10321,4 @@ Kontrolka LED w prawym dolnym rogu edytora kształtu fali pokazuje, czy wybrana Wzmocnienie wyścia - \ No newline at end of file + diff --git a/data/locale/ru.ts b/data/locale/ru.ts index f4c1e6a0116..f717d598df4 100644 --- a/data/locale/ru.ts +++ b/data/locale/ru.ts @@ -1,37 +1,117 @@ - - - + + + AboutDialog + + + About LMMS + О программе LMMS + + + + LMMS + ЛММС + + + + Version %1 (%2/%3, Qt %4, %5) + Версия %1 (%2/%3, Qt %4, %5) + + + + About + Подробнее + + + + LMMS - easy music production for everyone + LMMS - лёгкое создание музыки для всех + + + + Copyright © %1 + Все права защищены © %1 + + + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + + + + Authors + Авторы + + + + Involved + Участники + + + + Contributors ordered by number of commits: + Разработчики сортированные по числу коммитов: + + + + Translation + Перевод + + + + Current language not translated (or native English). + +If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! + Если Вы заинтересованы в переводе LMMS на другой язык или хотите улучшить существующий перевод, мы приветствуем любую помощь! Просто свяжитесь с разработчиками! + +Перевод выполнили: +Alexey Kouznetsov <alexey/dot/kouznetsov/at/gmail/dot/com> +Oe Ai <oeai/at/symbiants/dot/com> + + + + License + Лицензия + + AmplifierControlDialog + VOL ГРОМ + Volume: Громкость: + PAN БАЛ + Panning: Баланс: + LEFT Лево + Left gain: Лево мощность: + RIGHT Право + Right gain: Право мощность: @@ -39,4270 +119,11763 @@ AmplifierControls + Volume Громкость + Panning Баланс + Left gain Лево мощн + Right gain Право мощн + + AudioAlsaSetupWidget + + + DEVICE + УСТРОЙСТВО + + + + CHANNELS + КАНАЛЫ + + AudioFileProcessorView - Reverse sample - Отзеркалить запись + + Open other sample + Открыть другую запись - Amplify: - Усиление: + + Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. + Нажмите здесь, чтобы открыть другой звуковой файл. В новом окне диалога вы сможете выбрать нужный файл. Такие настройки, как режим повтора, точки начала/конца, усиление и прочие не сбросятся, поэтому звучание может отличаться от оригинала. - Continue sample playback across notes - Продолжить воспроизведение записи по нотам + + Reverse sample + Отзеркалить запись + + + + If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. + Если включить эту кнопку, вся запись пойдёт в обратную сторону, это удобно для крутых эффектов, типа обратного грохота. + Disable loop Отключить петлю + + This button disables looping. The sample plays only once from start to end. + Эта кнопка отключает зацикливание (loop-цикл). Запись проигрывается только один раз от начала до конца. + + + + Enable loop Включить петлю - Loopback point: - Точка возврата петли: + + This button enables forwards-looping. The sample loops between the end point and the loop point. + Эта кнопка включает переднюю петлю. Сэмпл кольцуется между конечной точкой и точкой петли. - Open sample - + + This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. + Эта кнопка включает пинг-понг петлю. Сэмпл кольцуется обратно и вперёд между конечной точкой и точкой петли. - Enable ping-pong loop - + + Continue sample playback across notes + Продолжить воспроизведение записи по нотам - Start point: - + + Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) + Включение этой опции продолжит воспроизведение записи по разным нотам - если изменить ускорение или длительность ноты остановится до конца записи, то со следующей ноты запись продолжится там, где остановилась, чтобы сбросить воспроизвдение на начало записи, вставьте ноту внизу у клавиш (<20 Гц) - End point: - + + Amplify: + Усиление: - - - AudioFileProcessorWaveView - Sample length: - Длина записи: + + With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + Эта ручка задаёт коэффициент усиления. При значении 100% исходный звук не меняется, в противном случае ― он будет ослаблен или усилен. (Обратите внимание, что исходная запись при этом останется нетронутой.) - - - BassBoosterControlDialog - FREQ - ЧАСТ + + Startpoint: + Начало: - Frequency: - Частота: + + With this knob you can set the point where AudioFileProcessor should begin playing your sample. + Этим регулятором можно установить точку где АудиоФайлПроцессор должен начать воспроизведение сэмпла. - GAIN - МОЩ + + Endpoint: + Конец: - Gain: - Мощность: + + With this knob you can set the point where AudioFileProcessor should stop playing your sample. + Этот регулятор устанавливает точку в которой АудиоФайлПроцессор должен перестать воспроизвдение сэмпла. - RATIO - ОТН + + Loopback point: + Точка возврата петли: - Ratio: - Отношение: + + With this knob you can set the point where the loop starts. + Этот регулятор ставит точку начала петли. - BassBoosterControls - - Frequency - Частота - - - Gain - Мощность - + AudioFileProcessorWaveView - Ratio - Отношение + + Sample length: + Длина записи: - BitcrushControlDialog + AudioJack - IN - IN + + JACK client restarted + JACK-клиент перезапущен - OUT - OUT + + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. + LMMS не был подключен к JACK по какой-то причине, поэтому LMMS подключение к JACK было перезапущено. Вам придётся заново вручную создать соединения. - GAIN - МОЩ + + JACK server down + JACK-сервер не доступен - CLIP - СРЕЗ + + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. + Возможно JACK-сервер был выключен и запуск нового процесса не удался, поэтому ЛММС не может продолжить работу. Вам следует сохранить проект и перезапустить JACK и LMMS. - Sample rate: - Частота сэмплирования: + + CLIENT-NAME + ИМЯ КЛИЕНТА - Stereo difference: - Стерео разница: + + CHANNELS + КАНАЛЫ + + + AudioOss::setupWidget - Levels: - Уровни: + + DEVICE + УСТРОЙСТВО - NOISE - Шум + + CHANNELS + КАНАЛЫ + + + AudioPortAudio::setupWidget - FREQ - FREQ + + BACKEND + УПРАВЛЕНИЕ - STEREO - СТЕРЕО + + DEVICE + УСТРОЙСТВО + + + AudioPulseAudio::setupWidget - QUANT - + + DEVICE + УСТРОЙСТВО - Input gain: - Входная мощность: + + CHANNELS + КАНАЛЫ + + + AudioSdl::setupWidget - Input noise: - + + DEVICE + УСТРОЙСТВО + + + AudioSndio::setupWidget - Output gain: - Выходная мощность: + + DEVICE + УСТРОЙСТВО - Output clip: - + + CHANNELS + КАНАЛЫ + + + AudioSoundIo::setupWidget - Rate enabled - + + BACKEND + БЭКЕНД - Enable sample-rate crushing - + + DEVICE + УСТРОЙСТВО + + + AutomatableModel - Depth enabled - + + &Reset (%1%2) + &R Сбросить (%1%2) - Enable bit-depth crushing - + + &Copy value (%1%2) + &C Копировать значение (%1%2) - - - BitcrushControls - Input gain - Входная мощность + + &Paste value (%1%2) + &P Вставить значение (%1%2) - Input noise - + + Edit song-global automation + Изменить глоабльную автоматизацию композиции - Output gain - Выходная мощность + + Remove song-global automation + Убрать глобальную автоматизацию композиции - Output clip - + + Remove all linked controls + Убрать всё присоединенное управление - Sample rate - + + Connected to %1 + Подсоединено к %1 - Stereo difference - + + Connected to controller + Подсоединено к контроллеру - Levels - + + Edit connection... + Настроить соединение... - Rate enabled - + + Remove connection + Удалить соединение - Depth enabled - + + Connect to controller... + Соединить с контроллером... - CarlaInstrumentView + AutomationEditor - Show GUI - Показать интерфейс + + Please open an automation pattern with the context menu of a control! + Откройте редатор автоматизации через контекстное меню регулятора! + + + + Values copied + Значения скопированы + + + + All selected values were copied to the clipboard. + Все выбранные значения скопированы в буфер обмена. - CrossoverEQControlDialog + AutomationEditorWindow - Band 1/2 crossover: - + + Play/pause current pattern (Space) + Игра/Пауза текущей мелодии (Пробел) - Band 2/3 crossover: - + + Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. + Нажмите здесь чтобы проиграть текущую мелодию. Это может пригодиться при его редактировании. Мелодия автоматически закольцуется при достижении конца. - Band 3/4 crossover: - + + Stop playing of current pattern (Space) + Остановить воспроизведение текущей мелодии (Пробел) - Band 1 gain - + + Click here if you want to stop playing of the current pattern. + Нажмите здесь, если вы хотите остановить воспроизведение текущей мелодии. - Band 1 gain: - + + Edit actions + Правка: - Band 2 gain - + + Draw mode (Shift+D) + Режим рисования (Shift+D) - Band 2 gain: - + + Erase mode (Shift+E) + Режим стирания (Shift-E) - Band 3 gain - + + Flip vertically + Перевернуть вертикально - Band 3 gain: - + + Flip horizontally + Перевернуть горизонтально - Band 4 gain - + + Click here and the pattern will be inverted.The points are flipped in the y direction. + Нажмите здесь и мелодия перевернётся. Точки переворачиваются в Y направлении. - Band 4 gain: - + + Click here and the pattern will be reversed. The points are flipped in the x direction. + Нажмите здесь и мелодия перевернётся в направлении X. - Band 1 mute - + + Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. + При нажатии на эту кнопку активируется режим рисования нот, в нём вы можете добавлять/перемещать и изменять длительность одиночных нот. Это основной режим и используется большую часть времени. +Для включения этого режима можно использовать комбинацию клавиш Shift+D. - Mute band 1 - + + Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. + При нажатии на эту кнопку активируется режим стирания. В этом режиме вы можете стирать ноты по одной. +Для включения этого режима можно использовать комбинацию клавиш Shift+E. - Band 2 mute - + + Interpolation controls + Управление интерполяцией - Mute band 2 - + + Discrete progression + Дискретная прогрессия - Band 3 mute - + + Linear progression + Линейная прогрессия - Mute band 3 - + + Cubic Hermite progression + Кубическая Эрмитова прогрессия - Band 4 mute - + + Tension value for spline + Величина напряжения для сплайна - Mute band 4 - + + A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. + Более высокое напряжение может сделать кривую более мягкой, но перегрузит некоторые величины. Низкое напряжение сделает наклон кривой ниже в каждой контрольной точке. - - - DelayControls - Feedback - Возврат + + Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. + Выбор дискретной прогрессии для этого шаблона автоматизации. Кол-во подсоединенных объектов будет оставаться постоянным между управляющими точками и будет установлено на новое значение сразу по достижении каждой управляющей точки. - Output gain - Выходная мощность + + Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. + Выбор линейной прогрессии для этого шаблона автоматизации. Кол-во подсоединенных объектов будет меняться с постоянной скоростью во времени между управляющими точками для достижения точного значения в каждой управляющей точки без внезапных изменений. - Delay samples - + + Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. + Кубическая Эрмитова прогрессия для этого шаблона автоматизации. Кол-во подсоединенных объектов изменится по сглаженной кривой и смягчится на пиках и спадах. - LFO frequency - + + Tension: + Напряжение: - LFO amount - + + Cut selected values (%1+X) + Вырезать выбранные ноты (%1+X) - - - DelayControlsDialog - Gain - Усиление + + Copy selected values (%1+C) + Копировать выбранные ноты в буфер (%1+C) - DELAY - ЗАДЕРЖ + + Paste values from clipboard (%1+V) + Вставить запомненные значения (%1+V) - FDBK - + + Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При нажатии на эту кнопку выделеные ноты будут вырезаны в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". - RATE - ЧАСТ + + Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При нажатии на эту кнопку выделеные ноты будут скопированы в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". - AMNT - ГЛУБ + + Click here and the values from the clipboard will be pasted at the first visible measure. + При нажатии на эту кнопку ноты из буфера будут вставлены в первый видимый такт. + + + + Zoom controls + Приблизить управление + + + + Quantization controls + Управление квантованием - Delay time - + + Quantization + Квантование - Feedback amount - + + Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. + - LFO frequency - + + + Automation Editor - no pattern + Редактор автоматизаци — нет шаблона - LFO amount - + + + Automation Editor - %1 + Редактор автоматизации — %1 - Out gain - + + Model is already connected to this pattern. + Модель уже подключена к этому шаблону. - DualFilterControlDialog + AutomationPattern - Filter 1 enabled - Фильтр 1 включен + + Drag a control while pressing <%1> + Тяните контроль удерживая <%1> + + + AutomationPatternView - Filter 2 enabled - Фильтр 2 включен + + double-click to open this pattern in automation editor + Дважды щёлкните мышью чтобы настроить автоматизацию этого шаблона - FREQ - FREQ + + Open in Automation editor + Открыть в редакторе автоматизации - Cutoff frequency - Срез частот + + Clear + Очистить - RESO - RESO + + Reset name + Сбросить название - Resonance - Резонанс + + Change name + Переименовать - GAIN - МОЩ + + Set/clear record + Установить/очистить запись - Gain - УСИЛ + + Flip Vertically (Visible) + Перевернуть вертикально (Видимое) - MIX - + + Flip Horizontally (Visible) + Перевернуть горизонтально (Видимое) - Mix - + + %1 Connections + Соединения %1 - Enable/disable filter 1 - + + Disconnect "%1" + Отсоединить «%1» - Enable/disable filter 2 - + + Model is already connected to this pattern. + Модель уже подключена к этому шаблону. - DualFilterControls + AutomationTrack - Filter 1 enabled - Фильтр 1 включен + + Automation track + Дорожка автоматизации + + + BBEditor - Filter 1 type - + + Beat+Bassline Editor + Ритм+Бас Редактор - Q/Resonance 1 - + + Play/pause current beat/bassline (Space) + Игра/пауза текущей линии ритма/баса (<Space>) - Gain 1 - + + Stop playback of current beat/bassline (Space) + Остановить воспроизведение текущей линии ритм-баса (ПРОБЕЛ) - Mix - + + Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. + Нажмите чтобы проиграть текущую линию ритм-баса. Она будет закольцована по достижении окончания. - Filter 2 enabled - Фильтр 2 включен + + Click here to stop playing of current beat/bassline. + Остановить воспроизведение (Пробел). - Filter 2 type - + + Beat selector + Выбор бита - Q/Resonance 2 - + + Track and step actions + Действия для дорожки или ее части - Gain 2 - + + Add beat/bassline + Добавить ритм/бас - Notch - Полосно-заграждающий + + Add sample-track + Добавить дорожку записи - Moog - Муг + + Add automation-track + Добавить дорожку автоматизации - 2x Moog - 2x Муг + + Remove steps + Убрать такты - SV Notch - + + Add steps + Добавить такты - Fast Formant - + + Clone Steps + Клонировать такты + + + BBTCOView - Tripole - + + Open in Beat+Bassline-Editor + Открыть в редакторе ритм + баса - Cutoff frequency 1 - + + Reset name + Сбросить название - Cutoff frequency 2 - + + Change name + Переименовать - Low-pass - + + Change color + Изменить цвет - Hi-pass - + + Reset color to default + Установить цвет по умолчанию + + + BBTrack - Band-pass csg - + + Beat/Bassline %1 + Ритм-Бас Линия %1 - Band-pass czpg - + + Clone of %1 + Копия %1 + + + BassBoosterControlDialog - All-pass - + + FREQ + ЧАСТ - 2x Low-pass - + + Frequency: + Частота: - RC Low-pass 12 dB/oct - + + GAIN + МОЩ - RC Band-pass 12 dB/oct - + + Gain: + Мощность: - RC High-pass 12 dB/oct - + + RATIO + ОТН - RC Low-pass 24 dB/oct - + + Ratio: + Отношение: + + + BassBoosterControls - RC Band-pass 24 dB/oct - + + Frequency + Частота - RC High-pass 24 dB/oct - + + Gain + Мощность - Vocal Formant - + + Ratio + Отношение + + + BitcrushControlDialog - SV Low-pass - + + IN + ВХОД - SV Band-pass - + + OUT + ВЫХОД - SV High-pass - + + + GAIN + МОЩ - - - EqControls - Input gain - Входная мощность + + Input Gain: + Входная мощность: - Output gain - Выходная мощность + + NOISE + Шум - Peak 1 gain - + + Input Noise: + Входной шум: - Peak 2 gain - + + Output Gain: + Выходная мощность: - Peak 3 gain - + + CLIP + СРЕЗ - Peak 4 gain - + + Output Clip: + Выходная обрезка: - HP res - - - - Peak 1 BW - + + Rate Enabled + Частота выборки включена - Peak 2 BW - + + Enable samplerate-crushing + Включить дробление частоты дискретизации - Peak 3 BW - + + Depth Enabled + Глубина включена - Peak 4 BW - + + Enable bitdepth-crushing + Включить дробление битовой глубины - LP res - + + FREQ + FREQ - HP freq - + + Sample rate: + Частота сэмплирования: - Peak 1 freq - + + STEREO + СТЕРЕО - Peak 2 freq - + + Stereo difference: + Стерео разница: - Peak 3 freq - + + QUANT + КВАНТ - Peak 4 freq - + + Levels: + Уровни: + + + CaptionMenu - LP freq - + + &Help + &H Справка - HP active - + + Help (not available) + Справка (не доступна) + + + CarlaInstrumentView - Peak 1 active - + + Show GUI + Показать интерфейс - Peak 2 active - + + Click here to show or hide the graphical user interface (GUI) of Carla. + Нажмите сюда, чтобы показать или скрыть графический интерфейс Карла. + + + Controller - Peak 3 active - + + Controller %1 + Контроллер %1 + + + ControllerConnectionDialog - Peak 4 active - + + Connection Settings + Параметры соединения - LP active - + + MIDI CONTROLLER + MIDI-КОНТРОЛЛЕР - LP 12 - + + Input channel + Канал ввода - LP 24 - + + CHANNEL + КАНАЛ - LP 48 - + + Input controller + Контроллер ввода - HP 12 - + + CONTROLLER + КОНТРОЛЛЕР - HP 24 - + + + Auto Detect + Автоопределение - HP 48 - + + MIDI-devices to receive MIDI-events from + Устройства MiDi для приёма событий - Analyse IN - + + USER CONTROLLER + ПОЛЬЗ. КОНТРОЛЛЕР - Analyse OUT - + + MAPPING FUNCTION + ПЕРЕОПРЕДЕЛЕНИЕ - Low-shelf gain - + + OK + ОК - High-shelf gain - + + Cancel + Отменить - Low-shelf res - + + LMMS + LMMS - High-shelf res - + + Cycle Detected. + Обнаружен цикл. + + + ControllerRackView - Low-shelf freq - + + Controller Rack + Рэка контроллеров - High-shelf freq - + + Add + Добавить - Low-shelf active - + + Confirm Delete + Подтвердить удаление - High-shelf active - + + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. + Подтверждаете удаление? Есть возможные соединения с этим контроллером, возврата не будет. + + + ControllerView - Low-pass type - + + Controls + Управление - High-pass type - + + Controllers are able to automate the value of a knob, slider, and other controls. + Контроллеры могут автоматизировать изменения значений регуляторов, ползунков и прочего управления. - - - EqControlsDialog - HP - + + Rename controller + Переименовать контроллер - Peak 1 - + + Enter the new name for this controller + Введите новое название для контроллера - Peak 2 - + + LFO + LFO - Peak 3 - + + &Remove this controller + Убрать этот контроллер - Peak 4 - + + Re&name this controller + Переименовать этот контроллер + + + CrossoverEQControlDialog - LP - + + Band 1/2 Crossover: + Полоса 1/2 кроссовер: - Gain - Мощность + + Band 2/3 Crossover: + Полоса 2/3 кроссовер: - Bandwidth: - + + Band 3/4 Crossover: + Полоса 3/4 кроссовер: - Resonance : - Резонанс: + + Band 1 Gain: + Полоса 1 усиление: - Frequency: - Частота: + + Band 2 Gain: + Полоса 2 усиление: - Octave - Октава + + Band 3 Gain: + Полоса 3 усиление: - Low-shelf - + + Band 4 Gain: + Полоса 4 усиление: - High-shelf - + + Band 1 Mute + Полоса 1 выключена - Input gain - Входная мощность + + Mute Band 1 + Заглушить полосу 1 - Output gain - Выходная мощность + + Band 2 Mute + Полоса 2 выключена - LP group - + + Mute Band 2 + Заглушить полосу 2 - HP group - + + Band 3 Mute + Полоса 3 заглушена - - - EqHandle - Reso: - + + Mute Band 3 + Заглушить полосу 3 - BW: - + + Band 4 Mute + Полоса 4 заглушена - Freq: - + + Mute Band 4 + Заглушить полосу 4 - FlangerControls - - Seconds - Секунды - + DelayControls - Regen - + + Delay Samples + Задержка сэмплов - Noise - Шум + + Feedback + Возврат - Invert - + + Lfo Frequency + Частота LFO - Delay samples - + + Lfo Amount + Объём LFO - LFO frequency - + + Output gain + Выходная мощность - FlangerControlsDialog + DelayControlsDialog + DELAY - Задержка + ЗАДЕРЖ + + + + Delay Time + Время задержки + + + + FDBK + + + + + Feedback Amount + Объём возврата: + RATE ЧАСТ + + Lfo + Lfo + + + AMNT ГЛУБ - Amount: - + + Lfo Amt + Вел LFO - FDBK - + + Out Gain + Выходная мощность - NOISE - Шум + + Gain + Усиление + + + DualFilterControlDialog - Invert - + + + FREQ + FREQ - Period: - + + + Cutoff frequency + Срез частот - Delay time: - + + + RESO + RESO - Feedback amount: - + + + Resonance + Резонанс - White noise amount: - + + + GAIN + МОЩ - - - FreeBoyInstrument - Sweep time - Время распространения + + + Gain + УСИЛ - Sweep direction - Направление распространения + + MIX + МИКС - Channel 1 volume - Громкость первого канала + + Mix + Микс - Volume sweep direction - Объём направления распространения + + Filter 1 enabled + Фильтр 1 включен - Length of each step in sweep - Длина каждого такта в распространении + + Filter 2 enabled + Фильтр 2 включен - Channel 2 volume - Громкость второго канала + + Click to enable/disable Filter 1 + Кликнуть для включения/выключения Фильтра 1 - Channel 3 volume - Громкость третьего канала + + Click to enable/disable Filter 2 + Кликнуть для включения/выключения Фильтра 2 + + + DualFilterControls - Channel 4 volume - Громкость четвёртого канала + + Filter 1 enabled + Фильтр 1 включен - Channel 1 to SO2 (Left) - От первого канала к SO2 (левый канал) + + Filter 1 type + Фильтр 1 тип - Channel 2 to SO2 (Left) - От второго канала к SO2 (левый канал) + + Cutoff 1 frequency + Срез 1 частоты - Channel 3 to SO2 (Left) - От третьего канала к SO2 (левый канал) + + Q/Resonance 1 + - Channel 4 to SO2 (Left) - От четвёртого канала к SO2 (левый канал) + + Gain 1 + Усиление 1 - Channel 1 to SO1 (Right) - От первого канала к SO1 (правый канал) + + Mix + Микс - Channel 2 to SO1 (Right) - От второго канала к SO1 (правый канал) + + Filter 2 enabled + Фильтр 2 включен - Channel 3 to SO1 (Right) - От третьего канала к SO1 (правый канал) + + Filter 2 type + Фильтр 2 тип - Channel 4 to SO1 (Right) - От четвёртого канала к SO1 (правый канал) + + Cutoff 2 frequency + Срез 2 частоты - Treble - Верхние + + Q/Resonance 2 + - Bass - Нижние + + Gain 2 + Усиление 2 - Shift Register width - Сдвиг ширины регистра + + + LowPass + Низ.ЧФ - Sweep rate shift amount - + + + HiPass + Выс.ЧФ - Wave pattern duty cycle - + + + BandPass csg + Сред.ЧФ csg - Right output level - + + + BandPass czpg + Сред.ЧФ czpg - Left output level - + + + Notch + Полосно-заграждающий - - - FreeBoyInstrumentView - Length of each step in sweep: - Длина каждого такта в развёртке: + + + Allpass + Все проходят - Length of each step in sweep - Длина каждого такта в распространении + + + Moog + Муг - Treble: - Верхние: + + + 2x LowPass + 2х Низ.ЧФ - Treble - Верхние + + + RC LowPass 12dB + RC Низ.ЧФ 12дБ - Bass: - Нижние: + + + RC BandPass 12dB + RC Сред.ЧФ 12 дБ - Bass - Нижние + + + RC HighPass 12dB + RC Выс.ЧФ 12дБ - Sweep time: - + + + RC LowPass 24dB + RC Низ.ЧФ 24дБ - Sweep time - Время распространения + + + RC BandPass 24dB + RC Сред.ЧФ 24дБ - Sweep rate shift amount: - + + + RC HighPass 24dB + RC Выс.ЧФ 24дБ - Sweep rate shift amount - + + + Vocal Formant Filter + Фильтр Вокальной форманты - Wave pattern duty cycle: - + + + 2x Moog + 2x Муг - Wave pattern duty cycle - + + + SV LowPass + SV Низ.ЧФ - Square channel 1 volume: - + + + SV BandPass + SV Сред.ЧФ - Square channel 1 volume - + + + SV HighPass + SV Выс.ЧФ - Square channel 2 volume: - + + + SV Notch + - Square channel 2 volume - + + + Fast Formant + - Wave pattern channel volume: - + + + Tripole + Триполи + + + Editor - Wave pattern channel volume - + + Transport controls + Управление транспортом - Noise channel volume: - + + Play (Space) + Игра (Пробел) - Noise channel volume - + + Stop (Space) + Стоп (Пробел) - SO1 volume (Right): - + + Record + Запись - SO1 volume (Right) - + + Record while playing + Запись при игре + + + Effect - SO2 volume (Left): - + + Effect enabled + Эффект включён - SO2 volume (Left) - + + Wet/Dry mix + Насыщенность - Sweep direction - Направление распространения + + Gate + Шлюз - Volume sweep direction - Объём направления распространения + + Decay + Затихание + + + EffectChain - Shift register width - + + Effects enabled + Эффекты включёны + + + EffectRackView - Channel 1 to SO1 (Right) - От первого канала к SO1 (правый канал) + + EFFECTS CHAIN + ЦЕПЬ ЭФФЕКТОВ - Channel 2 to SO1 (Right) - От второго канала к SO1 (правый канал) + + Add effect + Добавить эффект + + + EffectSelectDialog - Channel 3 to SO1 (Right) - От третьего канала к SO1 (правый канал) + + Add effect + Добавить эффект - Channel 4 to SO1 (Right) - От четвёртого канала к SO1 (правый канал) + + + Name + Имя - Channel 1 to SO2 (Left) - От первого канала к SO2 (левый канал) + + Type + Тип - Channel 2 to SO2 (Left) - От второго канала к SO2 (левый канал) + + Description + Описание - Channel 3 to SO2 (Left) - От третьего канала к SO2 (левый канал) + + Author + Автор + + + EffectView - Channel 4 to SO2 (Left) - От четвёртого канала к SO2 (левый канал) + + Toggles the effect on or off. + Вкл/выкл эффект. - Wave pattern graph - + + On/Off + Вкл/Выкл - - - GigInstrument - Bank - Банк + + W/D + - Patch - Патч + + Wet Level: + Уровень насыщенности: - Gain - Мощность + + The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. + Регулятор насыщенности определяет долю обработанного сигнала, которая будет на выходе. - - - GigInstrumentView - Open GIG file - Открыть GIG файл + + DECAY + - GIG Files (*.gig) - GIG Файлы (*.gig) + + Time: + Время: - Choose patch - + + The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. + Decay (затихание) управляет количеством буферов тишины, которые должны пройти до конца работы плагина. Меньшие величины снижают перегрузку процессора, но вознкает риск появления потрескивания или подрезания в хвосте на передержке (delay) или эхо (reverb) эффектах. - Gain: - + + GATE + ШЛЮЗ - - - InstrumentTrack - Default preset - Основная предустановка + + Gate: + Шлюз: - - - LadspaControlDialog - Link Channels - Связать каналы + + The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. + GATE (Шлюз) определяет уровень сигнала, который будет считаться "тишиной" при определении остановки обрабатывания сигналов. - Channel - Канал + + Controls + Управление - - - LadspaEffect - Unknown LADSPA plugin %1 requested. - Запрошен неизвестный модуль LADSPA «%1». + + Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. + +The On/Off switch allows you to bypass a given plugin at any point in time. + +The Wet/Dry knob controls the balance between the input signal and the effected signal that is the resulting output from the effect. The input for the stage is the output from the previous stage. So, the 'dry' signal for effects lower in the chain contains all of the previous effects. + +The Decay knob controls how long the signal will continue to be processed after the notes have been released. The effect will stop processing signals when the volume has dropped below a given threshold for a given length of time. This knob sets the 'given length of time'. Longer times will require more CPU, so this number should be set low for most effects. It needs to be bumped up for effects that produce lengthy periods of silence, e.g. delays. + +The Gate knob controls the 'given threshold' for the effect's auto shutdown. The clock for the 'given length of time' will begin as soon as the processed signal level drops below the level specified with this knob. + +The Controls button opens a dialog for editing the effect's parameters. + +Right clicking will bring up a context menu where you can change the order in which the effects are processed or delete an effect altogether. + Сигнал проходит последовательно через все установленные фильтры (сверху вниз). + +Переключатель Вкл/Выкл позволяет в любой момент включать/выключать фильтр. + +Регулятор (wet / dry) насыщенности определяет баланс между входящим сигналом и сигналом после эффекта, который становится выходным сигналом эффекта. Входной сигнал каждого фильтра является выходом предыдущего, так что доля чистого сигнала при прохождении по цепочке постоянно падает. + +Регулятор (decay) затихания определяет время, которое будет действовать фильтр после того как ноты были отпущены. +Эффект перестанет обрабатывать сигналы, когда грмокость упадёт ниже порога для заданной длины времени. Эта ручка (Knob) устанавливает "заданную длину времени" Чем меньше значение, тем меньше требования к ЦП, поэтому лучше ставить это число низким для большинства эффектов. однако это может вызвать обрезку звука при использовании эффектов с длительными периодами тишины, типа задержки. + +Регулятор шлюза служит для указания порога сигнала для авто-отключения эффекта, отсчёт для "заданной длины времени" начнётся как только обрабатываемый сигнал упадёт ниже указанного этим регулятором уровня. + +Кнопка „Управление“ открывает окно изменения параметров эффекта. + +Контекстное меню, вызываемое щелчком правой кнопкой мыши, позволяет менять порядок следования фильтров или удалять их вместе с другими. + + + + Move &up + &u Переместить выше + + + + Move &down + &d Переместить ниже + + + + &Remove this plugin + &R Убрать фильтр - MidiImport - - Setup incomplete - установка не завершена - - - You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. - Вы не включили поддержку проигрывателя SoundFont2 при компиляции ЛММС, он используется для добавления основного звука в импортируемые Миди файлы, поэтому звука не будет после импорта этого миди файла. - + EnvelopeAndLfoParameters - Track - + + Predelay + Задержка - You have not set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. - + + Attack + Вступление - - - MonstroInstrument - Osc 3 Stereo phase offset - + + Hold + Удерживание - Selected view - + + Decay + Затихание - Sine wave - Синусоида + + Sustain + Выдержка - Bandlimited Triangle wave - Ограниченная по частоте треугольная волна + + Release + Убывание - Bandlimited Saw wave - Ограниченная по частоте острая волна + + Modulation + Модуляция - Bandlimited Ramp wave - + + LFO Predelay + Задержка LFO - Bandlimited Square wave - Ограниченная по частоте квадратная волна + + LFO Attack + Вступление LFO - Bandlimited Moog saw wave - Ограниченная по частоте Муг острая волна + + LFO speed + Скорость LFO - Soft square wave - Сглаженная квадратная волна + + LFO Modulation + Модуляция LFO - Absolute sine wave - + + LFO Wave Shape + Форма сигнала LFO - Exponential wave - Экспоненциальная волна + + Freq x 100 + ЧАСТ x 100 - White noise - Белый шум + + Modulate Env-Amount + Модулировать огибающую + + + EnvelopeAndLfoView - Digital Triangle wave - Цифровая треугольная волна + + + DEL + DEL - Digital Saw wave - Цифровая острая волна + + Predelay: + Задержка: - Digital Ramp wave - + + Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. + Эта ручка определяет задержку огибающей. Чем больше эта величина, тем дольше время до старта текущей огибающей. - Digital Square wave - Цифровая квадратная волна + + + ATT + ATT - Digital Moog saw wave - Цифровая Муг острая волна + + Attack: + Вступление: - Triangle wave - Треугольная волна + + Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. + Эта ручка устанавливает время возрастания для текущей огибающей. Чем больше значение, тем дольше характеристика (н-р, громкость) возрастает до максимума. Для инструменов вроде пианино характерны малые времена нарастания, а для струнных - большие. - Saw wave - Зигзаг + + HOLD + HOLD - Ramp wave - + + Hold: + Удержание: - Square wave - Квадрат + + Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. + Эта ручка устанавливает длительность огибающей. Чем больше значение, тем дольше огибающая держится на наивысшем уровне. - Moog saw wave - + + DEC + DEC - Abs. sine wave - + + Decay: + Затухание: - Random - Случайно + + Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. + Эта ручка устанавливает время спада для текущей огибающей. Чем больше значение, тем дольше огибающая должна сокращаться от вступления до уровня выдержки. Для инструментов вроде пианино следует выбирать небольшие значения. - Random smooth - Случайное сглаживание + + SUST + SUST - Osc 1 volume - + + Sustain: + Выдержка: - Osc 1 panning - + + Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. + Эта ручка устанавливает уровень выдержки. Чем больше эта величина, тем выше уровень на котором остаётся огибающая, прежде чем опуститься до нуля. - Osc 1 coarse detune - + + REL + REL - Osc 1 fine detune left - + + Release: + Убывание: - Osc 1 fine detune right - + + Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. + Эта ручка устанавливает время убывания для текущей огибающей. Чем больше значение, тем дольше характеристика (н-р, громкость) уменьшается от уровня выдержки до нуля. Для струнных инструментов следует выбирать большие значения. - Osc 1 stereo phase offset - + + + AMT + AMT - Osc 1 pulse width - + + + Modulation amount: + Глубина модуляции: - Osc 1 sync send on rise - + + Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. + Эта ручка устанавливает глубину модуляции для текущей огибающей. Чем больше значение, тем в большей степени выбранная характеристика (н-р, громкость или частота среза) будет зависеть от этой огибающей. - Osc 1 sync send on fall - + + LFO predelay: + Пред. задержка LFO: - Osc 2 volume - + + Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. + Эта ручка определяет задержку перед запуском LFO (LFO - НизкоЧастотный осциллятор (генератор)). Чем больше величина, тем больше времени до того как LFO начнёт работать. - Osc 2 panning - + + LFO- attack: + Вступление LFO: - Osc 2 coarse detune - + + Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. + Используйте эту ручку для установления времени вступления этого LFO. Чем больше значение, тем дольше LFO нуждается в увеличении своей амплитуды до максимума. - Osc 2 fine detune left - + + SPD + SPD - Osc 2 fine detune right - + + LFO speed: + Скорость LFO: - Osc 2 stereo phase offset - + + Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. + Эта ручка устанавлявает скорость текущего LFO. Чем больше значение, тем быстрее LFO осциллирует и быстрее производится эффект. - Osc 2 waveform - + + Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. + Эта ручка устанавливает глубину модуляции для текущего LFO. Чем больше значение, тем в большей степени выбранная характеристика (н-р, громкость или частота среза) будет зависеть от этого LFO. - Osc 2 sync hard - + + Click here for a sine-wave. + Синусоида. - Osc 2 sync reverse - + + Click here for a triangle-wave. + Сгенерировать треугольный сигнал. - Osc 3 volume - + + Click here for a saw-wave for current. + Сгенерировать зигзагообразный сигнал. - Osc 3 panning - + + Click here for a square-wave. + Сгенерировать квадрат. - Osc 3 coarse detune - + + Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. + Задать свою форму сигнала. Впоследствии, перетащить соответствующий файл с записью в граф LFO. - Osc 3 sub-oscillator mix - + + Click here for random wave. + Нажмите сюда для случайной волны. - Osc 3 waveform 1 - + + FREQ x 100 + ЧАСТОТА x 100 - Osc 3 waveform 2 - + + Click here if the frequency of this LFO should be multiplied by 100. + Нажмите, чтобы умножить частоту этого LFO на 100. - Osc 3 sync hard - + + multiply LFO-frequency by 100 + Умножить частоту LFO на 100 - Osc 3 Sync reverse - + + MODULATE ENV-AMOUNT + МОДУЛИР ОГИБАЮЩУЮ - LFO 1 waveform - + + Click here to make the envelope-amount controlled by this LFO. + Нажмите сюда, чтобы глубина модуляции огибающей задавалась этим LFO. - LFO 1 attack - + + control envelope-amount by this LFO + Разрешить этому LFO задавать значение огибающей - LFO 1 rate - + + ms/LFO: + мс/LFO: - LFO 1 phase - + + Hint + Подсказка - LFO 2 waveform - + + Drag a sample from somewhere and drop it in this window. + Перетащите в это окно какую-нибудь запись. + + + EqControls - LFO 2 attack - + + Input gain + Входная мощность - LFO 2 rate - + + Output gain + Выходная мощность - LFO 2 phase - + + Low shelf gain + Низкая ступень усиления - Env 1 pre-delay - + + Peak 1 gain + Пик 1 усиление - Env 1 attack - + + Peak 2 gain + Пик 2 усиление - Env 1 hold - + + Peak 3 gain + Пик 3 усиление - Env 1 decay - + + Peak 4 gain + Пик 4 усиление - Env 1 sustain - + + High Shelf gain + Высокая степень усиления - Env 1 release - + + HP res + ВЧ резон - Env 1 slope - + + Low Shelf res + Низкая ступень резон - Env 2 pre-delay - + + Peak 1 BW + Пик 1 BW - Env 2 attack - + + Peak 2 BW + Пик 2 BW - Env 2 hold - + + Peak 3 BW + Пик 3 BW - Env 2 decay - + + Peak 4 BW + Пик 4 BW - Env 2 sustain - + + High Shelf res + Высокая ступень резон - Env 2 release - + + LP res + НЧ резон - Env 2 slope - + + HP freq + НЧ част - Osc 2+3 modulation - + + Low Shelf freq + Низкая степень част - Osc 1 - Vol env 1 - + + Peak 1 freq + Пик 1 част - Osc 1 - Vol env 2 - + + Peak 2 freq + Пик 2 част - Osc 1 - Vol LFO 1 - + + Peak 3 freq + Пик 3 част - Osc 1 - Vol LFO 2 - + + Peak 4 freq + Пик 4 част - Osc 2 - Vol env 1 - + + High shelf freq + Высокая ступень част - Osc 2 - Vol env 2 - + + LP freq + НЧ част - Osc 2 - Vol LFO 1 - + + HP active + ВЧ активна - Osc 2 - Vol LFO 2 - + + Low shelf active + Низкая ступень активна - Osc 3 - Vol env 1 - + + Peak 1 active + Пик 1 активен - Osc 3 - Vol env 2 - + + Peak 2 active + Пик 2 активен - Osc 3 - Vol LFO 1 - + + Peak 3 active + Пик 3 активен - Osc 3 - Vol LFO 2 - + + Peak 4 active + Пик 3 активен - Osc 1 - Phs env 1 - + + High shelf active + Высокая степень активна - Osc 1 - Phs env 2 - + + LP active + НЧ активна - Osc 1 - Phs LFO 1 - + + LP 12 + НЧ 12 - Osc 1 - Phs LFO 2 - + + LP 24 + НЧ 24 - Osc 2 - Phs env 1 - + + LP 48 + НЧ 48 - Osc 2 - Phs env 2 - + + HP 12 + ВЧ 12 - Osc 2 - Phs LFO 1 - + + HP 24 + ВЧ 24 - Osc 2 - Phs LFO 2 - + + HP 48 + ВЧ 48 - Osc 3 - Phs env 1 - + + low pass type + Тип нижних частот - Osc 3 - Phs env 2 - + + high pass type + Тип верхних частот - Osc 3 - Phs LFO 1 - + + Analyse IN + Анализировать ВХОД - Osc 3 - Phs LFO 2 - + + Analyse OUT + Анализировать ВЫХОД + + + EqControlsDialog - Osc 1 - Pit env 1 - + + HP + ВЧ - Osc 1 - Pit env 2 - + + Low Shelf + Низкая ступень - Osc 1 - Pit LFO 1 - + + Peak 1 + Пик 1 - Osc 1 - Pit LFO 2 - + + Peak 2 + Пик 2 - Osc 2 - Pit env 1 - + + Peak 3 + Пик 3 - Osc 2 - Pit env 2 - + + Peak 4 + Пик 3 - Osc 2 - Pit LFO 1 - + + High Shelf + Высокая ступень - Osc 2 - Pit LFO 2 - + + LP + НЧ - Osc 3 - Pit env 1 - + + In Gain + Входная мощность - Osc 3 - Pit env 2 - + + + + Gain + Мощность - Osc 3 - Pit LFO 1 - + + Out Gain + Выходная мощность - Osc 3 - Pit LFO 2 - + + Bandwidth: + Полоса пропускания: - Osc 1 - PW env 1 - + + Octave + Октава - Osc 1 - PW env 2 - + + Resonance : + Резонанс: - Osc 1 - PW LFO 1 - + + Frequency: + Частота: - Osc 1 - PW LFO 2 - + + lp grp + нч grp - Osc 3 - Sub env 1 - + + hp grp + вч grp + + + EqHandle - Osc 3 - Sub env 2 - + + Reso: + Резон: - Osc 3 - Sub LFO 1 - + + BW: + BW - Osc 3 - Sub LFO 2 - + + + Freq: + Част: - MonstroView + ExportProjectDialog - Operators view - Операторский вид + + Export project + Экспорт проекта - Matrix view - Матричный вид + + Output + Вывод - Volume - Громкость + + File format: + Формат файла: - Panning - Баланс + + Samplerate: + Частота дискретизации: - Coarse detune - + + 44100 Hz + 44.1 КГц - semitones - полутона + + 48000 Hz + 48 КГц - cents - + + 88200 Hz + 88.2 КГц - Stereo phase offset - Сдвиг стерео фазы + + 96000 Hz + 96 КГц - deg - + + 192000 Hz + 192 КГц - Pulse width - Длительность импульса + + Depth: + Емкость: - Send sync on pulse rise - + + 16 Bit Integer + 16 Бит целое - Send sync on pulse fall - + + 24 Bit Integer + 24 бита целое - Hard sync oscillator 2 - + + 32 Bit Float + 32 Бит плавающая - Reverse sync oscillator 2 - + + Stereo mode: + Режим стерео: - Sub-osc mix - + + Stereo + Стерео - Hard sync oscillator 3 - + + Joint Stereo + Объединённое стерео - Reverse sync oscillator 3 - + + Mono + Моно - Attack - Вступление + + Bitrate: + Частота бит: - Rate - Частота выборки + + 64 KBit/s + 64 КБит/с - Phase - + + 128 KBit/s + 128 КБит/с - Pre-delay - + + 160 KBit/s + 160 КБит/с - Hold - Удерживание + + 192 KBit/s + 192 КБит/с - Decay - Затихание + + 256 KBit/s + 256 КБит/с - Sustain - Выдержка + + 320 KBit/s + 320 КБит/с - Release - Убывание + + Use variable bitrate + Использовать плавающую глубину битности - Slope - + + Quality settings + Настройки качества - Modulation amount - Глубина модуляции + + Interpolation: + Интерполяция: - Fine tune left - + + Zero Order Hold + Нулевая задержка - Fine tune right - + + Sinc Fastest + Синхр. Быстрая - Mix osc 2 with osc 3 - + + Sinc Medium (recommended) + Синхр. Средняя (рекомендовано) - Modulate amplitude of osc 3 by osc 2 - + + Sinc Best (very slow!) + Синхр. лучшая (очень медленно!) - Modulate frequency of osc 3 by osc 2 - + + Oversampling (use with care!): + Передискретизация (использовать осторожно!): - Modulate phase of osc 3 by osc 2 - + + 1x (None) + 1х (Нет) - - - MultitapEchoControlDialog - Length - Длина + + 2x + - Step length: - + + 4x + - Dry - + + 8x + - Stages - + + Export as loop (remove end silence) + Экспортировать как петлю (убрать тишину в конце) - Swap inputs - + + Export between loop markers + Экспорт между метками петли - Dry gain: - + + Start + Начать - Low-pass stages: - + + Cancel + Отменить - Swap left and right input channels for reflections - + + Could not open file + Не могу открыть файл - - - NesInstrument - Channel 2 Coarse detune - + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Невозможно открыть файл %1 для записи. Пожалуйста, убедитесь, что у вас есть разрешение на запись в файл и содержащую его директорию, и попробуйте снова. - Channel 2 Volume - Громкость 2 канала + + Export project to %1 + Экспорт проекта в %1 - Master volume - Основная громкость + + Error + Ошибка - Vibrato - Вибрато + + Error while determining file-encoder device. Please try to choose a different output format. + Ошибка при определении кодека файла. Попробуйте выбрать другой формат вывода. - Channel 1 coarse detune - + + Rendering: %1% + Обработка: %1% - Channel 1 volume - Громкость первого канала + Compression level: + - Channel 1 envelope length - + (fastest) + - Channel 1 duty cycle - + (default) + - Channel 1 sweep amount - + (smallest) + + + + Expressive - Channel 1 sweep rate - + Selected graph + - Channel 2 envelope length - + A1 + - Channel 2 duty cycle - + A2 + - Channel 2 sweep amount - + A3 + - Channel 2 sweep rate - + W1 smoothing + - Channel 3 coarse detune - + W2 smoothing + - Channel 3 volume - Громкость третьего канала + W3 smoothing + - Channel 4 volume - Громкость четвёртого канала + PAN1 + - Channel 4 envelope length - + PAN2 + - Channel 4 noise frequency - + REL TRANS + + + + Fader - Channel 4 noise frequency sweep - + + + Please enter a new value between %1 and %2: + Введите новое значение от %1 до %2: - NesInstrumentView + FileBrowser - Volume - Громкость + + Browser + Обозреватель файлов - Coarse detune - + Search + - Envelope length - + Refresh list + + + + FileBrowserTreeWidget - Enable channel 1 - + + Send to active instrument-track + Послать на активную инструментальную-дорожку - Enable envelope 1 - + + Open in new instrument-track/Song Editor + Отркрыть в новой инструментальной дорожке/редакторе песни - Enable envelope 1 loop - + + Open in new instrument-track/B+B Editor + Открыть в новой инструментальной дорожке/Б+Б редакторе - Enable sweep 1 - + + Loading sample + Загрузка записи - Sweep amount - + + Please wait, loading sample for preview... + Пж. ждите, запись загружается для просмотра... - Sweep rate - + + Error + Ошибка - 12.5% Duty cycle - + + does not appear to be a valid + Не похоже на правильное - 25% Duty cycle - + + file + файл - 50% Duty cycle - + + --- Factory files --- + --- Заводские файлы --- + + + FlangerControls - 75% Duty cycle - + + Delay Samples + Задержка сэмплов - Enable channel 2 - + + Lfo Frequency + Частота LFO - Enable envelope 2 - + + Seconds + Секунды - Enable envelope 2 loop - + + Regen + - Enable sweep 2 - + + Noise + Шум - Enable channel 3 - + + Invert + Инвертировать + + + FlangerControlsDialog - Noise Frequency - + + DELAY + Задержка - Frequency sweep - + + Delay Time: + Время задержки: - Enable channel 4 - + + RATE + ЧАСТ - Enable envelope 4 - + + Period: + Период: - Enable envelope 4 loop - + + AMNT + ГЛУБ - Quantize noise frequency when using note frequency - + + Amount: + Величина: - Use note frequency for noise - + + FDBK + - Noise mode - + + Feedback Amount: + Объём возврата: - Vibrato - Вибрато + + NOISE + Шум - Master volume - Основная громкость + + White Noise Amount: + Объём белого шума: + + + + Invert + Инвертировать - OpulenzInstrument + FxLine - Patch - Патч + + Channel send amount + Величина отправки канала - Op 1 attack - + + The FX channel receives input from one or more instrument tracks. + It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. + +In order to route the channel to another channel, select the FX channel and click on the "send" button on the channel you want to send to. The knob under the send button controls the level of signal that is sent to the channel. + +You can remove and move FX channels in the context menu, which is accessed by right-clicking the FX channel. + + Канал эффектов (ЭФ) получает сигнал на вход от одной или нескольких инструментальных дорожек. +В свою очередь его можно подключить к нескольким другим каналам эффектов. ЛММС автоматически предотвращает бесконечные циклы и не позволяет создавать соединения, которые приведут к бесконечному циклу. +Чтобы соединить один канал с другим, выберите канал ЭФфектов и кликните кнопку послать (Send) на канале, куда нужно послать. Регулятор под кнопкой "послать" контролирует уровень сигнала, посылаемого на канал. +Можно убирать и двигать каналы эффектов через контекстное меню, если кликнуть правой кнопкой мыши по каналу эффектов. + - Op 1 decay - + + Move &left + Двигать влево &L - Op 1 sustain - + + Move &right + Двигать вправо &r - Op 1 release - + + Rename &channel + Переименовать канал &c - Op 1 level - + + R&emove channel + Удалить канал &e - Op 1 level scaling - + + Remove &unused channels + Удалить неиспользуемые каналы &u + + + FxMixer - Op 1 frequency multiplier - + + Master + Главный - Op 1 feedback - + + + + FX %1 + Эффект %1 - Op 1 key scaling rate - + + Volume + Громкость - Op 1 percussive envelope - + + Mute + Тихо - Op 1 tremolo - + + Solo + Соло + + + FxMixerView - Op 1 vibrato - + + FX-Mixer + Микшер Эффектов - Op 1 waveform - + + FX Fader %1 + - Op 2 attack - + + Mute + Тихо - Op 2 decay - + + Mute this FX channel + Заглушить этот канал ЭФ - Op 2 sustain - + + Solo + Соло - Op 2 release - + + Solo FX channel + Соло канал ЭФ + + + FxRoute - Op 2 level - + + + Amount to send from channel %1 to channel %2 + Величина отправки с канала %1 на канал %2 + + + GigInstrument - Op 2 level scaling - + + Bank + Банк - Op 2 frequency multiplier - + + Patch + Патч - Op 2 key scaling rate - + + Gain + Мощность + + + GigInstrumentView - Op 2 percussive envelope - + + Open other GIG file + Открыть другой GIG файл - Op 2 tremolo - + + Click here to open another GIG file + Кликните сюда, чтобы открыть другой GIG файл - Op 2 vibrato - + + Choose the patch + Выбрать патч - Op 2 waveform - + + Click here to change which patch of the GIG file to use + Нажмите здесь для смены используемого патча GIG файла - FM - FM + + + Change which instrument of the GIG file is being played + Изменить инструмент, который воспроизводит GIG файл - Vibrato depth - + + Which GIG file is currently being used + Какой GIG файл сейчас используется - Tremolo depth - + + Which patch of the GIG file is currently being used + Какой патч GIG файла сейчас используется - - - OpulenzInstrumentView - Attack - Вступление + + Gain + УСИЛ - Decay - Затихание + + Factor to multiply samples by + Фактор умножения сэмплов - Release - Убывание + + Open GIG file + Открыть GIG файл - Frequency multiplier - + + GIG Files (*.gig) + GIG Файлы (*.gig) - OscillatorObject - - Osc %1 volume - Громкость осциллятора %1 - + GuiApplication - Osc %1 panning - Стереобаланс для осциллятора %1 + + Working directory + Рабочий каталог - Osc %1 coarse detuning - Подстройка осциллятора %1 грубая + + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. + Рабочий каталог LMMS (%1) не существует. Создать его? Позже вы сможете сменить его через Правка -> Параметры. - Osc %1 fine detuning left - Подстройка левого канала осциллятора %1 тонкая + + Preparing UI + Подготовка UI - Osc %1 fine detuning right - Подстройка правого канала осциллятора %1 тонкая + + Preparing song editor + Подготовка редактора песни - Osc %1 phase-offset - Сдвиг фазы для осциллятора %1 + + Preparing mixer + Подготовка микшера - Osc %1 stereo phase-detuning - Подстройка стерео-фазы осциллятора %1 + + Preparing controller rack + Подготовка стойки управления - Osc %1 wave shape - Гладкость сигнала осциллятора %1 + + Preparing project notes + Подготовка заметок проекта - Modulation type %1 - Тип модуляции %1 + + Preparing beat/bassline editor + Подготовка Ритм+Бас редактора - Osc %1 waveform - Форма сигнала осциллятора %1 + + Preparing piano roll + Подготовка редактора нот - Osc %1 harmonic - Осц %1 гармонический + + Preparing automation editor + Подготовка редактора автоматизации - PatchesDialog + InstrumentFunctionArpeggio - Qsynth: Channel Preset - + + Arpeggio + Арпеджио - Bank selector - + + Arpeggio type + Тип арпеджио - Bank - Банк + + Arpeggio range + Диапазон арпеджио - Program selector - Выбор программ + + Cycle steps + - Patch - Патч + + Skip rate + Частота пропуска - Name - Имя + + Miss rate + - OK - ОК + + Arpeggio time + Период арпеджио - Cancel - Отмена + + Arpeggio gate + Шлюз арпеджио - - - PatmanView - Loop - Повтор + + Arpeggio direction + Направление арпеджио - Loop mode - Режим повтора + + Arpeggio mode + Режим арпеджио - Tune - Подстроить + + Up + Вверх - Tune mode - Тип подстройки + + Down + Вниз - No file selected - Не выбран файл + + Up and down + Вверх и вниз - Open patch file - Открыть патч-файл + + Down and up + Вниз и вверх - Patch-Files (*.pat) - Патч-файлы (*.pat) + + Random + Случайно + + + + Free + Свободно + + + + Sort + Упорядочить - Open patch - + + Sync + Синхронизировать - PeakControllerEffectControlDialog + InstrumentFunctionArpeggioView - BASE - БАЗА + + ARPEGGIO + ARPEGGIO - Modulation amount: - Глубина модуляции: + + An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. + Арпеджио — разновидность исполнения аккордов на фортепиано и струнных инструментах, которая оживляет звучание. Струнф таких инструментов играются перебором по аккордам, как на арфе, когда звуки аккорда следуют один за другим. Типичные арпеджио - мажорные и минорные триады, среди которых можно выбрать и другие. - Attack: - Вступление: + + RANGE + RANGE - Release: - Убывание: + + Arpeggio range: + Диапазон арпеджио: - AMNT - ГЛУБ + + octave(s) + Октав[а/ы] - MULT - МНОЖ + + Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. + Используйте эту ручку, чтобы установить диапазон арпеджио (в октавах). Выбранный тип арпеджио будет охватывать указанное количество октав. - ATCK - ВСТУП + + CYCLE + ЦИКЛ - DCAY - СПАД + + Cycle notes: + - Treshold: - + + note(s) + нота(ы) - TRSH - + + Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. + - Base: - + + SKIP + ПРОПУСК - Amount multiplicator: - + + Skip rate: + Частота пропуска: - Mute output - Заглушить вывод + + + + % + % - Absolute value - + + The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. + - - - PeakControllerEffectControls - Base value - Опорное значение + + MISS + ПРОПУСК - Modulation amount - Глубина модуляции + + Miss rate: + - Mute output - Заглушить вывод + + The miss function will make the arpeggiator miss the intended note. + - Attack - Вступление + + TIME + TIME - Release - Убывание + + Arpeggio time: + Период арпеджио: - Treshold - + + ms + мс - Absolute value - + + Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. + Регулировка периода арпеджио - время (в миллисекундах), которое должен звучать каждый тон арпеджио. - Amount multiplicator - + + GATE + GATE - - - QWidget - Name: - Название: + + Arpeggio gate: + Шлюз арпеджио: - Maker: - Создатель: + + Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. + Регулировка шлюза арпеджио, показывает процентную долю каждого тона арпеджио, которая будет воспроизведена. Простой способ создавать стаккато-арпеджио. - Copyright: - Правообладатель: + + Chord: + Аккорд: - Requires Real Time: - Требуется обработка в реальном времени: + + Direction: + Направление: - Yes - Да + + Mode: + Режим: + + + InstrumentFunctionNoteStacking - No - Нет + + octave + Октава - Real Time Capable: - Работа в реальном времени: + + + Major + Мажорный - In Place Broken: - Вместо сломанного: + + Majb5 + Majb5 - Channels In: - Каналы в: + + minor + минорный - Channels Out: - Каналы из: + + minb5 + minb5 - File: - Файл: + + sus2 + sus2 - File: %1 - Файл: %1 + + sus4 + sus4 - - - ReverbSCControlDialog - Input - Ввод + + aug + aug - Size - Размер + + augsus4 + augsus4 - Size: - Размер: + + tri + tri - Color - Цвет + + 6 + 6 - Color: - Цвет: + + 6sus4 + 6sus4 - Output - Вывод + + 6add9 + 6add9 - Input gain: - Входная мощность: + + m6 + m6 - Output gain: - Выходная мощность: + + m6add9 + m6add9 - - - ReverbSCControls - Size - Размер + + 7 + 7 - Color - Цвет + + 7sus4 + 7sus4 - Input gain - Входная мощность + + 7#5 + 7#5 - Output gain - Выходная мощность + + 7b5 + 7b5 - - - SpectrumAnalyzerControlDialog - Linear spectrum - Линейный спектр + + 7#9 + 7#9 - Linear Y axis - Линейная ось ординат (Y) + + 7b9 + 7b9 - - - SpectrumAnalyzerControls - Linear spectrum - Линейный спектр + + 7#5#9 + 7#5#9 - Linear Y axis - Линейная ось ординат (Y) + + 7#5b9 + 7#5b9 - Channel mode - Режим канала + + 7b5b9 + 7b5b9 - - - TrackContainer - Cancel - Отменить + + 7add11 + 7add11 - Please wait... - Подождите, пожалуйста... + + 7add13 + 7add13 - Importing MIDI-file... - Импортирую файл MIDI... + + 7#11 + 7#11 - - - TripleOscillatorView - Synchronize oscillator 1 with oscillator 2 - Синхронизировать первый осциллятор по второму + + Maj7 + Maj7 - Synchronize oscillator 2 with oscillator 3 - Синхронизировать осциллятор 2 и 3 + + Maj7b5 + Maj7b5 - Osc %1 volume: - Громкость осциллятора %1: + + Maj7#5 + Maj7#5 - Osc %1 panning: - Баланс для осциллятора %1: + + Maj7#11 + Maj7#11 - Osc %1 coarse detuning: - Грубая подстройка осциллятора %1: + + Maj7add13 + Maj7add13 - semitones - полутон[а,ов] + + m7 + m7 - Osc %1 fine detuning left: - Точная подстройка левого канала осциллятора %1: + + m7b5 + m7b5 - cents - Проценты + + m7b9 + m7b9 - Osc %1 fine detuning right: - Точная подстройка правого канала осциллятора %1: + + m7add11 + m7add11 - Osc %1 phase-offset: - Сдвиг фазы осциллятора %1: + + m7add13 + m7add13 - degrees - градусы + + m-Maj7 + m-Maj7 - Osc %1 stereo phase-detuning: - Подстройка стерео фазы осциллятора %1: + + m-Maj7add11 + m-Maj7add11 - Modulate phase of oscillator 1 by oscillator 2 - + + m-Maj7add13 + m-Maj7add13 - Modulate amplitude of oscillator 1 by oscillator 2 - + + 9 + 9 - Mix output of oscillators 1 & 2 - + + 9sus4 + 9sus4 - Modulate frequency of oscillator 1 by oscillator 2 - + + add9 + add9 - Modulate phase of oscillator 2 by oscillator 3 - + + 9#5 + 9#5 - Modulate amplitude of oscillator 2 by oscillator 3 - + + 9b5 + 9b5 - Mix output of oscillators 2 & 3 - + + 9#11 + 9#11 - Modulate frequency of oscillator 2 by oscillator 3 - + + 9b13 + 9b13 - Sine wave - Синусоида + + Maj9 + Maj9 - Triangle wave - + + Maj9sus4 + Maj9sus4 - Saw wave - Зигзаг + + Maj9#5 + Maj9#5 - Square wave - + + Maj9#11 + Maj9#11 - Moog-like saw wave - + + m9 + m9 - Exponential wave - Экспоненциальная волна + + madd9 + madd9 - White noise - Белый шум + + m9b5 + m9b5 - User-defined wave - + + m9-Maj7 + m9-Maj7 - - - VestigeInstrumentView - Show/hide GUI - Показать/скрыть интерфейс + + 11 + 11 - Turn off all notes - Выключить все ноты + + 11b9 + 11b9 - DLL-files (*.dll) - Бибилиотеки DLL (*.dll) + + Maj11 + Maj11 - EXE-files (*.exe) - Программы EXE (*.exe) + + m11 + m11 - Previous (-) - Предыдущий <-> + + m-Maj11 + m-Maj11 - Save preset - Сохранить предустановку + + 13 + 13 - Next (+) - Следующий <+> + + 13#9 + 13#9 - Preset - Предустановка + + 13b9 + 13b9 - by - от + + 13b5b9 + 13b5b9 - - VST plugin control - - управление VST плагином + + Maj13 + Maj13 - Open VST plugin - + + m13 + m13 - Control VST plugin from LMMS host - + + m-Maj13 + m-Maj13 - Open VST plugin preset - + + Harmonic minor + Гармонический минор - No VST plugin loaded - + + Melodic minor + Мелодический минор - - - VstEffectControlDialog - Show/hide - Показать/Скрыть + + Whole tone + Целый тон - Previous (-) - Предыдущий <-> + + Diminished + Пониженный - Next (+) - Следующий <+> + + Major pentatonic + Мажорная пентатоника - Save preset - Сохранить настройку + + Minor pentatonic + Минорная пентатоника - Effect by: - Эффекты по: + + Jap in sen + - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + + Major bebop + - Control VST plugin from LMMS host - + + Dominant bebop + - Open VST plugin preset - + + Blues + Blues - - - VstPlugin - Loading plugin - Загрузка модуля + + Arabic + Арабский - Open Preset - Открыть предустановку + + Enigmatic + - Vst Plugin Preset (*.fxp *.fxb) - Предустановка VST плагина (*.fxp *.fxb) + + Neopolitan + Неополитанский - : default - : основные + + Neopolitan minor + Неополитанский минор - " - " + + Hungarian minor + - ' - ' + + Dorian + Дорийский - Save Preset - Сохранить предустановку + + Phrygian + Фригийский - .fxp - .fxp + + Lydian + Лидийский - .FXP - .FXP + + Mixolydian + Миксолидийский - .FXB - .FXB + + Aeolian + Эолийский - .fxb - .fxb + + Locrian + - Please wait while loading VST plugin... - Пожалуйста, подождите пока грузится VST плагин... + + Minor + - The VST plugin %1 could not be loaded. - VST плагин %1 не может быть загружен. + + Chromatic + Хроматический - - - WatsynInstrument - Volume A1 - + + Half-Whole Diminished + - Volume A2 - + + 5 + 5 - Volume B1 - + + Phrygian dominant + - Volume B2 - + + Persian + - Panning A1 - + + Chords + Аккорды - Panning A2 - + + Chord type + Тип аккорда - Panning B1 - + + Chord range + Диапазон аккорда + + + InstrumentFunctionNoteStackingView - Panning B2 - + + STACKING + СТЫКОВКА - Freq. multiplier A1 - + + Chord: + Аккорд: - Freq. multiplier A2 - + + RANGE + ДИАП - Freq. multiplier B1 - + + Chord range: + Диапазон аккорда: - Freq. multiplier B2 - + + octave(s) + Октав[а/ы] - Left detune A1 - + + Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. + Эта ручка изменяет диапазон аккорда, который будет содержать указанное число октав. + + + InstrumentMidiIOView - Left detune A2 - + + ENABLE MIDI INPUT + ВКЛ MIDI ВВОД - Left detune B1 - + + + CHANNEL + CHANNEL - Left detune B2 - + + + VELOCITY + VELOCITY - Right detune A1 - + + ENABLE MIDI OUTPUT + ВКЛ MIDI ВЫВОД - Right detune A2 - + + PROGRAM + PROGRAM - Right detune B1 - + + NOTE + NOTE - Right detune B2 - + + MIDI devices to receive MIDI events from + MiDi устройства-источники событий - A-B Mix - + + MIDI devices to send MIDI events to + MiDi устройства для отправки событий на них - A-B Mix envelope amount - + + CUSTOM BASE VELOCITY + ПРОИЗВОЛЬНАЯ БАЗОВАЯ СКОРОСТЬ - A-B Mix envelope attack - + + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity + Определяет базовую скорость нормализации для MiDi инструментов при громкости ноты 100% - A-B Mix envelope hold - + + BASE VELOCITY + БАЗОВАЯ СКОРОСТЬ + + + InstrumentMiscView - A-B Mix envelope decay - + + MASTER PITCH + Мастер-высота - A1-B2 Crosstalk - + + Enables the use of Master Pitch + Включает использование основной тональности + + + InstrumentSoundShaping - A2-A1 modulation - + + VOLUME + VOLUME - B2-B1 modulation - + + Volume + Громкость - Selected graph - + + CUTOFF + CUTOFF - - - WatsynView - Select oscillator A1 - + + + Cutoff frequency + Срез частоты - Select oscillator A2 - + + RESO + RESO - Select oscillator B1 - + + Resonance + Резонанс - Select oscillator B2 - + + Envelopes/LFOs + Огибание/LFO - Mix output of A2 to A1 - + + Filter type + Тип фильтра - Mix output of B2 to B1 - + + Q/Resonance + - Draw your own waveform here by dragging your mouse on this graph. - Здесь вы можете рисовать собственный сигнал передвигая зажатой мышью по этому графу. + + LowPass + Низ.ЧФ - Load waveform - + + HiPass + Выс.ЧФ - Phase left - Фаза слева + + BandPass csg + Сред.ЧФ csg - Phase right - Фаза справа + + BandPass czpg + Сред.ЧФ czpg - Normalize - Нормализовать + + Notch + Полосно-заграждающий - Invert - + + Allpass + Все проходят - Smooth - Сгладить + + Moog + Муг - Sine wave - Синусоида + + 2x LowPass + 2х Низ.ЧФ - Triangle wave - Треугольная волна + + RC LowPass 12dB + RC Низ.ЧФ 12дБ - Square wave - Квадрат + + RC BandPass 12dB + RC Сред.ЧФ 12 дБ - Volume - Громкость + + RC HighPass 12dB + RC Выс.ЧФ 12дБ - Panning - Баланс + + RC LowPass 24dB + RC Низ.ЧФ 24дБ - Freq. multiplier - + + RC BandPass 24dB + RC Сред.ЧФ 24дБ - Left detune - + + RC HighPass 24dB + RC Выс.ЧФ 24дБ - cents - + + Vocal Formant Filter + Фильтр Вокальной форманты - Right detune - + + 2x Moog + 2x Муг - A-B Mix - + + SV LowPass + SV Низ.ЧФ - Mix envelope amount - + + SV BandPass + SV Сред.ЧФ - Mix envelope attack - + + SV HighPass + SV Выс.ЧФ - Mix envelope hold - + + SV Notch + - Mix envelope decay - + + Fast Formant + - Crosstalk - + + Tripole + Триполи + + + + InstrumentSoundShapingView + + + TARGET + ЦЕЛЬ - Modulate amplitude of A1 by output of A2 - + + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + Эта вкладка позволяет вам настроить огибающие. Они очень важны для настройки звучания. +Например, с помощью огибающей громкости вы можете задать зависимость громкости звучания от времени. Если вам понадобится эмулировать мягкие струнные, просто задайте больше времени нарастания и исчезновения звука. С помощью обгибающих и низкочастотного осцилятора (LFO) вы в несколько щелчков мыши сможете создать просто невероятные звуки! - Ring modulate A1 and A2 - + + FILTER + ФИЛЬТР - Modulate phase of A1 by output of A2 - + + Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. + Здесь вы можете выбрать фильтр для дорожки этого инструмента. Фильтры могут довольно сильно менять звучание. - Modulate amplitude of B1 by output of B2 - + + FREQ + ЧАСТ - Ring modulate B1 and B2 - + + cutoff frequency: + Срез частот: - Modulate phase of B1 by output of B2 - + + Hz + Гц - Load a waveform from a sample file - + + Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... + Эта ручка устанавливает частоту среза для выбранного фильтра. К примеру, ФНЧ будет срезать сигнал на частотах выше частоты среза, полосно-пропускающий фильтр будет хорошо пропускать сигнал только на заданной частоте и так далее... - Shift phase by -15 degrees - + + RESO + RESO - Shift phase by +15 degrees - + + Resonance: + Усиление: - Saw wave - Зигзаг + + Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. + Эта ручка задаёт количество резонанса для фильтра, этим определяется насколько нужно усилить ближайшие к отрезанным частоты. + + + + Envelopes, LFOs and filters are not supported by the current instrument. + Огибающие, LFO и фильтры не поддерживаются этим инструментом. - Xpressive + InstrumentTrack - Selected graph - + + With this knob you can set the volume of the opened channel. + Регулировка громкости текущего канала. - A1 - + + + unnamed_track + безымянная_дорожка - A2 - + + Base note + Опорная нота - A3 - + + Volume + Громкость - W1 smoothing - + + Panning + Стерео - W2 smoothing - + + Pitch + Тональность - W3 smoothing - + + Pitch range + Диапазон тональности - Panning 1 - + + FX channel + Канал ЭФ - Panning 2 - + + Master Pitch + Основная тональность - Rel trans - + + + Default preset + Основная предустановка - XpressiveView + InstrumentTrackView - Draw your own waveform here by dragging your mouse on this graph. - + + Volume + Громкость - Select oscillator W1 - + + Volume: + Громкость: - Select oscillator W2 - + + VOL + ГРОМ - Select oscillator W3 - + + Panning + Баланс - Select output O1 - + + Panning: + Баланс: - Select output O2 - + + PAN + БАЛ - Open help window - + + MIDI + MIDI - Sine wave - Синусоида + + Input + Вход - Moog-saw wave - + + Output + Выход - Exponential wave - Экспоненциальная волна + + FX %1: %2 + ЭФ %1: %2 + + + InstrumentTrackWindow - Saw wave - Зигзаг + + GENERAL SETTINGS + ОСНОВНЫЕ НАСТРОЙКИ - User-defined wave - + + Use these controls to view and edit the next/previous track in the song editor. + Используйте эти регуляторы, чтобы видеть и редактировать дорожку в редакторе песни. - Triangle wave - + + Instrument volume + Громкость инструмента - Square wave - + + Volume: + Громкость: - White noise - Белый шум + + VOL + ГРОМ - WaveInterpolate - + + Panning + Баланс - ExpressionValid - + + Panning: + Стереобаланс: - General purpose 1: - + + PAN + БАЛ - General purpose 2: - + + Pitch + Тональность - General purpose 3: - + + Pitch: + Тональность: - O1 panning: - + + cents + процентов - O2 panning: - + + PITCH + ТОН - Release transition: - + + Pitch range (semitones) + Диапазон тональности (полутона) - Smoothness - + + RANGE + ДИАП - - - ZynAddSubFxInstrument - Portamento - Портаменто + + FX channel + Канал ЭФ - Bandwidth - Ширина полосы + + FX + ЭФ - Filter frequency - + + Save current instrument track settings in a preset file + Сохранить текущую инструментаьную дорожку в файл предустановок - Filter resonance - + + Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. + Нажать здесь, чтобы сохранить настройки текущей инстр. дорожки в файл предустановок. Позже можно загрузить эту предустановку двойным кликом в браузере предустановок. - FM gain - + + SAVE + Сохранить - Resonance center frequency - + + Envelope, filter & LFO + - Resonance bandwidth - + + Chord stacking & arpeggio + - Forward MIDI control change events - + + Effects + Эффекты - - - ZynAddSubFxView - Show GUI - Показать интерфейс + + MIDI settings + Параметры MIDI - Portamento: - Портаменто: + + Miscellaneous + Разное - PORT - PORT + + Save preset + Сохранить предустановку - FREQ - FREQ + + XML preset file (*.xpf) + XML файл настроек (*.xpf) - RES - RES + + Plugin + Модуль + + + Knob - Bandwidth: - Полоса пропускания: + + Set linear + Установить линейно - BW - BW + + Set logarithmic + Установить логарифмически - FM GAIN - FM GAIN + + Please enter a new value between -96.0 dBFS and 6.0 dBFS: + Введите новое значение от –96,0 дБВ до 6,0 дБВ: - Resonance center frequency: - Частоты центра резонанса: + + Please enter a new value between %1 and %2: + Введите новое значение от %1 до %2: + + + LadspaControl - RES CF - RES CF + + Link channels + Связать каналы + + + LadspaControlDialog - Resonance bandwidth: - Ширина полосы резонанса: + + Link Channels + Связать каналы - RES BW - RES BW + + Channel + Канал + + + LadspaControlView - Filter frequency: - + + Link channels + Связать каналы - Filter resonance: - + + Value: + Значение: - FM gain: - + + Sorry, no help available. + Извините, справки нет. + + + LadspaEffect - Forward MIDI control changes - + + Unknown LADSPA plugin %1 requested. + Запрошен неизвестный модуль LADSPA «%1». - audioFileProcessor + LcdSpinBox - Amplify - Усиление + + Please enter a new value between %1 and %2: + Введите новое значение от %1 до %2: + + + LeftRightNav - Start of sample - Начало записи + + + + Previous + Предыдущий - End of sample - Конец записи + + + + Next + Следующий - Reverse sample - Перевернуть запись + + Previous (%1) + Предыдущий (%1) - Stutter - Запинание + + Next (%1) + Следующий (%1) + + + LfoController - Loopback point - Точка петли + + LFO Controller + Контроллер LFO - Loop mode - Режим повтора + + Base value + Основное значение - Interpolation mode - Режим интерполяции + + Oscillator speed + Скорость волны - None - Нет + + Oscillator amount + Размер волны - Linear - + + Oscillator phase + Фаза волны - Sinc - + + Oscillator waveform + Форма волны - Sample not found: %1 - Сэмпл не найден: %1 + + Frequency Multiplier + Множитель частоты - bitInvader + LfoControllerDialog - Sample length - + + LFO + LFO - - - bitInvaderView - Sine wave - Синусоида + + LFO Controller + Контроллер LFO - Triangle wave - Треугольник + + BASE + БАЗА - Saw wave - Зигзаг + + Base amount: + Базовое значение: - Square wave - Квадрат (Меандр) + + todo + доделать - Interpolation - Интерполяция + + SPD + СКОР - Normalize - Нормализовать + + LFO-speed: + Скорость LFO: - Draw your own waveform here by dragging your mouse on this graph. - Здесь вы можете рисовать собственный сигнал. + + Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. + Эта ручка устанавлявает скорость LFO. Чем больше значение, тем больше частота осциллятора. - Sample length - + + AMNT + ГЛУБ - White noise - Белый шум + + Modulation amount: + Количество модуляции: - User-defined wave - + + Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. + Эта ручка устанавливает глубину модуляции для LFO. Чем больше значение, тем в большей степени выбранная характеристика (н-р, громкость или частота среза) будет зависеть от ГНЧ(LFO). - Smooth waveform - Сгладить волну + + PHS + ФАЗА - - - dynProcControlDialog - INPUT - ВХОД + + Phase offset: + Сдвиг фазы: - Input gain: - Входная мощность: + + degrees + градусы - OUTPUT - Выход + + With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + Эта ручка устанавливает начальную фазу НизкоЧастотного Осциллятора (LFO), т. е. точку, с которой осциллятор начинает вырабатывать сигнал. Например, если вы задали синусоидальную форму сигнала и начальную фазу 180º, волна сначала пойдёт вниз, а не вверх, так же как и для квадратной волны. - Output gain: - Выходная мощность: + + Click here for a sine-wave. + Синусоида. - ATTACK - АТАКА + + Click here for a triangle-wave. + Сгенерировать треугольный сигнал. - Peak attack time: - Время пиковой атаки: + + Click here for a saw-wave. + Сгенерировать зигзаг. - RELEASE - ОТПУСК + + Click here for a square-wave. + Сгенерировать квадрат. - Peak release time: - Время отпуска пика: + + Click here for a moog saw-wave. + Нажать здесь для зигзагообразной муг волны. - Process based on the maximum of both stereo channels - Процесс основанный на максимуме от обоих каналов + + Click here for an exponential wave. + Генерировать экспоненциальный сигнал. - Process based on the average of both stereo channels - Процесс основанный на средней обоих каналов + + Click here for white-noise. + Сгенерировать белый шум. - Process each stereo channel independently - Обрабатывает каждый стерео канал независимо + + Click here for a user-defined shape. +Double click to pick a file. + Нажмите здесь для определения своей формы. +Двойное нажатие для выбора файла. + + + LmmsCore - Reset wavegraph - + + Generating wavetables + Генерация волн - Smooth wavegraph - + + Initializing data structures + Инициализация структуры данных - Increase wavegraph amplitude by 1 dB - + + Opening audio and midi devices + Открываем аудио и миди устройства - Decrease wavegraph amplitude by 1 dB - + + Launching mixer threads + Запускаем потоки микшера + + + MainWindow - Stereo mode: maximum - + Settings + Параметры + + Configuration file + Файл настроек - Stereo mode: average - + + Error while parsing configuration file at line %1:%2: %3 + Ошибка во время обработки файла настроек в строке %1:%2: %3 - Stereo mode: unlinked - + + Could not open file + Не могу открыть файл - - - dynProcControls - Input gain - Входная мощность + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Невозможно открыть файл %1 для записи. Пожалуйста, убедитесь, что у вас есть разрешение на запись в файл и содержащую его директорию, и попробуйте снова. - Output gain - Выходная мощность + + Project recovery + Восстановление проекта - Attack time - Время атаки + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + Остался файл для восстановления. Похоже последняя сессия не была нормально завершена или запущен ещё один процесс LMMS. +Хотите восстановить проект из этой сессии? - Release time - Время отпуска + + + + Recover + Восстановить - Stereo mode - Режим стерео + + Recover the file. Please don't run multiple instances of LMMS when you do this. + Восстановить файл. Пожалуйства, не запускайте несколько процессов ЛММС во время этого. - - - kickerInstrument - Start frequency - Начальная частота + + + + Discard + Отказать - End frequency - Конечная частота + + Launch a default session and delete the restored files. This is not reversible. + Запустить обычную сессию и удалить восстановленные файлы. Это безвозвратно. - Gain - Усиление + + Version %1 + Версия %1 - Length - Длина + + Preparing plugin browser + Подготовка обзора плагинов - Noise - Шум + + Preparing file browsers + Подготовка обзора файлов - Click - + + My Projects + Мои проекты - Start from note - + + My Samples + Мои сэмплы - End to note - + + My Presets + Мои предустановки - Start distortion - + + My Home + Моя домашняя папка - End distortion - + + Root directory + Корневая директория - Envelope slope - + + Volumes + Громкость 1 оциллятора - Frequency slope - + + My Computer + Мой компьютер - - - kickerInstrumentView - Start frequency: - Начальная частота: + + Loading background artwork + Загружаем фоновый рисунок - End frequency: - Конечная частота: + + &File + &F Файл - Gain: - Усиление: + + &New + &N Новый - Click: - + + New from template + Новый на основе шаблона - Noise: - Шум: + + &Open... + &Открыть... - Frequency slope: - + + &Recently Opened Projects + &R Недавние проекты - Envelope length: - + + &Save + &S Сохранить - Envelope slope: - + + Save &As... + &A Сохранить как... - Start distortion: - + + Save as New &Version + &V Сохранить как новую версию - End distortion: - + + Save as default template + Сохранить как обычный шаблон - - - ladspaBrowserView - Available Effects - Доступные эффекты + + Import... + Импорт... - Unavailable Effects - Недоступные эффекты + + E&xport... + &X Экспорт... - Instruments - Инструменты + + E&xport Tracks... + &x Экспорт дорожек... - Analysis Tools - Анализаторы + + Export &MIDI... + Экспорт &MIDI... - Don't know - Неизвестные + + &Quit + &Q Выйти - Type: - Тип: + + &Edit + &E Правка - - - ladspaDescription - Plugins - Модули + + Undo + Откатить действие - Description - Описание + + Redo + Возврат действия - - - ladspaPortDialog - Ports - Порты + + Settings + Параметры - Name - Название - - - Rate - Частота выборки + + &View + &Просмотр - Direction - Направление + + &Tools + &T Сервис - Type - Тип + + &Help + &H Справка - Min < Default < Max - Меньше < Стандарт < Больше + + Online Help + Помощь онлайн - Logarithmic - Логарифмический + + Help + Справка - SR Dependent - Зависимость от SR + + What's This? + Что это? - Audio - Аудио + + About + О программе - Control - Управление + + Create new project + Создать новый проект - Input - Ввод + + Create new project from template + Создать новый проект по шаблону - Output - Вывод + + Open existing project + Открыть существующий проект - Toggled - Включено + + Recently opened projects + Недавние проекты - Integer - Целое + + Save current project + Сохранить текущий проект - Float - Дробное + + Export current project + Экспорт проекта - Yes - Да + + What's this? + Что это? - - - lb302Synth - VCF Cutoff Frequency - Частота среза VCF + + Toggle metronome + Включить метроном - VCF Resonance - Усиление VCF + + Show/hide Song-Editor + Показать/скрыть музыкальный редактор - VCF Envelope Mod - Модуляция огибающей VCF + + By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. + Сим запускается или скрывается музыкальный редактор. С его помощью вы можете редактировать композицию и задавать время воспроизведения каждой дорожки. +Также вы можете вставлять и передвигать записи прямо в списке воспроизведения. - VCF Envelope Decay - Спад огибающей VCF + + Show/hide Beat+Bassline Editor + Показать/скрыть Ритм+Бас редактор - Distortion - Искажение + + By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. + Сим запускается ритм-бас редактор. Он необходим для установки ритма, открытия, добавления и удаления каналов, а также вырезания, копирования и вставки ритм-бас шаблонов, мелодий и т. п. - Waveform - Форма сигнала + + Show/hide Piano-Roll + Показать/Скрыть Редактор Нот - Slide Decay - Сдвиг затухания + + Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. + Запуск редатора нот. С его помощью вы можете легко редактировать мелодии. - Slide - Сдвиг + + Show/hide Automation Editor + Показать/скрыть редактор автоматизации - Accent - Акцент + + Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. + Показать/скрыть окно редактора автоматизации. С его помощью вы можете легко редактироватьдинамику выбранных величин. - Dead - Глухо + + Show/hide FX Mixer + Показать/скрыть микшер ЭФ - 24dB/oct Filter - 24дБ/окт фильтр + + Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. + Скрыть/показать микшер ЭФфектов. Он является мощным инструментом для управления эффектами. Вы можете вставлять эффекты в различные каналы. - - - lb302SynthView - Cutoff Freq: - Частота среза: + + Show/hide project notes + Показать/скрыть заметки проекта - Resonance: - Отзвук: + + Click here to show or hide the project notes window. In this window you can put down your project notes. + Эта кнопка показывает/прячет окно с заметками. В этом окне вы можете помещать любые комментарии к своей композиции. - Env Mod: - Мод Огиб: + + Show/hide controller rack + Показать/скрыть управление контроллерами - Decay: - Спад: + + Untitled + Неназванный - 303-es-que, 24dB/octave, 3 pole filter - 303-ий, 24дБ/октаву, 3-польный фильтр + + Recover session. Please save your work! + Восстановление сессии. Пожалуйста, сохраните свою работу! - Slide Decay: - Сдвиг спада: + + LMMS %1 + LMMS %1 - DIST: - ИСК: + + Recovered project not saved + Восстановленный проект не сохранён. - Saw wave - Зигзаг + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + Проект был восстановлен из предыдущей сессии. Сейчас он не сохранён и будет потерян, если его не сохранить. +Хотите сохранить его сейчас? - Click here for a saw-wave. - Сгенерировать зигзаг. + + Project not saved + Проект не сохранён - Triangle wave - Треугольная волна + + The current project was modified since last saving. Do you want to save it now? + Проект был изменён. Сохранить его сейчас? - Click here for a triangle-wave. - Сгенерировать треугольный сигнал. + + Open Project + Открыть проект - Square wave - Квадрат + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) - Click here for a square-wave. - Сгенерировать квадрат. + + Save Project + Сохранить проект - Rounded square wave - Волна скругленного квадрата + + LMMS Project + ЛММС Проект - Click here for a square-wave with a rounded end. - Создать квадратную волну закруглённую в конце. + + LMMS Project Template + Шаблон ЛММС Проекта - Moog wave - Муг волна + + Save project template + - Click here for a moog-like wave. - Сгенерировать волну похожую на муг. + + Overwrite default template? + Перезаписать обычный шаблон? - Sine wave - Синусоида + + This will overwrite your current default template. + Это перезапишет текущий обычный шаблон. - Click for a sine-wave. - Сгенерировать гармонический (синусоидальный) сигнал. + + Help not available + Справка недоступна - White noise wave - Белый шум + + Currently there's no help available in LMMS. +Please visit http://lmms.sf.net/wiki for documentation on LMMS. + Пока что справка для LMMS не написана. +Вероятно, Вы сможете найти нужные материалы на http://lmms.sf.net/wiki . - Click here for an exponential wave. - Генерировать экспоненциальный сигнал. + + Song Editor + Показать/скрыть музыкальный редактор - Click here for white-noise. - Сгенерировать белый шум. + + Beat+Bassline Editor + Показать/скрыть ритм-бас редактор - Bandlimited saw wave - + + Piano Roll + Показать/скрыть нотный редактор - Click here for bandlimited saw wave. - Нажать здесь для пилообразной волны с ограниченной полосой. + + Automation Editor + Показать/скрыть редактор автоматизации - Bandlimited square wave - + + FX Mixer + Показать/скрыть микшер ЭФ - Click here for bandlimited square wave. - Нажать здесь для квадратной волны с ограниченной полосой. + + Project Notes + Показать/скрыть заметки к проекту - Bandlimited triangle wave - + + Controller Rack + Показать/скрыть управление контроллерами - Click here for bandlimited triangle wave. - Нажать здесь для треуголной волны с ограниченной полосой. + + Volume as dBFS + - Bandlimited moog saw wave - + + Smooth scroll + Плавная прокрутка - Click here for bandlimited moog saw wave. - Нажать здесь для пилообразной муг (moog) волны с ограниченной полосой. + + Enable note labels in piano roll + Включить обозначение нот в музыкальном редакторе - malletsInstrument + MeterDialog - Hardness - Жёсткость + + + Meter Numerator + Шкала чисел - Position - Положение + + + Meter Denominator + Шкала делений - Modulator - Модулятор + + TIME SIG + ПЕРИОД + + + MeterModel - Crossfade - Переход + + Numerator + Числитель - ADSR - ADSR + + Denominator + Знаменатель + + + MidiController - Pressure - Давление + + MIDI Controller + Контроллер MIDI - Motion - Движение + + unnamed_midi_controller + нераспознанный миди контроллер + + + MidiImport - Speed - Скорость + + + Setup incomplete + установка не завершена - Bowed - Наклон + + You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. + Вы не установили SoundFont по умолчанию в параметрах (Правка->Настройки), поэтому после импорта миди файла звук воспроизводиться не будет. +Вам следует загрузить основной MiDi SoundFont, указать его в параметрах и попробовать снова. - Spread - Разброс + + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. + Вы не включили поддержку проигрывателя SoundFont2 при компиляции ЛММС, он используется для добавления основного звука в импортируемые Миди файлы, поэтому звука не будет после импорта этого миди файла. - Marimba - Маримба + + Track + Дорожка + + + MidiJack - Vibraphone - Вибрафон + + JACK server down + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) + JACK-сервер не доступен - Agogo - Дискотека + + The JACK server seems to be shuted down. + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) + JACK-сервер, похоже, не запущен. + + + MidiPort - Reso - Резо + + Input channel + Вход - Beats - Удары + + Output channel + Выход - Clump - Тяжёлая поступь + + Input controller + Контроллер входа - Glass - Стекло + + Output controller + Контроллер выхода - Vibrato gain - + + Fixed input velocity + Постоянная скорость ввода - Vibrato frequency - + + Fixed output velocity + Постоянная скорость вывода - Stick mix - + + Fixed output note + Постоянный вывод нот - LFO speed - Скорость LFO + + Output MIDI program + Программа для вывода MiDi - LFO depth - + + Base velocity + Базовая скорость - Wood 1 - + + Receive MIDI-events + Принимать события MIDI - Wood 2 - + + Send MIDI-events + Отправлять события MIDI + + + MidiSetupWidget - Two fixed - + + DEVICE + УСТРОЙСТВО + + + MonstroInstrument - Tubular bells - + + Osc 1 Volume + Осциллятор 1 громкость - Uniform bar - + + Osc 1 Panning + Осциллятор 1 баланс - Tuned bar - + + Osc 1 Coarse detune + - Tibetan bowl - + + Osc 1 Fine detune left + - - - malletsInstrumentView - Instrument - Инструмент + + Osc 1 Fine detune right + - Spread - Разброс + + Osc 1 Stereo phase offset + - Spread: - Разброс: + + Osc 1 Pulse width + - Hardness - Жёсткость + + Osc 1 Sync send on rise + - Hardness: - Жёсткость: + + Osc 1 Sync send on fall + - Position - Положение + + Osc 2 Volume + Осциллятор 2 громкость - Position: - Положение: + + Osc 2 Panning + Осциллятор 2 баланс - Modulator - Модулятор + + Osc 2 Coarse detune + - Modulator: - Модулятор: + + Osc 2 Fine detune left + - Crossfade - Переход + + Osc 2 Fine detune right + - Crossfade: - Переход: + + Osc 2 Stereo phase offset + - ADSR - ADSR + + Osc 2 Waveform + - ADSR: - ADSR: + + Osc 2 Sync Hard + - Pressure - Давление + + Osc 2 Sync Reverse + - Pressure: - Давление: + + Osc 3 Volume + Осциллятор 3 громкость - Speed - Скорость + + Osc 3 Panning + Осциллятор 3 баланс - Speed: - Скорость: + + Osc 3 Coarse detune + - Missing files - Файлы отсутствуют + + Osc 3 Stereo phase offset + - Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! - Похоже устновка Stk прошла не полностью. Пожалуйста, убедитесь, что пакет Stk полностью установлен! + + Osc 3 Sub-oscillator mix + - Vibrato gain - + + Osc 3 Waveform 1 + - Vibrato gain: - + + Osc 3 Waveform 2 + - Vibrato frequency - + + Osc 3 Sync Hard + - Vibrato frequency: - + + Osc 3 Sync Reverse + - Stick mix - + + LFO 1 Waveform + - Stick mix: - + + LFO 1 Attack + - LFO speed - Скорость LFO + + LFO 1 Rate + - LFO speed: - Скорость LFO: + + LFO 1 Phase + - LFO depth - + + LFO 2 Waveform + - LFO depth: - + + LFO 2 Attack + - - - manageVSTEffectView - - VST parameter control - Управление VST параметрами + + LFO 2 Rate + - Automated - Автоматизировано + + LFO 2 Phase + - Close - Закрыть + + Env 1 Pre-delay + - VST sync - + + Env 1 Attack + - - - manageVestigeInstrumentView - - VST plugin control - Управление VST плагином + + Env 1 Hold + - VST Sync - VST синхронизация + + Env 1 Decay + - Automated - Автоматизировано + + Env 1 Sustain + - Close - Закрыть + + Env 1 Release + - - - organicInstrument - Distortion - Искажение + + Env 1 Slope + - Volume - Громкость + + Env 2 Pre-delay + - - - organicInstrumentView - Distortion: - Искажение: + + Env 2 Attack + - Volume: - Громкость: + + Env 2 Hold + - Randomise - Случайно + + Env 2 Decay + - Osc %1 waveform: - Форма сигнала для осциллятора %1: + + Env 2 Sustain + - Osc %1 volume: - Громкость осциллятора %1: + + Env 2 Release + - Osc %1 panning: + + Env 2 Slope + Кривая 2 Наклон + + + + Osc2-3 modulation + + + + + Selected view + Выбранный вид + + + + Vol1-Env1 + + + + + Vol1-Env2 + + + + + Vol1-LFO1 + + + + + Vol1-LFO2 + + + + + Vol2-Env1 + + + + + Vol2-Env2 + + + + + Vol2-LFO1 + + + + + Vol2-LFO2 + + + + + Vol3-Env1 + + + + + Vol3-Env2 + + + + + Vol3-LFO1 + + + + + Vol3-LFO2 + + + + + Phs1-Env1 + + + + + Phs1-Env2 + + + + + Phs1-LFO1 + + + + + Phs1-LFO2 + + + + + Phs2-Env1 + + + + + Phs2-Env2 + + + + + Phs2-LFO1 + + + + + Phs2-LFO2 + + + + + Phs3-Env1 + + + + + Phs3-Env2 + + + + + Phs3-LFO1 + + + + + Phs3-LFO2 + + + + + Pit1-Env1 + + + + + Pit1-Env2 + + + + + Pit1-LFO1 + + + + + Pit1-LFO2 + + + + + Pit2-Env1 + + + + + Pit2-Env2 + + + + + Pit2-LFO1 + + + + + Pit2-LFO2 + + + + + Pit3-Env1 + + + + + Pit3-Env2 + + + + + Pit3-LFO1 + + + + + Pit3-LFO2 + + + + + PW1-Env1 + + + + + PW1-Env2 + + + + + PW1-LFO1 + + + + + PW1-LFO2 + + + + + Sub3-Env1 + + + + + Sub3-Env2 + + + + + Sub3-LFO1 + + + + + Sub3-LFO2 + + + + + + Sine wave + Синусоида + + + + Bandlimited Triangle wave + Ограниченная по частоте треугольная волна + + + + Bandlimited Saw wave + Ограниченная по частоте острая волна + + + + Bandlimited Ramp wave + Ограничение по частоте ниспадающая волна + + + + Bandlimited Square wave + Ограниченная по частоте квадратная волна + + + + Bandlimited Moog saw wave + Ограниченная по частоте Муг-зигзаг волна + + + + + Soft square wave + Сглаженная квадратная волна + + + + Absolute sine wave + + + + + + Exponential wave + Экспоненциальная волна + + + + White noise + Белый шум + + + + Digital Triangle wave + Цифровая треугольная волна + + + + Digital Saw wave + Цифровая острая волна + + + + Digital Ramp wave + + + + + Digital Square wave + Цифровая квадратная волна + + + + Digital Moog saw wave + Цифровая Муг острая волна + + + + Triangle wave + Треугольная волна + + + + Saw wave + Зигзаг + + + + Ramp wave + + + + + Square wave + Квадрат + + + + Moog saw wave + + + + + Abs. sine wave + + + + + Random + Случайно + + + + Random smooth + Случайное сглаживание + + + + MonstroView + + + Operators view + Операторский вид + + + + The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. + +Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. + Операторский вид содержит все операторы. Они включают и звучащие операторы (осцилляторы) и беззвучные операторы или модуляторы: Низко-частотные осцилляторы и огибающие. + +Регуляторы и другие виджеты в Операторском виде имеют свои подписи "Что это?", можно получить по ним более детальную справку таким образом. + + + + Matrix view + Матричный вид + + + + The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. + +The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. + +Each modulation target has 4 knobs, one for each modulator. By default the knobs are at 0, which means no modulation. Turning a knob to 1 causes that modulator to affect the modulation target as much as possible. Turning it to -1 does the same, but the modulation is inversed. + Матричный вид содержит матрицу модуляции. Здесь можно определить модуляционное отношение между разными операторами. Каждый слышимый оператор (осцилляторы 1-3) имеют 3-4 свойства, которые можно модулировать любыми модуляторами. Используя больше модуляций увеличивается нагрузка на процессор. + +Вид делится на цели модуляции, сгруппированные на целевой осциллятор. Доступные цели : громкость, тон, фаза, ширина пульсации и отношение с подчиненным (под-) осциллятором. Отметим что некоторые цели определены только для одного осциллятора. + +Каждая цель модуляции имеет 4 регулятора, один на каждый модулятор. По умолчанию регуляторы установлены на 0, то есть без модуляции. Включая регулятор на 1 ведёт к тому, что модулятор влияет на цель модуляции на столько на сколько возможно. Включая его на -1 делает то же, но с обратной модуляцией. + + + + + + Volume + Громкость + + + + + + Panning + Баланс + + + + + + Coarse detune + Грубая расстройка + + + + + + semitones + полутона + + + + + Finetune left + + + + + + + + cents + + + + + + Finetune right + + + + + + + Stereo phase offset + Сдвиг стерео фазы + + + + + + + + deg + град + + + + Pulse width + Длительность импульса + + + + Send sync on pulse rise + Выдача синхронизации по нарастанию импульса + + + + Send sync on pulse fall + Выдача синхронизации по спаду импульса + + + + Hard sync oscillator 2 + + + + + Reverse sync oscillator 2 + + + + + Sub-osc mix + + + + + Hard sync oscillator 3 + + + + + Reverse sync oscillator 3 + + + + + + + + Attack + Вступление + + + + + Rate + Частота выборки + + + + + Phase + + + + + + Pre-delay + Пре-дилэй + + + + + Hold + Удерживание + + + + + Decay + Затихание + + + + + Sustain + Выдержка + + + + + Release + Убывание + + + + + Slope + Фронт + + + + Mix Osc2 with Osc3 + Смешать Осц2 с Осц3 + + + + Modulate amplitude of Osc3 with Osc2 + Модулировать амплитуду осциллятора 3 сигналом с осц2 + + + + Modulate frequency of Osc3 with Osc2 + Модулировать частоту осциллятора 3 сигналом с осц2 + + + + Modulate phase of Osc3 with Osc2 + Модулировать фазу Осц3 осциллятором2 + + + + The CRS knob changes the tuning of oscillator 1 in semitone steps. + Регулятор CRS меняет настройку осциллятора 1 в размере полутона. + + + + The CRS knob changes the tuning of oscillator 2 in semitone steps. + Регулятор CRS меняет настройку осциллятора 2 в размере полутона. + + + + The CRS knob changes the tuning of oscillator 3 in semitone steps. + Регулятор CRS меняет настройку осциллятора 3 в размере полутона. + + + + + + + FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. + FTL и FTR меняют подстройку осциллятора для левого и правого канала соответственно. Они могут добавить стерео расстраивания осциллятора, которое расширяет стерео картину и создаёт иллюзию космоса. + + + + + + The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. + Регулятор SPO меняет фазовую разницу между левым и правым каналами. Высокая разница создаёт более широкую стерео картину. + + + + The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. + PW регулятор контролирует ширину пульсаций, также известную как рабочий цикл осциллятора 1. Осциллятор 1 это цифровой импульсный волновой генератор, он не воспроизводит сигнал с ограниченной полосой, это значит, что его можно использовать как слышимый осциллятор, но приведёт к наложению сигналов (или сглаживанию). Его можно использовать и как не слышимый источник синхронизирующего сигнала, для использования в синхронизации осцилляторов 2 и 3. + + + + Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + Посылать синхронизацию при повышении: при включении, сигнал синхронизации посылается каждый раз когда состояние осциллятора 1 меняется с низкого на высокое, т.е. когда амплитуда меняется от -1 до 1. +Тон осциллятора 1, фаза и ширина пульсаций может влиять на время синхронизации, но громкость не имеет эффекта. Сигнал синхронизации посылается независимо для левого и правого каналов. + + + + Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + Посылать синхронизацию при падении: при включении, сигнал синхронизации посылается каждый раз когда состояние осциллятора 1 меняется с выского на низкое, т.е. когда амплитуда меняется от 1 до -1. +Тон осциллятора 1, фаза и ширина пульсаций может влиять на время синхронизации, но громкость не имеет эффекта. Сигнал синхронизации посылается независимо для левого и правого каналов. + + + + + Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. + Жесткая синхр. : Каждый раз при получении осциллятором сигнала синхронизации от осциллятора 1, его фаза сбрасывается до 0 + его граница фазы, какой бы она ни была. + + + + + Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. + Обратная синхронизация: Каждый раз при получении сигнала синхронизации от осциллятора 1, амплитуда осцилятора переворачивается. + + + + Choose waveform for oscillator 2. + Выбрать форму волны для осциллятора 2. + + + + Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + Выберите форму волны для первого доп. осциллятора осциллятора 3. Осциллятор 3 может мягко переходить между двумя разными волнами. + + + + Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + Выберите форму волны для второго доп. осциллятора осциллятора 3. Осциллятор 3 может мягко переходить между двумя разными волнами. + + + + The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. + SUB меняет смешивание двух доп. осяцилляторов осциллятора 3. Каждый доп. осц. может быть установлен для создания разных волн и осциллятор 3 может мягко переходить между ними. Все входящие модуляции для осциллятора 3 применяются на оба доп.осц./волны одним и тем же образом. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +Mix mode means no modulation: the outputs of the oscillators are simply mixed together. + В дополнение к выделенным модуляторам Монстро позволяет выходу осциллятора 2 модулировать осцллятор 3. + +Смешанный (Mix) режим значит без модуляции: выходы осцилляторов просто смешиваются друг с другом. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. + В дополнение к выделенным модуляторам Монстро позволяет выходу осциллятора 2 модулировать осцллятор 3. + +AM режим значит Амплитуда Модуляции: Осциллятор 2 модулирует амплитуду (громкость) осциллятора 3. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. + В дополнение к выделенным модуляторам Монстро позволяет выходу осциллятора 2 модулировать осцллятор 3. + +FM (ЧМ) режим значит Частотная Модуляция: Осциллятор 2 модулирует частоту (pitch, тональность) осциллятора 3. Частота модуляции происходит в фазе модуляции, которая даёт более стабильный общий тон, чем "чистая" частотная модуляция. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. + В дополнение к выделенным модуляторам Монстро позволяет выходу осциллятора 2 модулировать осцллятор 3. + +PM (ФМ) режим значит фазовая модуляция: Осциллятор 2 модулирует фазу осциллятора 3. Это отличается от частотной модуляции тем, что изменения фаз не суммируются. + + + + Select the waveform for LFO 1. +"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + Выберите форму волны для LFO 1 (НизкоЧастотныйГенератор). +"Random" (Случайно) и "Random-smooth" (случайное сглаживание) - это специальные волны: они создают случаный сигнал, где частота LFO контролирует как часто изменяется состояние генератора (LFO). +Сглаженная версия переходит между этими состояниями с косинусоидальной интерплояцией. Эти случайные режимы могут быть использованы, чтобы дать "жизни" вашим настройкам - добавить немного аналоговой непредсказуемости... + + + + Select the waveform for LFO 2. +"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + Выберите форму волны для LFO 2 (НизкоЧастотныйГенератор). +"Random" (Случайно) и "Random-smooth" (случайное сглаживание) - это специальные волны: они создают случаный сигнал, где частота LFO контролирует как часто изменяется состояние генератора (LFO). +Сглаженная версия переходит между этими состояниями с косинусоидальной интерплояцией. Эти случайные режимы могут быть использованы, чтобы дать "жизни" вашим настройкам - добавить немного аналоговой непредсказуемости... + + + + + Attack causes the LFO to come on gradually from the start of the note. + Атака отвечает за плавность поведения LFO от начала ноты. + + + + + Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. + Rate (Частота) устанавливает скорость LFO, измеряемую в миллисекундах за цикл. Может синхронизироваться с темпом. + + + + + PHS controls the phase offset of the LFO. + PHS контролирует сдвиг фазы LFO (НЧГ). + + + + + PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. + PRE предзадержка, задерживает старт огибающей от начала ноты. 0 значит без задержки. + + + + + ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. + ATT атака контролирует как быстро огибающая наращивается на старте, измеряясь в милисекундах. Значение 0 значит мгновенно. + + + + + HOLD controls how long the envelope stays at peak after the attack phase. + HOLD (УДЕРЖ) контролирует как долго огибающая остаётся на пике после фазы атаки. + + + + + DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. + DEC (decay) затухание контролирует как быстро огибающая спадает с пикового значения, измеряется в милисекундах, как долго будет идти с пика до нуля. Реальное затухание может быть короче, если используется выдержка. + + + + + SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. + SUS (sustain) выдержка, контролирует уровень огибающей. Затухание фазы не пойдёт ниже этого уровня пока нота удерживается. + + + + + REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. + REL (release) отпуск контролирует как долго нота отпускается, измеряясь в долготе падения от пика до нуля. Реальный отпуск может быть короче, в зависимости от фазы, в которой нота отпущена. + + + + + The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. + Регулятор наклона контролирует кривую или образ огибающей. Значение 0 создаёт прямые подъёмы и спады. Отрицательные величины создают кривые с замедленным началом, быстрым пиком и снова замедленным спадом. Позитивные значения создают кривые которые начинаются и кончаются быстро, но долбше остаются на пиках. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modulation amount + Глубина модуляции + + + + MultitapEchoControlDialog + + + Length + Длина + + + + Step length: + Длина шага: + + + + Dry + Высушить + + + + Dry Gain: + + + + + Stages + + + + + Lowpass stages: + + + + + Swap inputs + Переставить входы местами + + + + Swap left and right input channel for reflections + Поменять вход левого и правого канала для отзвуков + + + + NesInstrument + + + Channel 1 Coarse detune + Канал 1 - грубая расстройка + + + + Channel 1 Volume + Громкость 1 канала + + + + Channel 1 Envelope length + Канал 1 - Длина огибающей + + + + Channel 1 Duty cycle + + + + + Channel 1 Sweep amount + + + + + Channel 1 Sweep rate + + + + + Channel 2 Coarse detune + + + + + Channel 2 Volume + Громкость 2 канала + + + + Channel 2 Envelope length + + + + + Channel 2 Duty cycle + + + + + Channel 2 Sweep amount + + + + + Channel 2 Sweep rate + + + + + Channel 3 Coarse detune + + + + + Channel 3 Volume + Громкость 3 канала + + + + Channel 4 Volume + Громкость 4 канала + + + + Channel 4 Envelope length + + + + + Channel 4 Noise frequency + + + + + Channel 4 Noise frequency sweep + + + + + Master volume + Основная громкость + + + + Vibrato + Вибрато + + + + NesInstrumentView + + + + + + Volume + Громкость + + + + + + Coarse detune + Грубая расстройка + + + + + + Envelope length + Длина огибающей + + + + Enable channel 1 + Включить канал 1 + + + + Enable envelope 1 + Включить кривую 1 + + + + Enable envelope 1 loop + + + + + Enable sweep 1 + + + + + + Sweep amount + Амплитуда биений + + + + + Sweep rate + Частота биений + + + + + 12.5% Duty cycle + 12.5% Рабочий цикл + + + + + 25% Duty cycle + 25% Рабочий цикл + + + + + 50% Duty cycle + 50% Рабочий цикл + + + + + 75% Duty cycle + 75% Рабочий цикл + + + + Enable channel 2 + Включить канал 2 + + + + Enable envelope 2 + Включить кривую 2 + + + + Enable envelope 2 loop + Включить повтор кривой 2 + + + + Enable sweep 2 + + + + + Enable channel 3 + + + + + Noise Frequency + Частота шума + + + + Frequency sweep + + + + + Enable channel 4 + + + + + Enable envelope 4 + + + + + Enable envelope 4 loop + + + + + Quantize noise frequency when using note frequency + + + + + Use note frequency for noise + Использовние частоты ноты для шума + + + + Noise mode + Режим шума + + + + Master Volume + Мастер-громкость + + + + Vibrato + Вибрато + + + + OscillatorObject + + + Osc %1 waveform + Форма сигнала осциллятора %1 + + + + Osc %1 harmonic + Осц %1 гармонический + + + + + Osc %1 volume + Громкость осциллятора %1 + + + + + Osc %1 panning + Стереобаланс для осциллятора %1 + + + + + Osc %1 fine detuning left + Подстройка левого канала осциллятора %1 тонкая + + + + Osc %1 coarse detuning + Подстройка осциллятора %1 грубая + + + + Osc %1 fine detuning right + Подстройка правого канала осциллятора %1 тонкая + + + + Osc %1 phase-offset + Сдвиг фазы для осциллятора %1 + + + + Osc %1 stereo phase-detuning + Подстройка стерео-фазы осциллятора %1 + + + + Osc %1 wave shape + Гладкость сигнала осциллятора %1 + + + + Modulation type %1 + Тип модуляции %1 + + + + PatchesDialog + + + Qsynth: Channel Preset + + + + + Bank selector + Выбор банка + + + + Bank + Банк + + + + Program selector + Выбор программ + + + + Patch + Патч + + + + Name + Имя + + + + OK + ОК + + + + Cancel + Отмена + + + + PatmanView + + + Open other patch + Открыть другой патч + + + + Click here to open another patch-file. Loop and Tune settings are not reset. + Нажмите чтобы открыть другой патч-файл. Цикличность и настройки при этом сохранятся. + + + + Loop + Повтор + + + + Loop mode + Режим повтора + + + + Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. + Здесь включается/выключается режим повтора, при включёнии PatMan будет использовать информацию о повторе из файла. + + + + Tune + Подстроить + + + + Tune mode + Тип подстройки + + + + Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. + Здесь включается/выключается режим подстройки. Если он включён, то PatMan изменит запись так, чтобы она совпадала по частоте с нотой. + + + + No file selected + Не выбран файл + + + + Open patch file + Открыть патч-файл + + + + Patch-Files (*.pat) + Патч-файлы (*.pat) + + + + PatternView + + + use mouse wheel to set velocity of a step + + + + + double-click to open in Piano Roll + Двойной щелчок открывает в Редакторе Нот + + + + Open in piano-roll + Открыть в редакторе нот + + + + Clear all notes + Очистить все ноты + + + + Reset name + Сбросить название + + + + Change name + Переименовать + + + + Add steps + Добавить такты + + + + Remove steps + Удалить такты + + + + Clone Steps + Клонировать такты + + + + PeakController + + + Peak Controller + Контроллер вершин + + + + Peak Controller Bug + Контроллер вершин с багом + + + + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. + Из-за ошибки в старой версии LMMS контроллеры вершин не могут правильно подключаться. Пж. убедитесь, что контроллеры вершин правильно подсоединены и пересохраните этот файл, извините, за причинённые неудобства. + + + + PeakControllerDialog + + + PEAK + ПИК + + + + LFO Controller + Контроллер LFO + + + + PeakControllerEffectControlDialog + + + BASE + БАЗА + + + + Base amount: + Базовое значение: + + + + AMNT + ГЛУБ + + + + Modulation amount: + Глубина модуляции: + + + + MULT + МНОЖ + + + + Amount Multiplicator: + Величина множителя: + + + + ATCK + ВСТУП + + + + Attack: + Вступление: + + + + DCAY + СПАД + + + + Release: + Убывание: + + + + TRSH + ПОР + + + + Treshold: + Порог: + + + + PeakControllerEffectControls + + + Base value + Опорное значение + + + + Modulation amount + Глубина модуляции + + + + Attack + Вступление + + + + Release + Убывание + + + + Treshold + Порог + + + + Mute output + Заглушить вывод + + + + Abs Value + Абс значение + + + + Amount Multiplicator + Величина множителя + + + + PianoRoll + + + Note Velocity + Громкость нот + + + + Note Panning + Стереофония нот + + + + Mark/unmark current semitone + Отметить/Снять отметку с текущего полутона + + + + Mark/unmark all corresponding octave semitones + Отметить/Снять отметку со всех соответствующих октав полутонов + + + + Mark current scale + Отметить текущий подъём + + + + Mark current chord + Отметить текущий аккорд + + + + Unmark all + Снять выделение + + + + Select all notes on this key + Выбрать все ноты по этой кнопке + + + + Note lock + Фиксация нот + + + + Last note + По посл. ноте + + + + No scale + Без подъёма + + + + No chord + Убрать аккорды + + + + Velocity: %1% + Громкость %1% + + + + Panning: %1% left + Баланс: %1% лево + + + + Panning: %1% right + Баланс: %1% право + + + + Panning: center + Баланс: центр + + + + Please open a pattern by double-clicking on it! + Откройте мелодию с помощью двойного щелчка мышью! + + + + + Please enter a new value between %1 and %2: + Введите новое значение от %1 до %2: + + + + PianoRollWindow + + + Play/pause current pattern (Space) + Игра/Пауза текущей мелодии (Пробел) + + + + Record notes from MIDI-device/channel-piano + Записать ноты с музыкального инструмента (MIDI)/канала + + + + Record notes from MIDI-device/channel-piano while playing song or BB track + Записать ноты с цифрового музыкального инструмента (MIDI) во время воспроизведения композиции или дорожки Ритм-Баса + + + + Stop playing of current pattern (Space) + Остановить воспроизведение текущей мелодии (Пробел) + + + + Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. + Нажмите здесь чтобы проиграть текущую мелодию. Это может пригодиться при её редактировании. По окончании мелодии воспроизведение начнётся сначала. + + + + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. + Нажмите эту кнопку, если вы хотите записать ноты с устройства MIDI или виртуального синтезатора соответствующего канала. Позже вы сможете отредактировать записанную мелодию. + + + + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. + Нажмите эту кнопку, если вы хотите записать ноты с устройства MIDI или виртуального синтезатора соответствующего канала. Во время записи все ноты записываются в эту мелодию, и вы будете слышать композицию или РБ дорожку на заднем плане. + + + + Click here to stop playback of current pattern. + Нажмите здесь, если вы хотите остановить воспроизведение текущей мелодии. + + + + Edit actions + Правка: + + + + Draw mode (Shift+D) + Режим рисования (Shift+D) + + + + Erase mode (Shift+E) + Режим стирания (Shift+E) + + + + Select mode (Shift+S) + Режим выбора нот (Shift+S) + + + + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + Режим рисования нот, в нём вы можете добавлять/перемещать и изменять длительность одиночных нот. Это режим по умолчанию и используется большую часть времени. +Для включения этого режима можно использовать комбинацию клавиш Shift+D, удерживайте %1 для временного переключения в режим выбора. + + + + Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. + Режим стирания. В этом режиме вы можете стирать ноты. Для включения этого режима можно использовать комбинацию клавиш Shift+E. + + + + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Режим выделения. В этом режиме можно выделять ноты, можно также удерживать %1 в режиме рисования, чтобы можно было на время войти в режим выделения. + + + + Pitch Bend mode (Shift+T) + + + + + Click here and Pitch Bend mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + Нажмите здесь для активации Pitch Blend режима. Вы сможете кликнуть на ноту, чтобы начать автоматическией детюн. Можно использовать это для "скольжения" от одной ноты к другой. Можно включить этот режим при помощи Shift + T. + + + + Quantize + + + + + Copy paste controls + Копировать-вставить управление + + + + Cut selected notes (%1+X) + Переместить выделенные ноты в буфер (%1+X) + + + + Copy selected notes (%1+C) + Копировать выделенные ноты в буфер (%1+X) + + + + Paste notes from clipboard (%1+V) + Вставить ноты из буфера (%1+V) + + + + Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При нажатии на эту кнопку выделеные ноты будут вырезаны в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". + + + + Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При нажатии на эту кнопку выделеные ноты будут скопированы в буфер. Позже вы можете вставить их в любое место любой мелодии с помощью кнопки "Вставить". + + + + Click here and the notes from the clipboard will be pasted at the first visible measure. + При нажатии на эту кнопку ноты из буфера будут вставлены в первый видимый такт. + + + + Timeline controls + Управление временем + + + + Zoom and note controls + Контроль нот и увеличения. + + + + This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. + Этим контролируется масштаб оси. Это может быть полезно для специальных задач. Для обычного редактирования, масштаб следует устанавливать по наименьшей ноте. + + + + The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. + "Q" обозначает квантизацию и контролирует размер нотной сетки и контрольные точки притяжения. С меньшей величиной квантизации, можно рисовать короткие ноты в редаторе нот и более точно контролировать точки в Редакторе Автоматизации. + + + + This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited + Позволяет выбрть длину новой ноты. "Последняя Нота" значит, что LMMS будет использовать длину ноты, изменённой в последний раз + + + + The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! + Функция напрямую связана с контекстным меню на виртуальной клавиатуре слева в нотном редакторе. После того, как выбран масштаб в выпадающем меню, можно кликнуть правой кнопкой в виртуальной клавиатуре и выбрать "Mark Current Scale" (Отметить текущий масштаб). LMMS подсветит все ноты лежащие в выбранном масштабе для выбранной клавиши! + + + + Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + Позволяет выбрать аккорд, который LMMS затем сможет нарисовать или подсветить. В этом меню можно найти ниболее популярные аккорды. После того, как вы выбрали аккорд, кликните в любом месте, чтобы поставить его и правым кликом по виртуальной клавиатуре открывается контекстное меню и подсветка аккорда. Для возврата в режим одной ноты нужно выбрать "Без аккорда" в этом выпадающем меню. + + + + + Piano-Roll - %1 + Нотный редактор - %1 + + + + + Piano-Roll - no pattern + Пианоролл — нет шаблона + + + + PianoView + + + Base note + Опорная нота + + + + Plugin + + + Plugin not found + Модуль не найден + + + + The plugin "%1" wasn't found or could not be loaded! +Reason: "%2" + Модуль «%1» отсутствует либо не может быть загружен! +Причина: «%2» + + + + Error while loading plugin + Ошибка загрузки модуля + + + + Failed to load plugin "%1"! + Не получилось загрузить модуль «%1»! + + + + PluginBrowser + + + Instrument Plugins + Плагины инструментов + + + + Instrument browser + Обзор инструментов + + + + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. + Вы можете переносить нужные вам инструменты из этой панели в музыкальный, ритм-бас редактор или в существующую дорожку инструмента. + + + + PluginFactory + + + Plugin not found. + Плагин не найден + + + + LMMS plugin %1 does not have a plugin descriptor named %2! + ЛММС плагин %1 не имеет описания плагина с именем %2! + + + + ProjectNotes + + + Project Notes + Показать/скрыть заметки к проекту + + + + Enter project notes here + Напишите заметки, касающиеся проекта здесь + + + + Edit Actions + Правка + + + + &Undo + &U Отменить + + + + %1+Z + %1+Z + + + + &Redo + &R Повторить + + + + %1+Y + %1+Y + + + + &Copy + &C Копировать + + + + %1+C + %1+C + + + + Cu&t + &t Вырезать + + + + %1+X + %1+X + + + + &Paste + &P Вставить + + + + %1+V + %1+V + + + + Format Actions + Форматирование + + + + &Bold + &b Полужирный + + + + %1+B + %1+B + + + + &Italic + &i Курсив + + + + %1+I + %1+I + + + + &Underline + &U Подчеркнутый + + + + %1+U + %1+U + + + + &Left + &L По левому краю + + + + %1+L + %1+L + + + + C&enter + По &центру + + + + %1+E + + + + + &Right + + + + + %1+R + + + + + &Justify + &Выравнивать + + + + %1+J + + + + + &Color... + &Цвет... + + + + ProjectRenderer + + + WAV-File (*.wav) + Файл WAV (*.wav) + + + + Compressed OGG-File (*.ogg) + Сжатый файл OGG (*.ogg) + + + FLAC-File (*.flac) + + + + + Compressed MP3-File (*.mp3) + + + + + QWidget + + + + + Name: + Название: + + + + + Maker: + Создатель: + + + + + Copyright: + Правообладатель: + + + + + Requires Real Time: + Требуется обработка в реальном времени: + + + + + + + + + Yes + Да + + + + + + + + + No + Нет + + + + + Real Time Capable: + Работа в реальном времени: + + + + + In Place Broken: + Вместо сломанного: + + + + + Channels In: + Каналы в: + + + + + Channels Out: + Каналы из: + + + + File: %1 + Файл: %1 + + + + File: + Файл: + + + + RenameDialog + + + Rename... + Переименовать... + + + + ReverbSCControlDialog + + + Input + Ввод + + + + Input Gain: + Входная мощность: + + + + Size + Размер + + + + Size: + Размер: + + + + Color + Цвет + + + + Color: + Цвет: + + + + Output + Вывод + + + + Output Gain: + Выходная мощность: + + + + ReverbSCControls + + + Input Gain + Входная мощность + + + + Size + Размер + + + + Color + Цвет + + + + Output Gain + Выходная мощность + + + + SampleBuffer + + + Fail to open file + Не удается открыть файл + + + + Audio files are limited to %1 MB in size and %2 minutes of playing time + + + + + Open audio file + Открыть звуковой файл + + + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + Все аудио файлы (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + + + + Wave-Files (*.wav) + Файлы Wave (*.wav) + + + + OGG-Files (*.ogg) + Файлы OGG (*.ogg) + + + + DrumSynth-Files (*.ds) + Файлы DrumSynth (*.ds) + + + + FLAC-Files (*.flac) + Файлы FLAC (*.flac) + + + + SPEEX-Files (*.spx) + Файлы SPEEX (*.spx) + + + + VOC-Files (*.voc) + Файлы VOC (*.voc) + + + + AIFF-Files (*.aif *.aiff) + Файлы AIFF (*.aif *.aiff) + + + + AU-Files (*.au) + Файлы AU (*.au) + + + + RAW-Files (*.raw) + Файлы RAW (*.raw) + + + + SampleTCOView + + + double-click to select sample + Выберите запись двойным нажатием мыши + + + + Delete (middle mousebutton) + Удалить (средняя кнопка мыши) + + + + Cut + Вырезать + + + + Copy + Копировать + + + + Paste + Вставить + + + + Mute/unmute (<%1> + middle click) + Заглушить/включить (<%1> + средняя кнопка мыши) + + + + SampleTrack + + + Volume + Громкость + + + + Panning + Баланс + + + + + Sample track + Дорожка записи + + + + SampleTrackView + + + Track volume + Громкость дорожки + + + + Channel volume: + Громкость канала: + + + + VOL + ГРОМ + + + + Panning + Баланс + + + + Panning: + Баланс: + + + + PAN + БАЛ + + + + SetupDialog + + + Setup LMMS + Настройка LMMS + + + + + General settings + Общие параметры + + + + BUFFER SIZE + РАЗМЕР БУФЕРА + + + + + Reset to default-value + Восстановить значение по умолчанию + + + + MISC + РАЗНОЕ + + + + Enable tooltips + Включить подсказки + + + + Show restart warning after changing settings + Показывать предупреждение о перезапуске при изменении настроек + + + + Display volume as dBFS + Отображать громкость в децибелах + + + + Compress project files per default + По умолчанию сжимать файлы проектов + + + + One instrument track window mode + Режим окна одной инструментальной дорожки + + + + HQ-mode for output audio-device + Режим высокого качества для устройства вывода звука + + + + Compact track buttons + Ужать кнопки дорожки + + + + Sync VST plugins to host playback + Синхронизировать VST плагины с хостом воспроизведения + + + + Enable note labels in piano roll + Включить обозначение нот в музыкальном редакторе + + + + Enable waveform display by default + Включить отображение формы звуков по умолчанию + + + + Keep effects running even without input + Продолжать работу эффектов даже без входящего сигнала + + + + Create backup file when saving a project + Создать запасной файл при сохранении проекта + + + + Reopen last project on start + Открыть последний проект на старте + + + + Use built-in NaN handler + + + + + PLUGIN EMBEDDING + + + + + No embedding + Не встраивать + + + + Embed using Qt API + Встроить с использованием QT API + + + + Embed using native Win32 API + Встроить с использованием Win32 API + + + + Embed using XEmbed protocol + Встроить с использованием протокола XEmbed + + + + LANGUAGE + ЯЗЫК + + + + + Paths + Пути + + + + Directories + Папки + + + + LMMS working directory + Рабочий каталог LMMS + + + + Themes directory + Папка тем + + + + Background artwork + Фоновое изображение + + + + VST-plugin directory + Каталог модулей VST + + + + GIG directory + Папка GIG + + + + SF2 directory + Папка SF2 + + + + LADSPA plugin directories + Папка плагинов LADSPA + + + + STK rawwave directory + Каталог STK rawwave + + + + Default Soundfont File + Основной Soundfont файл + + + + + Performance settings + Параметры производительности + + + + Auto save + Автосохранение + + + + Enable auto-save + Включить автосохранение + + + + Allow auto-save while playing + Разрешить автосохранение во время воспроизведения + + + + UI effects vs. performance + Визуальные эффекты/производительность + + + + Smooth scroll in Song Editor + Плавная прокрутка в музыкальном редакторе + + + + Show playback cursor in AudioFileProcessor + Показывать указатель воспроизведения в процессоре аудио файлов (AFP) + + + + + Audio settings + Параметры звука + + + + AUDIO INTERFACE + ЗВУКОВАЯ СИСТЕМА + + + + + MIDI settings + Параметры MIDI + + + + MIDI INTERFACE + MIDI СИСТЕМА + + + + OK + ОК + + + + Cancel + Отменить + + + + Restart LMMS + Перезапустить LMMS + + + + Please note that most changes won't take effect until you restart LMMS! + Учтите, что большинство настроек не вступят в силу до перезапуска ЛММС! + + + + Frames: %1 +Latency: %2 ms + Фрагментов: %1 +Отклик: %2 + + + + Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. + Здесь вы можете настроить размер внутреннего звукового буфера LMMS. Меньшие значения дают меньшее время отклика программы, но повышают потребление ресурсов - это особенно заметно на старых машинах и системах, ядро которых не поддерживает приоритета реального времени. Если наблюдается прерывистый звук, попробуйте увеличить размер буфера. + + + + Choose LMMS working directory + Выбор рабочего каталога LMMS + + + + Choose your GIG directory + Выберите вашу папку GIG + + + + Choose your SF2 directory + Выберите вашу папку SF2 + + + + Choose your VST-plugin directory + Выбор своего каталога для модулей VST + + + + Choose artwork-theme directory + Выбор каталога с темой оформления для LMMS + + + + Choose LADSPA plugin directory + Выбор каталога с модулями LADSPA + + + + Choose STK rawwave directory + Выбор каталога STK rawwave + + + + Choose default SoundFont + Выбрать главный SoundFont + + + + Choose background artwork + Выбрать фоновое изображение + + + + minutes + Минуты + + + + minute + Минута + + + + Disabled + Отключено + + + + Auto-save interval: %1 + Интервал автосорхранения: %1 + + + + Set the time between automatic backup to %1. +Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. + Установить время между автоматическим бэкапом на %1. Не забывайте сохранять проект вручную. + + + + Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. + Пожалуйста, выберите желаемую звуковую систему. В зависимости от конфигурации во время компилирования программы вы можете использовать ALSA, JACK, OSS и другие. В нижней части окна настройки можно задать специфические параметры выбранной системы. + + + + Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. + Пожалуйста, выберите интерфейс MIDI. В зависимости от конфигурации во время компилирования программы вы можете использовать ALSA, OSS и другие. В нижней части окна настройки можно задать специфические параметры выбранного интерфейса. + + + + Song + + + Tempo + Темп + + + + Master volume + Основная громкость + + + + Master pitch + Основная тональность + + + + LMMS Error report + Отчет об ошибке LMMS + + + + Project saved + Проект сохранён + + + + The project %1 is now saved. + Проект %1 сохранён. + + + + Project NOT saved. + Проект НЕ СОХРАНЁН. + + + + The project %1 was not saved! + Проект %1 не сохранён! + + + + Import file + Импорт файла + + + + MIDI sequences + MiDi последовательности + + + + Hydrogen projects + Hydrogen проекты + + + + All file types + Все типы файлов + + + + + Empty project + Пустой проект + + + + + This project is empty so exporting makes no sense. Please put some items into Song Editor first! + Проект ничего не содержит, так что и экспортировать нечего. Сначала добавьте хотя бы одну дорожку в музыкальном редакторе! + + + + Select directory for writing exported tracks... + Выберите папку для записи экспортированных дорожек... + + + + + untitled + Неназванное + + + + + Select file for project-export... + Выбор файла для экспорта проекта... + + + + Save project + Сохранить проект + + + + MIDI File (*.mid) + MIDI-файл (*.mid) + + + + The following errors occured while loading: + Следующие ошибки возникли при загрузке: + + + + SongEditor + + + Could not open file + Не могу открыть файл + + + + Could not open file %1. You probably have no permissions to read this file. + Please make sure to have at least read permissions to the file and try again. + Невозможно открыть файл %1, вероятно, нет разрешений на его чтение. +Пж. убедитесь, что есть по крайней мере права на чтение этого файла и попробуйте ещё раз. + + + + Could not write file + Не могу записать файл + + + + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. + Невозможно открыть %1 для записи, возможно, нет разрешений на запись в этот файл, пж. удостоверьтесь, что есть доступ к этому файлу и попробуйте снова. + + + + Error in file + Ошибка в файле + + + + The file %1 seems to contain errors and therefore can't be loaded. + Файл %1 возможно содержит ошибки из-за которых не может загрузиться. + + + + Version difference + Версия отличается + + + + This %1 was created with LMMS %2. + %1 был создан в LMMS %2. + + + + template + шаблон + + + + project + проект + + + + Tempo + Темп + + + + TEMPO/BPM + ТЕМП/BPM + + + + tempo of song + Темп музыки + + + + The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). + Это значение задаёт темп музыки в ударах в минуту (англ. аббр. BPM). На каждый такт приходится четыре удара, так что темп в ударах в минуту фактически указывает, сколько четвертей такта проигрывается за минуту (или, что то же, количество тактов, проигрываемых за четыре минуты). + + + + High quality mode + Высокое качество + + + + + Master volume + Основная громкость + + + + master volume + основная громкость + + + + + Master pitch + Основная тональность + + + + master pitch + основная тональность + + + + Value: %1% + Значение: %1% + + + + Value: %1 semitones + Значение: %1 полутон(а/ов) + + + + SongEditorWindow + + + Song-Editor + Музыкальный редактор + + + + Play song (Space) + Начать воспроизведение (Пробел) + + + + Record samples from Audio-device + Записать сэмпл со звукового устройства + + + + Record samples from Audio-device while playing song or BB track + Записать сэмпл с аудио-устройства во время воспроизведения в музыкальном или ритм/бас редакторе + + + + Stop song (Space) + Остановить воспроизведение (Пробел) + + + + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. + Нажмите, чтобы прослушать созданную мелодию. Воспроизведение начнётся с позиции курсора (зелёный треугольник); вы можете двигать его во время проигрывания. + + + + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. + Нажмите сюда, если вы хотите остановить воспроизведение мелодии. Курсор при этом будет установлен на начало композиции. + + + + Track actions + Действия трека + + + + Add beat/bassline + Добавить ритм/бас + + + + Add sample-track + Добавить дорожку записи + + + + Add automation-track + Добавить дорожку автоматизации + + + + Edit actions + Правка: + + + + Draw mode + Режим рисования + + + + Edit mode (select and move) + Правка (выделение/перемещение) + + + + Timeline controls + Управление временем + + + + Zoom controls + Приблизить управление + + + + SpectrumAnalyzerControlDialog + + + Linear spectrum + Линейный спектр + + + + Linear Y axis + Линейная ось ординат (Y) + + + + SpectrumAnalyzerControls + + + Linear spectrum + Линейный спектр + + + + Linear Y axis + Линейная ось ординат (Y) + + + + Channel mode + Режим канала + + + + SubWindow + + + Close + Закрыть + + + + Maximize + Развернуть + + + + Restore + Восстановить + + + + TabWidget + + + + Settings for %1 + Настройки для %1 + + + + TempoSyncKnob + + + + Tempo Sync + Синхронизация темпа + + + + No Sync + Синхронизации нет + + + + Eight beats + Восемь ударов (две ноты) + + + + Whole note + Целая нота + + + + Half note + Полунота + + + + Quarter note + Четверть ноты + + + + 8th note + Восьмая ноты + + + + 16th note + 1/16 ноты + + + + 32nd note + 1/32 ноты + + + + Custom... + Своя... + + + + Custom + Своя + + + + Synced to Eight Beats + Синхро по 8 ударам + + + + Synced to Whole Note + Синхро по целой ноте + + + + Synced to Half Note + Синхро по половине ноты + + + + Synced to Quarter Note + Синхро по четверти ноты + + + + Synced to 8th Note + Синхро по 1/8 ноты + + + + Synced to 16th Note + Синхро по 1/16 ноты + + + + Synced to 32nd Note + Синхро по 1/32 ноты + + + + TimeDisplayWidget + + + click to change time units + нажми для изменения единиц времени + + + + MIN + МИН + + + + SEC + СЕК + + + + MSEC + мСЕК + + + + BAR + ДЕЛЕНИЕ + + + + BEAT + БИТ + + + + TICK + ТИК + + + + TimeLineWidget + + + Enable/disable auto-scrolling + Вкл/выкл автопрокрутку + + + + Enable/disable loop-points + Вкл/выкл точки петли + + + + After stopping go back to begin + После остановки переходить к началу + + + + After stopping go back to position at which playing was started + После остановки переходить к месту, с которого началось воспроизведение + + + + After stopping keep position + Оставаться на месте остановки + + + + + Hint + Подсказка + + + + Press <%1> to disable magnetic loop points. + Нажмите <%1>, чтобы убрать прилипание точек петли. + + + + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + Зажмите <Shift> чтобы сдвинуть начало точек петли; Нажмите <%1>, чтобы убрать прилипание точек петли. + + + + Track + + + Mute + Тихо + + + + Solo + Соло + + + + TrackContainer + + + Couldn't import file + Не могу импортировать файл + + + + Couldn't find a filter for importing file %1. +You should convert this file into a format supported by LMMS using another software. + Не могу найти фильтр для импорта файла %1. +Для подключения этого файла преобразуйте его в формат, поддерживаемый LMMS. + + + + Couldn't open file + Не могу открыть файл + + + + Couldn't open file %1 for reading. +Please make sure you have read-permission to the file and the directory containing the file and try again! + Не могу открыть файл %1 для записи. +Проверьте, обладаете ли вы правами на запись в выбранный файл и содержащий его каталог и попробуйте снова! + + + + Loading project... + Чтение проекта... + + + + + Cancel + Отменить + + + + + Please wait... + Подождите, пожалуйста... + + + + Loading cancelled + Загрузка отменена. + + + + Project loading was cancelled. + Загрузка проекта была отменена. + + + + Loading Track %1 (%2/Total %3) + + + + + Importing MIDI-file... + Импортирую файл MIDI... + + + + TrackContentObject + + + Mute + Тихо + + + + TrackContentObjectView + + + Current position + Текущая позиция + + + + + Hint + Подсказка + + + + Press <%1> and drag to make a copy. + Нажмите <%1> и тащите мышью, чтобы создать копию. + + + + Current length + Текущая длительность + + + + Press <%1> for free resizing. + Для свободного изменения размера нажмите <%1>. + + + + + %1:%2 (%3:%4 to %5:%6) + %1:%2 (от %3:%4 до %5:%6) + + + + Delete (middle mousebutton) + Удалить (средняя кнопка мыши) + + + + Cut + Вырезать + + + + Copy + Копировать + + + + Paste + Вставить + + + + Mute/unmute (<%1> + middle click) + Тихо/громко (<%1> + middle click) + + + + TrackOperationsWidget + + + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Зажмите <Сtrl> и нажимайте мышь во время движения, чтобы начать новую переброску. + + + + Actions for this track + Действия для этой дорожки + + + + Mute + Тихо + + + + + Solo + Соло + + + + Mute this track + Заглушить эту дорожку + + + + Clone this track + Клонировать дорожку + + + + Remove this track + Удалить дорожку + + + + Clear this track + Очистить эту дорожку + + + + FX %1: %2 + ЭФ %1: %2 + + + + Assign to new FX Channel + Назначить на другой канал ЭФфектов + + + + Turn all recording on + Включить всё на запись + + + + Turn all recording off + Выключить всю запись + + + + TripleOscillatorView + + + Use phase modulation for modulating oscillator 1 with oscillator 2 + Модулировать фазу осциллятора 2 сигналом с 1 + + + + Use amplitude modulation for modulating oscillator 1 with oscillator 2 + Модулировать амплитуду осциллятора 2 сигналом с первого + + + + Mix output of oscillator 1 & 2 + Смешать выводы 1 и 2 осцилляторов + + + + Synchronize oscillator 1 with oscillator 2 + Синхронизировать первый осциллятор по второму + + + + Use frequency modulation for modulating oscillator 1 with oscillator 2 + Модулировать частоту осциллятора 2 сигналом с 1 + + + + Use phase modulation for modulating oscillator 2 with oscillator 3 + Модулировать фазу осциллятора 3 сигналом с 2 + + + + Use amplitude modulation for modulating oscillator 2 with oscillator 3 + Модулировать амплитуду осциллятора 3 сигналом с 2 + + + + Mix output of oscillator 2 & 3 + Совместить вывод осцилляторов 2 и 3 + + + + Synchronize oscillator 2 with oscillator 3 + Синхронизировать осциллятор 2 и 3 + + + + Use frequency modulation for modulating oscillator 2 with oscillator 3 + Модулировать частоту осциллятора 3 сигналом со 2 + + + + Osc %1 volume: + Громкость осциллятора %1: + + + + With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. + Эта ручка устанавливает громкость осциллятора %1. Если 0, то осциллятор выключается, иначе будет слышно настолько громко , как тут установлено. + + + + Osc %1 panning: Баланс для осциллятора %1: - cents - сотые + + With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. + Регулятор стереобаланса осциллятора %1. Величина -100 обозначает, что 100% сигнала идёт в левый канал, а 100 - в правый. + + + + Osc %1 coarse detuning: + Грубая подстройка осциллятора %1: + + + + semitones + полутон[а,ов] + + + + With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. + Грубая регулировка подстройки осциллятора %1. Возможна подстройка до 24 полутонов (до 2 октавы) вверх и вниз. Полезно для создания аккордов. + + + + Osc %1 fine detuning left: + Точная подстройка левого канала осциллятора %1: + + + + + cents + Проценты + + + + With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + Эта ручка устанавливает точную подстройку для левого канала осциллятора %1. Подстройка задаётся в диапазоне от -100 сотых до +100 сотых. Это полезно для создания "сочных" звуков. + + + + Osc %1 fine detuning right: + Точная подстройка правого канала осциллятора %1: + + + + With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + Эта ручка устанавливает точную подстройку для правого канала осциллятора %1. Подстройка задаётся в диапазоне от -100 сотых до +100 сотых. Это полезно для создания "сочных" звуков. + + + + Osc %1 phase-offset: + Сдвиг фазы осциллятора %1: + + + + + degrees + градусы + + + + With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + Эта ручка устанавливает начальную фазу осциллятора %1, т. е. точку, с которой осциллятор начинает вырабатывать сигнал. Например, если вы задали синусоидальную форму сигнала и начальную фазу 180º, волна сначала пойдёт вниз, а не вверх. То же для меандра (сигнала прямоугольной формы). + + + + Osc %1 stereo phase-detuning: + Подстройка стерео фазы осциллятора %1: + + + + With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. + Эта ручка устанавливает фазовую подстройку осциллятора %1 между каналами, то есть разность фаз между левым и правым каналами. Это удобно для создания расширения стереоэффектов. + + + + Use a sine-wave for current oscillator. + Генерировать гармонический (синусоидальный) сигнал. + + + + Use a triangle-wave for current oscillator. + Генерировать треугольный сигнал. + + + + Use a saw-wave for current oscillator. + Генерировать зигзагообразный сигнал. + + + + Use a square-wave for current oscillator. + Генерировать квадрат (меандр). + + + + Use a moog-like saw-wave for current oscillator. + Использовать муг-зигзаг для этого осциллятора. + + + + Use an exponential wave for current oscillator. + Использовать экспоненциальный сигнал для этого осциллятора. + + + + Use white-noise for current oscillator. + Генерировать белый шум. + + + + Use a user-defined waveform for current oscillator. + Задать форму сигнала. + + + + VersionedSaveDialog + + + Increment version number + Увеличивающийся номер версии + + + + Decrement version number + Понижающийся номер версии + + + + already exists. Do you want to replace it? + уже существует. Хотите перезаписать? + + + + VestigeInstrumentView + + + Open other VST-plugin + Открыть другой VST плагин + + + + Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. + Открыть другой модуль VST. После нажатия на кнопку появится стандартный диалог выбора файла, где вы сможете выбрать нужный модуль. + + + + Control VST-plugin from LMMS host + Управление VST плагином через LMMS хост + + + + Click here, if you want to control VST-plugin from host. + Нажмите здесь, для контроля VST плагином через хост. + + + + Open VST-plugin preset + Открыть предустановку VST плагина + + + + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + Открыть другую .fxp . fxb предустановку VST. + + + + Previous (-) + Предыдущий <-> + + + + + Click here, if you want to switch to another VST-plugin preset program. + Переключение на другую предустановку программы VST плагина. + + + + Save preset + Сохранить предустановку + + + + Click here, if you want to save current VST-plugin preset program. + Сохранить текущую предустановку программы VST плагина. + + + + Next (+) + Следующий <+> + + + + Click here to select presets that are currently loaded in VST. + Выбор из уже загруженных в VST предустановок. + + + + Show/hide GUI + Показать/скрыть интерфейс + + + + Click here to show or hide the graphical user interface (GUI) of your VST-plugin. + Скрывает/показывает графический пользовательский интерфейс (GUI) выбранного модуля VST. + + + + Turn off all notes + Выключить все ноты + + + + Open VST-plugin + Открыть модуль VST + + + + DLL-files (*.dll) + Бибилиотеки DLL (*.dll) + + + + EXE-files (*.exe) + Программы EXE (*.exe) + + + + No VST-plugin loaded + Модуль VST не загружен + + + + Preset + Предустановка + + + + by + от + + + + - VST plugin control + - управление VST плагином + + + + VisualizationWidget + + + click to enable/disable visualization of master-output + Нажмите, чтобы включить/выключить визуализацию главного вывода + + + + Click to enable + Нажать для включения + + + + VstEffectControlDialog + + + Show/hide + Показать/Скрыть + + + + Control VST-plugin from LMMS host + Управление VST плагином через LMMS хост + + + + Click here, if you want to control VST-plugin from host. + Нажмите здесь, для контроля VST плагином через хост. + + + + Open VST-plugin preset + Открыть предустановку VST плагина + + + + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + Открыть другую .fxp . fxb предустановку VST. + + + + Previous (-) + Предыдущий <-> + + + + + Click here, if you want to switch to another VST-plugin preset program. + Переключение на другую предустановку программы VST плагина. + + + + Next (+) + Следующий <+> + + + + Click here to select presets that are currently loaded in VST. + Выбор из уже загруженных в VST предустановок. + + + + Save preset + Сохранить настройку + + + + Click here, if you want to save current VST-plugin preset program. + Сохранить текущую предустановку программы VST плагина. + + + + + Effect by: + Эффекты по: + + + + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + + + + VstPlugin + + + + The VST plugin %1 could not be loaded. + VST плагин %1 не может быть загружен. + + + + Open Preset + Открыть предустановку + + + + + Vst Plugin Preset (*.fxp *.fxb) + Предустановка VST плагина (*.fxp *.fxb) + + + + : default + : основные + + + + " + " + + + + ' + ' + + + + Save Preset + Сохранить предустановку + + + + .fxp + .fxp + + + + .FXP + .FXP + + + + .FXB + .FXB + + + + .fxb + .fxb + + + + Loading plugin + Загрузка модуля + + + + Please wait while loading VST plugin... + Пожалуйста, подождите пока грузится VST плагин... + + + + WatsynInstrument + + + Volume A1 + Громкость А1 + + + + Volume A2 + Громкость А2 + + + + Volume B1 + Громкость B1 + + + + Volume B2 + Громкость B2 + + + + Panning A1 + + + + + Panning A2 + + + + + Panning B1 + + + + + Panning B2 + + + + + Freq. multiplier A1 + Множитель частоты А1 + + + + Freq. multiplier A2 + Множитель частоты А2 + + + + Freq. multiplier B1 + Множитель частоты B1 + + + + Freq. multiplier B2 + Множитель частоты B2 + + + + Left detune A1 + + + + + Left detune A2 + + + + + Left detune B1 + + + + + Left detune B2 + + + + + Right detune A1 + + + + + Right detune A2 + + + + + Right detune B1 + + + + + Right detune B2 + + + + + A-B Mix + + + + + A-B Mix envelope amount + + + + + A-B Mix envelope attack + + + + + A-B Mix envelope hold + + + + + A-B Mix envelope decay + + + + + A1-B2 Crosstalk + + + + + A2-A1 modulation + + + + + B2-B1 modulation + + + + + Selected graph + Выбранный график + + + + WatsynView + + + + + + Volume + Громкость + + + + + + + Panning + Баланс + + + + + + + Freq. multiplier + Множитель частоты + + + + + + + Left detune + + + + + + + + + + + + cents + + + + + + + + Right detune + + + + + A-B Mix + + + + + Mix envelope amount + + + + + Mix envelope attack + + + + + Mix envelope hold + + + + + Mix envelope decay + + + + + Crosstalk + + + + + Select oscillator A1 + + + + + Select oscillator A2 + + + + + Select oscillator B1 + + + + + Select oscillator B2 + + + + + Mix output of A2 to A1 + + + + + Modulate amplitude of A1 with output of A2 + Модулировать амплитуду A1 сигналом с A2 + + + + Ring-modulate A1 and A2 + Кольцевая модуляция А1 и А2 + + + + Modulate phase of A1 with output of A2 + Модулировать фазу A1 сигналом с A2 + + + + Mix output of B2 to B1 + + + + + Modulate amplitude of B1 with output of B2 + Модулировать амплитуду B1 сигналом с B2 + + + + Ring-modulate B1 and B2 + Кольцевая модуляция B1 и B2 + + + + Modulate phase of B1 with output of B2 + Модулировать фазу B1 сигналом с B2 + + + + + + + Draw your own waveform here by dragging your mouse on this graph. + Здесь вы можете рисовать собственный сигнал передвигая зажатой мышью по этому графу. + + + + Load waveform + + + + + Click to load a waveform from a sample file + Кликнуть для загрузки формы звука из файла с образцом + + + + Phase left + Фаза слева + + + + Click to shift phase by -15 degrees + + + + + Phase right + Фаза справа + + + + Click to shift phase by +15 degrees + + + + + Normalize + Нормализовать + + + + Click to normalize + + + + + Invert + Инвертировать + + + + Click to invert + + + + + Smooth + Сгладить + + + + Click to smooth + + + + + Sine wave + Синусоида + + + + Click for sine wave + + + + + + Triangle wave + Треугольная волна + + + + Click for triangle wave + + + + + Click for saw wave + + + + + Square wave + Квадрат + + + + Click for square wave + + + + + ZynAddSubFxInstrument + + + Portamento + Портаменто + + + + Filter Frequency + Фильтр Частот + + + + Filter Resonance + Фильтр резонанса + + + + Bandwidth + Ширина полосы + + + + FM Gain + Усил FM + + + + Resonance Center Frequency + Частоты центра резонанса + + + + Resonance Bandwidth + Ширина полосы резонанса + + + + Forward MIDI Control Change Events + Переслать изменение событий MiDi управления + + + + ZynAddSubFxView + + + Portamento: + Портаменто: + + + + PORT + PORT + + + + Filter Frequency: + Фильтр частот: + + + + FREQ + FREQ + + + + Filter Resonance: + Фильтр резонанса: + + + + RES + RES + + + + Bandwidth: + Полоса пропускания: + + + + BW + BW + + + + FM Gain: + Усиление частоты модуляции (FM): + + + + FM GAIN + FM GAIN + + + + Resonance center frequency: + Частоты центра резонанса: + + + + RES CF + RES CF + + + + Resonance bandwidth: + Ширина полосы резонанса: + + + + RES BW + RES BW + + + + Forward MIDI Control Changes + Переслать изменение событий MiDi управления + + + + Show GUI + Показать интерфейс + + + + Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + Скрыть или показать графический интерфейс ZynAddSubFX. + + + + audioFileProcessor + + + Amplify + Усиление + + + + Start of sample + Начало записи + + + + End of sample + Конец записи + + + + Loopback point + Точка петли + + + + Reverse sample + Перевернуть запись + + + + Loop mode + Режим повтора + + + + Stutter + Запинание + + + + Interpolation mode + Режим интерполяции + + + + None + Нет + + + + Linear + Линеарный + + + + Sinc + + + + + Sample not found: %1 + Сэмпл не найден: %1 + + + + bitInvader + + + Samplelength + Длительность + + + + bitInvaderView + + + Sample Length + Длительность записи + + + + Draw your own waveform here by dragging your mouse on this graph. + Здесь вы можете рисовать собственный сигнал. + + + + Sine wave + Синусоида + + + + Click for a sine-wave. + Сгенерировать гармонический (синусоидальный) сигнал. + + + + Triangle wave + Треугольник + + + + Click here for a triangle-wave. + Сгенерировать треугольный сигнал. + + + + Saw wave + Зигзаг + + + + Click here for a saw-wave. + Сгенерировать зигзаг. + + + + Square wave + Квадрат (Меандр) + + + + Click here for a square-wave. + Сгенерировать квадрат. + + + + White noise wave + Белый шум + + + + Click here for white-noise. + Сгенерировать белый шум. + + + + User defined wave + Пользовательская + + + + Click here for a user-defined shape. + Задать форму сигнала вручную. + + + + Smooth + Сгладить + + + + Click here to smooth waveform. + Щёлкните чтобы сгладить форму сигнала. + + + + Interpolation + Интерполяция + + + + Normalize + Нормализовать + + + + dynProcControlDialog + + + INPUT + ВХОД + + + + Input gain: + Входная мощность: + + + + OUTPUT + Выход + + + + Output gain: + Выходная мощность: + + + + ATTACK + АТАКА + + + + Peak attack time: + Время пиковой атаки: + + + + RELEASE + ОТПУСК + + + + Peak release time: + Время отпуска пика: + + + + Reset waveform + Сбросить волну + + + + Click here to reset the wavegraph back to default + Сбросить граф волны обратно по умолчанию + + + + Smooth waveform + Сгладить волну + + + + Click here to apply smoothing to wavegraph + Применить сглаживание к графу волны + + + + Increase wavegraph amplitude by 1dB + Повысить амплитуду графа волны на 1 дБ + + + + Click here to increase wavegraph amplitude by 1dB + Нажмите здесь, чтобы повысить амплитуду графа волны на 1 дБ + + + + Decrease wavegraph amplitude by 1dB + Снизить амплитуду графа волны на 1 дБ + + + + Click here to decrease wavegraph amplitude by 1dB + Снизить амплитуду графа волны на 1 дБ + + + + Stereomode Maximum + Стереорежим Максимум + + + + Process based on the maximum of both stereo channels + Процесс основанный на максимуме от обоих каналов + + + + Stereomode Average + Стереорежим Средний + + + + Process based on the average of both stereo channels + Процесс основанный на средней обоих каналов + + + + Stereomode Unlinked + Стереорежим Отдельный + + + + Process each stereo channel independently + Обрабатывает каждый стерео канал независимо + + + + dynProcControls + + + Input gain + Входная мощность + + + + Output gain + Выходная мощность + + + + Attack time + Время атаки + + + + Release time + Время отпуска + + + + Stereo mode + Режим стерео + + + + expressiveView + + Select oscillator W1 + + + + Select oscillator W2 + + + + Select oscillator W3 + + + + Select OUTPUT 1 + + + + Select OUTPUT 2 + + + + Open help window + + + + Sine wave + Синусоида + + + Click for a sine-wave. + Сгенерировать гармонический (синусоидальный) сигнал. + + + Moog-Saw wave + + + + Click for a Moog-Saw-wave. + + + + Exponential wave + Экспоненциальная волна + + + Click for an exponential wave. + + + + Saw wave + Зигзаг + + + Click here for a saw-wave. + Сгенерировать зигзаг. + + + User defined wave + Пользовательская + + + Click here for a user-defined shape. + Задать форму сигнала вручную. + + + Triangle wave + Треугольная волна + + + Click here for a triangle-wave. + Сгенерировать треугольный сигнал. + + + Square wave + Квадрат + + + Click here for a square-wave. + Сгенерировать квадрат. + + + White noise wave + Белый шум + + + Click here for white-noise. + Сгенерировать белый шум. + + + WaveInterpolate + + + + ExpressionValid + + + + General purpose 1: + + + + General purpose 2: + + + + General purpose 3: + + + + O1 panning: + + + + O2 panning: + + + + Release transition: + + + + Smoothness + + + + + fxLineLcdSpinBox + + + Assign to: + Назначить на: + + + + New FX Channel + Новый канал ЭФ + + + + graphModel + + + Graph + Граф + + + + kickerInstrument + + + Start frequency + Начальная частота + + + + End frequency + Конечная частота + + + + Length + Длина + + + + Distortion Start + Начало искажения + + + + Distortion End + Конец искажения + + + + Gain + Усиление + + + + Envelope Slope + Сглаживание кривой + + + + Noise + Шум + + + + Click + Клик + + + + Frequency Slope + Сглаживание частоты + + + + Start from note + + + + + End to note + Конец для ноты + + + + kickerInstrumentView + + + Start frequency: + Начальная частота: + + + + End frequency: + Конечная частота: + + + + Frequency Slope: + + + + + Gain: + Усиление: + + + + Envelope Length: + + + + + Envelope Slope: + + + + + Click: + Клик: + + + + Noise: + Шум: + + + + Distortion Start: + + + + + Distortion End: + + + + + ladspaBrowserView + + + + Available Effects + Доступные эффекты + + + + + Unavailable Effects + Недоступные эффекты + + + + + Instruments + Инструменты + + + + + Analysis Tools + Анализаторы + + + + + Don't know + Неизвестные + + + + This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. + +Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. + +Unavailable Effects are those that were identified as effects, but either didn't have the same number of input and output channels or weren't real time capable. + +Instruments are plugins for which only output channels were identified. + +Analysis Tools are plugins for which only input channels were identified. + +Don't Knows are plugins for which no input or output channels were identified. + +Double clicking any of the plugins will bring up information on the ports. + В этом окне показана информация обо всех модулях LADSPA, которые обнаружила LMMS. Они разделены на пять категорий, в зависимости от названий и типов портов. + +Доступные эффекты — это те, которые могут быть использоаны в LMMS. Чтобы эффект LADSPA мог быть использован, он должен, во-первых, быть собственно эффектом, т. е. иметь как входные так и выходные каналы. LMMS в качестве входного канала воспринимает аудиопорт, содержащий в названии „in“, а выходные узнаёт по подстроке „out“. Для использования в LMMS число входных каналов должно совпадать с числом выходных, и эффект должен иметь возможность использования в реальном времени. + +Недоступные эффекты — это модули LADSPA, опознанные в качестве эффектов, однако либо с несовпадающими количестами входных/выходных каналов, либо не предназначенные для использования в реальном времени. + +Инструменты — это модули, у которых есть только выходные каналы. + +Анализаторы — это модули, обладающие лишь входными каналами. + +Неизвестные — модули, у которых не было обнаружено ни входных, ни выходных каналов. + +Двойной щелчок левой кнопкой мыши по модулю даст информацию о его портах. + + + + Type: + Тип: + + + + ladspaDescription + + + Plugins + Модули + + + + Description + Описание + + + + ladspaPortDialog + + + Ports + Порты + + + + Name + Название + + + + Rate + Частота выборки + + + + Direction + Направление + + + + Type + Тип + + + + Min < Default < Max + Меньше < Стандарт < Больше + + + + Logarithmic + Логарифмический + + + + SR Dependent + Зависимость от SR + + + + Audio + Аудио + + + + Control + Управление + + + + Input + Ввод + + + + Output + Вывод + + + + Toggled + Включено + + + + Integer + Целое + + + + Float + Дробное + + + + + Yes + Да + + + + lb302Synth + + + VCF Cutoff Frequency + Частота среза VCF + + + + VCF Resonance + Усиление VCF + + + + VCF Envelope Mod + Модуляция огибающей VCF + + + + VCF Envelope Decay + Спад огибающей VCF + + + + Distortion + Искажение + + + + Waveform + Форма сигнала + + + + Slide Decay + Сдвиг затухания + + + + Slide + Сдвиг + + + + Accent + Акцент + + + + Dead + Глухо + + + + 24dB/oct Filter + 24дБ/окт фильтр + + + + lb302SynthView + + + Cutoff Freq: + Частота среза: + + + + Resonance: + Отзвук: + + + + Env Mod: + Мод Огиб: + + + + Decay: + Затухание: + + + + 303-es-que, 24dB/octave, 3 pole filter + 303-ий, 24дБ/октаву, 3-польный фильтр + + + + Slide Decay: + Сдвиг затухания: + + + + DIST: + ИСК: + + + + Saw wave + Зигзаг + + + + Click here for a saw-wave. + Сгенерировать зигзаг. + + + + Triangle wave + Треугольная волна + + + + Click here for a triangle-wave. + Сгенерировать треугольный сигнал. + + + + Square wave + Квадрат + + + + Click here for a square-wave. + Сгенерировать квадрат. + + + + Rounded square wave + Волна скругленного квадрата + + + + Click here for a square-wave with a rounded end. + Создать квадратную волну закруглённую в конце. + + + + Moog wave + Муг волна + + + + Click here for a moog-like wave. + Сгенерировать волну похожую на муг. + + + + Sine wave + Синусоида + + + + Click for a sine-wave. + Сгенерировать гармонический (синусоидальный) сигнал. + + + + + White noise wave + Белый шум + + + + Click here for an exponential wave. + Генерировать экспоненциальный сигнал. + + + + Click here for white-noise. + Сгенерировать белый шум. + + + + Bandlimited saw wave + + + + + Click here for bandlimited saw wave. + Нажать здесь для пилообразной волны с ограниченной полосой. + + + + Bandlimited square wave + + + + + Click here for bandlimited square wave. + Нажать здесь для квадратной волны с ограниченной полосой. + + + + Bandlimited triangle wave + Ограниченная треугольная волна + + + + Click here for bandlimited triangle wave. + Нажать здесь для треуголной волны с ограниченной полосой. + + + + Bandlimited moog saw wave + Пружинная волна с ограниченной полосой + + + + Click here for bandlimited moog saw wave. + Нажать здесь для пилообразной муг (moog) волны с ограниченной полосой. + + + + malletsInstrument + + + Hardness + Жёсткость + + + + Position + Положение + + + + Vibrato Gain + Усиление вибрато + + + + Vibrato Freq + Частота вибрато + + + + Stick Mix + Сведение ручек + + + + Modulator + Модулятор + + + + Crossfade + Переход + + + + LFO Speed + Скорость LFO + + + + LFO Depth + Глубина LFO + + + + ADSR + ADSR + + + + Pressure + Давление + + + + Motion + Движение + + + + Speed + Скорость + + + + Bowed + Наклон + + + + Spread + Разброс + + + + Marimba + Маримба + + + + Vibraphone + Вибрафон + + + + Agogo + Дискотека + + + + Wood1 + Дерево1 + + + + Reso + Резо + + + + Wood2 + Дерево2 + + + + Beats + Удары + + + + Two Fixed + Два фиксированных + + + + Clump + Тяжёлая поступь + + + + Tubular Bells + Трубные колокола + + + + Uniform Bar + Равномерные полосы + + + + Tuned Bar + Подстроенные полосы + + + + Glass + Стекло + + + + Tibetan Bowl + Тибетские шары + + + + malletsInstrumentView + + + Instrument + Инструмент + + + + Spread + Разброс + + + + Spread: + Разброс: + + + + Missing files + Файлы отсутствуют + + + + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! + Похоже устновка Stk прошла не полностью. Пожалуйста, убедитесь, что пакет Stk полностью установлен! + + + + Hardness + Жёсткость + + + + Hardness: + Жёсткость: + + + + Position + Положение + + + + Position: + Положение: + + + + Vib Gain + Усил. вибрато + + + + Vib Gain: + Усил. вибрато: + + + + Vib Freq + Част. виб + + + + Vib Freq: + Вибрато: + + + + Stick Mix + Сведение ручек + + + + Stick Mix: + Сведение ручек: + + + + Modulator + Модулятор + + + + Modulator: + Модулятор: + + + + Crossfade + Переход + + + + Crossfade: + Переход: + + + + LFO Speed + Скорость LFO + + + + LFO Speed: + Скорость LFO: + + + + LFO Depth + Глубина LFO + + + + LFO Depth: + Глубина LFO: + + + + ADSR + ADSR + + + + ADSR: + ADSR: + + + + Pressure + Давление + + + + Pressure: + Давление: + + + + Speed + Скорость + + + + Speed: + Скорость: + + + + manageVSTEffectView + + + - VST parameter control + Управление VST параметрами + + + + VST Sync + VST синхронизация + + + + Click here if you want to synchronize all parameters with VST plugin. + Нажмите здесь для синхронизации всех параметров VST плагина. + + + + + Automated + Автоматизировано + + + + Click here if you want to display automated parameters only. + Нажмите здесь, если хотите видеть только автоматизированные параметры. + + + + Close + Закрыть + + + + Close VST effect knob-controller window. + Закрыть окно управления регуляторами VST эффектов. + + + + manageVestigeInstrumentView + + + + - VST plugin control + Управление VST плагином + + + + VST Sync + VST синхронизация + + + + Click here if you want to synchronize all parameters with VST plugin. + Нажмите здесь для синхронизации всех параметров VST плагина. + + + + + Automated + Автоматизировано + + + + Click here if you want to display automated parameters only. + Нажмите здесь, если хотите видеть только автоматизированные параметры. + + + + Close + Закрыть + + + + Close VST plugin knob-controller window. + Закрыть окно управления регуляторами VST плагина. + + + + opl2instrument + + + Patch + Патч + + + + Op 1 Attack + ОП 1 Вступление + + + + Op 1 Decay + ОП 1 Спад + + + + Op 1 Sustain + ОП 1 Выдержка + + + + Op 1 Release + ОП 1 Убывание + + + + Op 1 Level + ОП 1 Уровень + + + + Op 1 Level Scaling + ОП 1 Уровень увеличения + + + + Op 1 Frequency Multiple + ОП 1 Множитель частот + + + + Op 1 Feedback + ОП 1 Возврат + + + + Op 1 Key Scaling Rate + ОП 1 Ключевая ставка увеличения + + + + Op 1 Percussive Envelope + ОП 1 Ударная огибающая + + + + Op 1 Tremolo + ОП 1 Тремоло + + + + Op 1 Vibrato + Оп 1 Вибрато + + + + Op 1 Waveform + ОП 1 Волна + + + + Op 2 Attack + ОП 2 Вступление + + + + Op 2 Decay + ОП 2 Спад + + + + Op 2 Sustain + ОП 2 Выдержка + + + + Op 2 Release + ОП 2 Убывание + + + + Op 2 Level + ОП 2 Уровень + + + + Op 2 Level Scaling + ОП 2 Уровень увеличения + + + + Op 2 Frequency Multiple + ОП 2 Множитель частот + + + + Op 2 Key Scaling Rate + ОП 2 Ключевая ставка множителя + + + + Op 2 Percussive Envelope + ОП 2 Ударная огибающая + + + + Op 2 Tremolo + ОП 2 Тремоло + + + + Op 2 Vibrato + Оп 2 Вибрато + + + + Op 2 Waveform + ОП 2 Волна + + + + FM + FM + + + + Vibrato Depth + Глубина вибрато + + + + Tremolo Depth + Глубина тремоло + + + + opl2instrumentView + + + + Attack + Вступление + + + + + Decay + Затихание + + + + + Release + Убывание + + + + + Frequency multiplier + Множитель частоты + + + + organicInstrument + + + Distortion + Искажение + + + + Volume + Громкость + + + + organicInstrumentView + + + Distortion: + Искажение: + + + + The distortion knob adds distortion to the output of the instrument. + Дисторшн добавляет искажения к выводу инструмента. + + + + Volume: + Громкость: + + + + The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. + Регулятор громкости вывода инструмента, суммируется с регулятором громкости окна инструмента. + + + + Randomise + Случайно + + + + The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. + Кнопка рандомизации случайно устанавливает все регуляторы, кроме гармоник, основной громкости и регулятора искажений (дисторшн). + + + + + Osc %1 waveform: + Форма сигнала для осциллятора %1: + + + + Osc %1 volume: + Громкость осциллятора %1: + + + + Osc %1 panning: + Баланс для осциллятора %1: + Osc %1 stereo detuning Осц %1 стерео расстройка + + cents + сотые + + + Osc %1 harmonic: Осц %1 гармоника: + + FreeBoyInstrument + + + Sweep time + Время распространения + + + + Sweep direction + Направление распространения + + + + Sweep RtShift amount + Кол-во развёртки сдвиг вправо + + + + + Wave Pattern Duty + Рабочая форма волны + + + + Channel 1 volume + Громкость первого канала + + + + + + Volume sweep direction + Объём направления распространения + + + + + + Length of each step in sweep + Длина каждого такта в распространении + + + + Channel 2 volume + Громкость второго канала + + + + Channel 3 volume + Громкость третьего канала + + + + Channel 4 volume + Громкость четвёртого канала + + + + Shift Register width + Сдвиг ширины регистра + + + + Right Output level + Выходной уровень справа + + + + Left Output level + Выходной уровень слева + + + + Channel 1 to SO2 (Left) + От первого канала к SO2 (левый канал) + + + + Channel 2 to SO2 (Left) + От второго канала к SO2 (левый канал) + + + + Channel 3 to SO2 (Left) + От третьего канала к SO2 (левый канал) + + + + Channel 4 to SO2 (Left) + От четвёртого канала к SO2 (левый канал) + + + + Channel 1 to SO1 (Right) + От первого канала к SO1 (правый канал) + + + + Channel 2 to SO1 (Right) + От второго канала к SO1 (правый канал) + + + + Channel 3 to SO1 (Right) + От третьего канала к SO1 (правый канал) + + + + Channel 4 to SO1 (Right) + От четвёртого канала к SO1 (правый канал) + + + + Treble + Верхние + + + + Bass + Нижние + + + + FreeBoyInstrumentView + + + Sweep Time: + Время развёртки: + + + + Sweep Time + Время развёртки + + + + The amount of increase or decrease in frequency + Кол-во увеличения или уменьшения в частоте + + + + Sweep RtShift amount: + Кол-во развёртки сдвиг вправо: + + + + Sweep RtShift amount + Кол-во развёртки сдвиг вправо + + + + The rate at which increase or decrease in frequency occurs + Темп проявления увеличения или снижения в частоте + + + + + Wave pattern duty: + Рабочая форма волны: + + + + Wave Pattern Duty + Рабочая форма волны + + + + + The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. + Рабочий цикл это коэффициент длительности (времени) включенного сигнала относительно всего периода сигнала. + + + + + Square Channel 1 Volume: + Громкость квадратного канала 1: + + + + Square Channel 1 Volume + Громкость квадратного канала 1 + + + + + + Length of each step in sweep: + Длина каждого такта в развёртке: + + + + + + Length of each step in sweep + Длина каждого такта в распространении + + + + + + The delay between step change + Задержка между изменениями такта + + + + Wave pattern duty + Рабочая форма волны + + + + Square Channel 2 Volume: + Громкость квадратного канала 2: + + + + + Square Channel 2 Volume + Громкость квадратного канала 2 + + + + Wave Channel Volume: + Громкость волнового канала: + + + + + Wave Channel Volume + Громкость волнового канала + + + + Noise Channel Volume: + Громкость канала шума: + + + + + Noise Channel Volume + Громкость канала шума + + + + SO1 Volume (Right): + Громкость SO1 (Правый): + + + + SO1 Volume (Right) + Громкость SO1 (Правый) + + + + SO2 Volume (Left): + Громкость SO2 (Левый): + + + + SO2 Volume (Left) + Громкость SO2 (Левый) + + + + Treble: + Верхние: + + + + Treble + Верхние + + + + Bass: + Нижние: + + + + Bass + Нижние + + + + Sweep Direction + Направление развёртки + + + + + + + + Volume Sweep Direction + Громкость направления развёртки + + + + Shift Register Width + Сдвиг ширины регистра + + + + Channel1 to SO1 (Right) + Канал1 в SO1 (Правый) + + + + Channel2 to SO1 (Right) + Канал2 в SO1 (Правый) + + + + Channel3 to SO1 (Right) + Канал3 в SO1 (Правый) + + + + Channel4 to SO1 (Right) + Канал4 в SO1 (Правый) + + + + Channel1 to SO2 (Left) + Канал1 в SO2 (Левый) + + + + Channel2 to SO2 (Left) + Канал2 в SO2 (Левый) + + + + Channel3 to SO2 (Left) + Канал2 в SO2 (Левый) + + + + Channel4 to SO2 (Left) + Канал4 в SO2 (Левый) + + + + Wave Pattern + Рисунок волны + + + + Draw the wave here + Рисовать волну здесь + + patchesDialog + Qsynth: Channel Preset - + + Bank selector - + Выбор банка + Bank Банк + Program selector Выбор программ + Patch Патч + Name Имя + OK ОК + Cancel Отмена @@ -4310,449 +11883,634 @@ pluginBrowser - Incomplete monophonic imitation tb303 - Незавершённая монофоническая имитация tb303 + + no description + описание отсутствует - Plugin for freely manipulating stereo output - Модуль для произвольного управления стереовыходом + + A native amplifier plugin + Родной плагин усилителя - Plugin for controlling knobs with sound peaks - Модуль для установки значений регуляторов по пикам громкости + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + Простой сэмплер с разными установками по использованию сэмплов (как барабаны) в инструментальной дорожке - Plugin for enhancing stereo separation of a stereo input file - Модуль, усиливающий разницу между каналами стереозаписи + + Boost your bass the fast and simple way + Накачай свой бас быстро и просто - List installed LADSPA plugins - Показать установленные модули LADSPA + + Customizable wavetable synthesizer + Настраиваемый синтезатор звукозаписей (wavetable) - GUS-compatible patch instrument - Патч-инструмент, совместимый с GUS + + An oversampling bitcrusher + - Additive Synthesizer for organ-like sounds - Синтезатор звуков вроде органа + + Carla Patchbay Instrument + - Tuneful things to bang on - Мелодичные ударные + + Carla Rack Instrument + Карла инструментальная стойка - VST-host for using VST(i)-plugins within LMMS - VST - хост для поддержки модулей VST(i) в LMMS + + A 4-band Crossover Equalizer + - Vibrating string modeler - Эмуляция вибрирующих струн + + A native delay plugin + Встроенный delay плагин - plugin for using arbitrary LADSPA-effects inside LMMS. - Модуль, позволяющий использовать в LMMS любые эффекты LADSPA. + + A Dual filter plugin + Двух фильтровый плагин - Filter for importing MIDI-files into LMMS - Фильтр для включения файла MIDI в проект ЛММС + + plugin for processing dynamics in a flexible way + - Emulation of the MOS6581 and MOS8580 SID. -This chip was used in the Commodore 64 computer. - Эмуляция MOS6581 и MOS8580. -Использовалось на компьютере Commodore 64. + + A native eq plugin + Родной плагин эквалайзера + + + + A native flanger plugin + - Player for SoundFont files - Проигрыватель файлов SoundFont + + Player for GIG files + Проигрыватель GIG-файлов - Emulation of GameBoy (TM) APU - Эмуляция GameBoy (TM) + + Filter for importing Hydrogen files into LMMS + Фильтр для импорта Hydrogen файлов в LMMS - Customizable wavetable synthesizer - Настраиваемый синтезатор звукозаписей (wavetable) + + Versatile drum synthesizer + Универсальный барабанный синтезатор - Embedded ZynAddSubFX - Встроенный ZynAddSubFX + + List installed LADSPA plugins + Показать установленные модули LADSPA - 2-operator FM Synth - 2-режимный синт модуляции частот (FM synth) + + plugin for using arbitrary LADSPA-effects inside LMMS. + Модуль, позволяющий использовать в LMMS любые эффекты LADSPA. - Filter for importing Hydrogen files into LMMS - Фильтр для импорта Hydrogen файлов в LMMS + + Incomplete monophonic imitation tb303 + Незавершённая монофоническая имитация tb303 - LMMS port of sfxr - LMMS порт SFXR + + Filter for exporting MIDI-files from LMMS + Фильтр для экспорта MIDI файлов из LMMS + + + + Filter for importing MIDI-files into LMMS + Фильтр для включения файла MIDI в проект ЛММС + Monstrous 3-oscillator synth with modulation matrix Монстро 3-осциляторный синт с матрицей модуляции - Three powerful oscillators you can modulate in several ways - Три мощных осциллятора, которые можно модулировать несколькими способами + + A multitap echo delay plugin + - A native amplifier plugin - Родной плагин усилителя + + A NES-like synthesizer + Синтезатор типа NES - Carla Rack Instrument - Карла инструментальная стойка + + 2-operator FM Synth + 2-режимный синт модуляции частот (FM synth) - 4-oscillator modulatable wavetable synth - + + Additive Synthesizer for organ-like sounds + Синтезатор звуков вроде органа - plugin for waveshaping - Плагин для сглаживания волн + + Emulation of GameBoy (TM) APU + Эмуляция GameBoy (TM) - Boost your bass the fast and simple way - Накачай свой бас быстро и просто + + GUS-compatible patch instrument + Патч-инструмент, совместимый с GUS - Versatile drum synthesizer - + + Plugin for controlling knobs with sound peaks + Модуль для установки значений регуляторов по пикам громкости - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - Простой сэмплер с разными установками по использованию сэмплов (как барабаны) в инструментальной дорожке + + Reverb algorithm by Sean Costello + - plugin for processing dynamics in a flexible way - + + Player for SoundFont files + Проигрыватель файлов SoundFont - Carla Patchbay Instrument - + + LMMS port of sfxr + LMMS порт SFXR - plugin for using arbitrary VST effects inside LMMS. - Плагин для использования любых VST эффектов в ЛММС + + Emulation of the MOS6581 and MOS8580 SID. +This chip was used in the Commodore 64 computer. + Эмуляция MOS6581 и MOS8580. +Использовалось на компьютере Commodore 64. + Graphical spectrum analyzer plugin Плагин графического анализа спектра - A NES-like synthesizer - Синтезатор типа NES - - - A native delay plugin - + + Plugin for enhancing stereo separation of a stereo input file + Модуль, усиливающий разницу между каналами стереозаписи - Player for GIG files - + + Plugin for freely manipulating stereo output + Модуль для произвольного управления стереовыходом - A multitap echo delay plugin - + + Tuneful things to bang on + Мелодичные ударные - A native flanger plugin - + + Three powerful oscillators you can modulate in several ways + Три мощных осциллятора, которые можно модулировать несколькими способами - An oversampling bitcrusher - + + VST-host for using VST(i)-plugins within LMMS + VST - хост для поддержки модулей VST(i) в LMMS - A native eq plugin - Родной плагин эквалайзера + + Vibrating string modeler + Эмуляция вибрирующих струн - A 4-band Crossover Equalizer - + + plugin for using arbitrary VST effects inside LMMS. + Плагин для использования любых VST эффектов в ЛММС - A Dual filter plugin - + + 4-oscillator modulatable wavetable synth + 4-осцилляторный модулируемый волновой синтезатор - Filter for exporting MIDI-files from LMMS - + + plugin for waveshaping + Плагин для сглаживания волн - Reverb algorithm by Sean Costello - + + Embedded ZynAddSubFX + Встроенный ZynAddSubFX Mathematical expression parser - + sf2Instrument + Bank Банк + Patch Патч + Gain Усиление + Reverb Эхо - Chorus - Хор (припев) + + Reverb Roomsize + Объём эха - A soundfont %1 could not be loaded. - Soundfont %1 не удаётся загрузить. + + Reverb Damping + Затухание эха - Reverb room size - + + Reverb Width + Долгота эха - Reverb damping - + + Reverb Level + Уровень эха - Reverb width - + + Chorus + Хор (припев) - Reverb level - + + Chorus Lines + Линии хора - Chorus voices - + + Chorus Level + Уровень хора - Chorus level - + + Chorus Speed + Скорость хора - Chorus speed - + + Chorus Depth + Глубина хора - Chorus depth - + + A soundfont %1 could not be loaded. + Soundfont %1 не удаётся загрузить. sf2InstrumentView + + Open other SoundFont file + Открыть другой файл SoundFront + + + + Click here to open another SF2 file + Нажмите здесь чтобы открыть другой файл SF2 + + + + Choose the patch + Выбрать патч + + + + Gain + УСИЛ + + + Apply reverb (if supported) Создать эхо (если поддерживается) - Apply chorus (if supported) - Создать эффект хора (если поддерживается) + + This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. + Эта кнопка включает эффект эха. Это может пригодиться, но работает не для всех файлов. - Open SoundFont file - Открыть файл SoundFront + + Reverb Roomsize: + Размер помещения: - Choose patch - + + Reverb Damping: + Глушение эха: - Gain: - + + Reverb Width: + Долгота эха: + + + + Reverb Level: + Уровень эха: - Room size: - + + Apply chorus (if supported) + Создать эффект хора (если поддерживается) - Damping: - + + This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. + Эта кнопка включает эффект хора. Это может пригодиться, но работает не для всех файлов. - Width: - Ширина: + + Chorus Lines: + Линии хора: - Level: - + + Chorus Level: + Уровень хора: - Voices: - + + Chorus Speed: + Скорость хора: - Speed: - Скорость: + + Chorus Depth: + Глубина хора: - Depth: - Емкость: + + Open SoundFont file + Открыть файл SoundFront - SoundFont Files (*.sf2 *.sf3) - + + SoundFont2 Files (*.sf2) + Файлы SoundFont2 (*.sf2) sfxrInstrument - Wave - + + Wave Form + Форма волны sidInstrument + + Cutoff + Срез + + + Resonance Усиление + Filter type Тип фильтра + Voice 3 off Голос 3 откл + Volume Громкость + Chip model Модель чипа - - Cutoff frequency - - sidInstrumentView + Volume: Громкость: + Resonance: Усиление: + + Cutoff frequency: Частота среза: + + High-Pass filter + Выс.ЧФ + + + + Band-Pass filter + Сред.ЧФ + + + + Low-Pass filter + Низ.ЧФ + + + + Voice3 Off + Голос 3 откл + + + MOS6581 SID - + MOS6581 SID + MOS8580 SID - + MOS8580 SID + + Attack: Вступление: + + Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. + Длительность вступления определяет, насколько быстро громкость %1-го голоса возрастает от нуля до наибольшего значения. + + + + Decay: - Спад: + Затухание: + + + + Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. + Длительность спада определяет, насколько быстро громкость падает от максимума до остаточного уровня. + Sustain: Выдержка: + + Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. + Громкость %1-го голоса будет оставаться на уровне амплитуды выдержки, пока длится нота. + + + + Release: Убывание: + + The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. + Громкость %1-го голоса будет падать от остаточного уровня до нуля с указанной здесь скоростью. + + + + Pulse Width: Длительность импульса: + + The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. + Длительность импульса позволяет мягко регулировать прохождение импульса без заметных сбоев. Импульсная волна должна быть выбрана на осцилляторе %1, чтобы получить звучание. + + + Coarse: Грубость: - Noise - Шум + + The Coarse detuning allows to detune Voice %1 one octave up or down. + Грубая настройка позволяет подстроить Голос %1 на одну октаву вверх или вниз. - Sync - Синхро + + Pulse Wave + Пульсирующая волна - Filtered - Фильтровать + + Triangle Wave + Треугольник - Test - Тест + + SawTooth + Зигзаг - High-pass filter - + + Noise + Шум - Band-pass filter - + + Sync + Синхро - Low-pass filter - + + Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. + Синхро синхронизирует фундаментальную частоту осцилляторов %1 фундаментальной частотой осциллятора %2, создавая эффект "Железной синхронизации". - Voice 3 off - + + Ring-Mod + Круговой режим - Pulse wave - + + Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. + Круговой режим заменяет треугольные волны на выходе осциллятора %1 "Круговой модуляцией" комбинацией осцилляторов %1 и %2. - Triangle wave - + + Filtered + Фильтровать - Saw wave - Зигзаг + + When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. + Если этот флажок установлен, то %1-й голос будет проходить через фильтр. Иначе голос №%1 будет подаваться прямо на выход. - Ring modulation - + + Test + Тест - Pulse width: - + + Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. + Если «флажок» установлен, то %1-й осциллятор выдаёт нулевой сигнал (пока флажок не снимется). stereoEnhancerControlDialog - Width: - Ширина: + + WIDE + ШИРЕ - WIDTH - + + Width: + Ширина: stereoEnhancerControls + Width Ширина @@ -4760,18 +12518,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControlDialog + Left to Left Vol: От левого на левый: + Left to Right Vol: От левого на правый: + Right to Left Vol: От правого на левый: + Right to Right Vol: От правого на правый: @@ -4779,18 +12541,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControls + Left to Left От левого на левый + Left to Right От левого на правый + Right to Left От правого на левый + Right to Right От правого на правый @@ -4798,191 +12564,380 @@ This chip was used in the Commodore 64 computer. vestigeInstrument + Loading plugin Загрузка модуля - Please wait while loading the VST plugin... - + + Please wait while loading VST-plugin... + Подождите, пока загрузится модуль VST... vibed + String %1 volume Громкость %1-й струны + String %1 stiffness Жёсткость %1-й струны + Pick %1 position Лад %1 + Pickup %1 position Положение %1-го звукоснимателя - Impulse %1 - Импульс %1 + + Pan %1 + Бал %1 - String %1 panning - + + Detune %1 + Подстройка %1 - String %1 detune - + + Fuzziness %1 + Нечёткость %1 - String %1 fuzziness - + + Length %1 + Длина %1 - String %1 length - + + Impulse %1 + Импульс %1 - String %1 - + + Octave %1 + Октава %1 vibedView + + Volume: + Громкость: + + + + The 'V' knob sets the volume of the selected string. + Регулятор 'V' устанавливает громкость текущей струны. + + + String stiffness: Жёсткость: + + The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. + Регулятор 'S' устанавливает жёсткость текущей струны. Этот параметр отвечает за длительность звучания струны (чем больше значение жёсткости, тем дольше звенит струна). + + + Pick position: Лад: + + The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. + Регулятор 'P' устанавливает место струны, где она будет „прижата“. Чем ниже значение, тем ближе это место будет к кобылке. + + + Pickup position: Положение звукоснимателя: + + The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. + Регулятор 'PU' устанавливает место струны, откуда будет сниматься звук. Чем ниже значение, тем ближе это место будет к кобылке. + + + + Pan: + Бал: + + + + The Pan knob determines the location of the selected string in the stereo field. + Эта ручка устанавливает стереобаланс для текущей струны. + + + + Detune: + Подстроить: + + + + The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. + Ручка подстройки изменяет сдвиг частоты для текущей струны. Отрицательные значения заставят струну звучать плоско (бемольно), положительные — остро (диезно). + + + + Fuzziness: + Нечёткость: + + + + The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. + Эта ручка добавляет размытости звуку, что наиболее заметно во время нарастания, впрочем, это может использоваться, чтобы сделать звук более „металлическим“. + + + + Length: + Длина: + + + + The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. + Ручка длины устанавливает длину текущей струны. Чем длиннее струна, тем более чистый и долгий звук она даёт; однако это требует больше ресурсов ЦП. + + + + Impulse or initial state + Начальная скорость/начальное состояние + + + + The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. + Переключатель „Imp“ устанавливает режим работы струны: если он включён, то указанная форма сигнала интерпретируется как начальный импульс, иначе — как начальная форма струны. + + + Octave Октава + + The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. + Переключатель октав позволяет указать гармонику основной частоты, на которой будет звучать струна. Например, „-2“ означает, что струна будет звучать двумя октавами ниже основной частоты, „F“ заставит струну звенеть на основной частоте инструмента, а „6“ — на частоте, на шесть октав более высокой, чем основная. + + + Impulse Editor Редактор сигнала + + The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. + +The waveform can also be drawn in the graph. + +The 'S' button will smooth the waveform. + +The 'N' button will normalize the waveform. + Редактор формы позволяет явно указать профиль струны в начальный момент времени, либо её начальный импульс (в заисимости от состояния переключателя „Imp“). +Кнопки справа от рисунка позволяют задавать некоторые стандартные формы, причём кнопка '?' служит для задания формы из произвольного звукового файла (загружаются первые 128 элементов выборки). + +Также форма сигнала может быть просто нарисована с помощью мыши. + +Кнопка 'S' сгладит текущую форму. + +Кнопка 'N' нормализует уровень. + + + + Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. + +The graph allows you to control the initial state or impulse used to set the string in motion. + +The 'V' knob controls the volume. The 'S' knob controls the string's stiffness. The 'P' knob controls the pick position. The 'PU' knob controls the pickup position. + +'Pan' and 'Detune' hopefully don't need explanation. The 'Slap' knob adds a bit of fuzz to the sound of the string. + +The 'Length' knob controls the length of the string. + +The LED in the lower right corner of the waveform editor determines whether the string is active in the current instrument. + Инструмент „Vibed“ моделирует до девяти независимых одновременно звучащих струн. + +Переключатель „Strings“ позволяет выбрать струну, чьи свойства редактируются. + +Переключатель „Imp“ устанавливает режим работы струны: если он включён, то указанная форма сигнала интерпретируется как начальный импульс, иначе — как начальная форма струны. + +Переключатель „Octave“ позволяет указать гармонику основной частоты, на которой будет звучать струна. + +Редактор формы позволяет явно указать профиль струны в начальный момент времени, либо её начальный импульс. + +Ручка 'V' устанавливает громкость текущей струны, 'S' — жёсткость, 'P' — место, где прижата струна, а 'PU'' — положение звукоснимателя + +Ручка подстройки и стереобаланса, есть надежда, не нуждаются в объяснениях. + +Ручка „Длина“ регулирует длину струны + +Индикатор-переключатель слева внизу определяет, включена ли текущая струна. + + + Enable waveform Включить + + Click here to enable/disable waveform. + Нажмите, чтобы включить/выключить сигнал. + + + String Струна + + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + Переключатель струн позволяет выбрать струну, чьи свойства редактируются. Инструмент Vibed содержит до девяти независимо звучащих струн, индикатор в левом нижнем углу показывает, активна ли текущая струна (т. е. будет ли она слышна). + + + Sine wave Синусоида + + Use a sine-wave for current oscillator. + Генерировать гармонический (синусоидальный) сигнал. + + + Triangle wave Треугольник - Saw wave - Зигзаг + + Use a triangle-wave for current oscillator. + Генерировать треугольный сигнал. - Square wave - Квадратная волна + + Saw wave + Зигзаг - String volume: - + + Use a saw-wave for current oscillator. + Генерировать зигзагообразный сигнал. - String panning: - + + Square wave + Квадратная волна - String detune: - + + Use a square-wave for current oscillator. + Генерировать квадрат (меандр). - String fuzziness: - + + White noise wave + Белый шум - String length: - + + Use white-noise for current oscillator. + Генерировать белый шум. - Impulse - + + User defined wave + Пользовательская - Enable/disable string - + + Use a user-defined waveform for current oscillator. + Задать форму сигнала. - White noise - Белый шум + + Smooth + Сгладить - User-defined wave - + + Click here to smooth waveform. + Щёлкните чтобы сгладить форму сигнала. - Smooth waveform - Сгладить волну + + Normalize + Нормализовать - Normalize waveform - + + Click here to normalize waveform. + Нажмите, чтобы нормализовать сигнал. voiceObject + Voice %1 pulse width Голос %1 длина сигнала + Voice %1 attack Вступление %1-го голоса + Voice %1 decay - Спад %1-го голоса + Затухание %1-го голоса + Voice %1 sustain Выдержка для %1-го голоса + Voice %1 release Убывание %1-го голоса + Voice %1 coarse detuning Подстройка %1-го голоса (грубо) + Voice %1 wave shape Форма сигнала для %1-го голоса + Voice %1 sync Синхронизация %1-го голоса + Voice %1 ring modulate Голос %1 кольцевой модулятор + Voice %1 filtered Фильтрованный %1-й голос + Voice %1 test Голос %1 тест @@ -4990,53 +12945,85 @@ This chip was used in the Commodore 64 computer. waveShaperControlDialog + INPUT ВХОД + Input gain: Входная мощность: + OUTPUT Выход + Output gain: Выходная мощность: - Clip input - Срезать выходной сигнал + + Reset waveform + Сбросить волну + + + + Click here to reset the wavegraph back to default + Сбросить граф волны обратно по умолчанию + + + + Smooth waveform + Сгладить волну + + + + Click here to apply smoothing to wavegraph + Применить сглаживание к графу волны - Reset wavegraph - + + Increase graph amplitude by 1dB + Повысить амплитуду графа на 1 дБ - Smooth wavegraph - + + Click here to increase wavegraph amplitude by 1dB + Нажмите здесь, чтобы повысить амплитуду графа волны на 1 дБ - Increase wavegraph amplitude by 1 dB - + + Decrease graph amplitude by 1dB + Снизить амплитуду графа на 1 дБ - Decrease wavegraph amplitude by 1 dB - + + Click here to decrease wavegraph amplitude by 1dB + Снизить амплитуду графа волны на 1 дБ + + + + Clip input + Срезать выходной сигнал - Clip input signal to 0 dB - + + Clip input signal to 0dB + Срезать входной сигнал до 0дБ waveShaperControls + Input gain Входная мощность + Output gain Выходная мощность diff --git a/data/locale/sv.ts b/data/locale/sv.ts index eb51c90822b..56cf1a0af10 100644 --- a/data/locale/sv.ts +++ b/data/locale/sv.ts @@ -1658,7 +1658,7 @@ If you're interested in translating LMMS in another language or want to imp W/D - B/T + @@ -1673,7 +1673,7 @@ If you're interested in translating LMMS in another language or want to imp DECAY - FÖRFALL + diff --git a/data/locale/uk.ts b/data/locale/uk.ts index e9aefd4c149..c088f401cb3 100644 --- a/data/locale/uk.ts +++ b/data/locale/uk.ts @@ -1,37 +1,116 @@ - - - + + + AboutDialog + + + About LMMS + Про програму LMMS + + + + LMMS + LMMS + + + + Version %1 (%2/%3, Qt %4, %5) + Версія %1 (%2/%3, Qt %4, %5) + + + + About + Про програму + + + + LMMS - easy music production for everyone + LMMS - легке створення музики для всіх + + + + Copyright © %1 + Авторське право © %1 + + + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + + + + Authors + Автори + + + + Involved + Учасники + + + + Contributors ordered by number of commits: + Розробники відсортовані за кількістю коммітов: + + + + Translation + Переклад + + + + Current language not translated (or native English). + +If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! + Переклад виконали: +Михайло Рожко <mihail.rozshko@gmail.com> + +Якщо Ви зацікавлені в перекладі LMMS на іншу мову або хочете поліпшити існуючий переклад, ми будемо раді будь-якій допомогі! Просто зв'яжіться з розробниками! + + + + License + Ліцензія + + AmplifierControlDialog + VOL ГУЧН + Volume: Гучність: + PAN БАЛ + Panning: Баланс: + LEFT ЛІВЕ + Left gain: Ліве підсилення: + RIGHT ПРАВЕ + Right gain: Праве підсилення: @@ -39,4270 +118,11761 @@ AmplifierControls + Volume Гучність + Panning Баланс + Left gain Ліве підсилення + Right gain Праве підсилення + + AudioAlsaSetupWidget + + + DEVICE + ПРИСТРІЙ + + + + CHANNELS + КАНАЛИ + + AudioFileProcessorView - Reverse sample - Реверс запису + + Open other sample + Відкрити інший запис - Amplify: - Підсилення: + + Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. + Натисніть тут, щоб відкрити інший звуковий файл. У новому вікні діалогу ви зможете вибрати потрібний файл. Такі налаштування, як режим повтору, точки початку/кінця, підсилення та інші не скинуться, тому звучання може відрізнятися від оригіналу. - Continue sample playback across notes - Продовжити відтворення запису по нотах + + Reverse sample + Реверс запису + + + + If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. + Якщо включити цю кнопку, весь запис піде у зворотний бік, це зручно для крутих ефектів, наприклад зворотного гуркоту. + Disable loop Відключити повторення + + This button disables looping. The sample plays only once from start to end. + Ця кнопка відключає повтор. Запис програється тільки один раз від початку до кінця. + + + + Enable loop Включити повторення - Loopback point: - Точка повернення з повтору: + + This button enables forwards-looping. The sample loops between the end point and the loop point. + Ця кнопка включає передній повтор. Запис повторюється між кінцевою точкою і точкою повтору. - Open sample - + + This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. + Ця кнопка включає пінг-понг петлю. Запис повторюється назад і вперед між кінцевою точкою і точкою повтору. - Enable ping-pong loop - + + Continue sample playback across notes + Продовжити відтворення запису по нотах - Start point: - + + Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) + Включення цієї опції продовжить відтворення запису за різними нотами - якщо змінити прискорення або тривалість ноти зупиниться до кінця запису, то з наступної ноти запис продовжиться там, де зупинився, щоб скинути відтворення на початок запису, вставте ноту внизу у клавіш (<20 Гц) - End point: - + + Amplify: + Підсилення: - - - AudioFileProcessorWaveView - Sample length: - Довжина запису: + + With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + Ця ручка задає коефіцієнт підсилення. При значенні 100% вихідний звук не змінюється, в іншому випадку - він буде ослаблений або підсилений. (Зверніть увагу, що вихідний запис при цьому залишиться недоторканим.) - - - BassBoosterControlDialog - FREQ - ЧАСТ + + Startpoint: + Початок: - Frequency: - Частота: + + With this knob you can set the point where AudioFileProcessor should begin playing your sample. + Цим регулятором можна встановити мітку з якої АудіоФайлПроцессор повинен почати відтворення запису. - GAIN - ПІДС + + Endpoint: + Кінець: - Gain: - Підсилення: + + With this knob you can set the point where AudioFileProcessor should stop playing your sample. + Цей регулятор встановлює мітку в якій АудіоФайлПроцессор повинен перестати програвати запис. - RATIO - ВІДН + + Loopback point: + Точка повернення з повтору: - Ratio: - Відношення: + + With this knob you can set the point where the loop starts. + Цей регулятор ставить мітку початку повторення. - BassBoosterControls - - Frequency - Частота - - - Gain - Підсилення - + AudioFileProcessorWaveView - Ratio - Відношення + + Sample length: + Довжина запису: - BitcrushControlDialog + AudioJack - IN - ВХД + + JACK client restarted + JACK-клієнт перезапущений - OUT - ВИХ + + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. + LMMS не був підключений до JACK з якоїсь причини, тому LMMS підключення до JACK було перезапущено. Вам доведеться заново вручну створити з'єднання. - GAIN - ПІДС + + JACK server down + JACK-сервер не доступний - CLIP - ЗРІЗ + + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. + Можливо JACK-сервер був вимкнений і запуск нового процесу не вдався, тому LMMS не може продовжити роботу. Вам слід зберегти проект і перезапустити JACK і LMMS. - Sample rate: - Частота дискретизації: + + CLIENT-NAME + ІМ'Я КЛІЄНТА - Stereo difference: - Стерео різниця: + + CHANNELS + КАНАЛИ + + + AudioOss::setupWidget - Levels: - Рівні: + + DEVICE + ПРИСТРІЙ - NOISE - + + CHANNELS + КАНАЛИ + + + AudioPortAudio::setupWidget - FREQ - ЧАСТ + + BACKEND + УПРАВЛІННЯ - STEREO - + + DEVICE + ПРИСТРІЙ + + + AudioPulseAudio::setupWidget - QUANT - + + DEVICE + ПРИСТРІЙ - Input gain: - Вхідне підсилення: + + CHANNELS + КАНАЛИ + + + AudioSdl::setupWidget - Input noise: - + + DEVICE + ПРИСТРІЙ + + + AudioSndio::setupWidget - Output gain: - Вихідне підсилення: + + DEVICE + ПРИСТРІЙ - Output clip: - + + CHANNELS + КАНАЛИ + + + AudioSoundIo::setupWidget - Rate enabled - + + BACKEND + УПРАВЛІННЯ - Enable sample-rate crushing - + + DEVICE + ПРИСТРІЙ + + + AutomatableModel - Depth enabled - + + &Reset (%1%2) + &R Скинути (%1%2) - Enable bit-depth crushing - + + &Copy value (%1%2) + &C Копіювати значення (%1%2) - - - BitcrushControls - Input gain - Вхідне підсилення + + &Paste value (%1%2) + &P Вставити значення (%1%2) - Input noise - + + Edit song-global automation + Змінити глоабльную автоматизацію композиції - Output gain - Вихідне підсилення + + Remove song-global automation + Прибрати глобальну автоматизацію композиції - Output clip - + + Remove all linked controls + Прибрати все приєднане управління - Sample rate - + + Connected to %1 + Приєднано до %1 - Stereo difference - + + Connected to controller + Приєднано до контролера - Levels - + + Edit connection... + Налаштувати з'єднання... - Rate enabled - + + Remove connection + Видалити з'єднання - Depth enabled - + + Connect to controller... + З'єднати з контролером ... - CarlaInstrumentView + AutomationEditor - Show GUI - Показати інтерфейс + + Please open an automation pattern with the context menu of a control! + Відкрийте редатор автоматизації через контекстне меню регулятора! + + + + Values copied + Значення скопійовані + + + + All selected values were copied to the clipboard. + Всі вибрані значення скопійовані до буферу обміну. - CrossoverEQControlDialog + AutomationEditorWindow - Band 1/2 crossover: - + + Play/pause current pattern (Space) + Гра/Пауза поточної мелодії (Пробіл) - Band 2/3 crossover: - + + Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. + Натисніть тут щоб програти поточну мелодію. Це може стати в нагоді при його редагуванні. Мелодія автоматично програватиме знову при досягненні кінця. - Band 3/4 crossover: - + + Stop playing of current pattern (Space) + Зупинити програвання поточної мелодії (Пробіл) - Band 1 gain - + + Click here if you want to stop playing of the current pattern. + Натисніть тут, якщо ви хочете зупинити відтворення поточної мелодії. - Band 1 gain: - + + Edit actions + Зміна - Band 2 gain - + + Draw mode (Shift+D) + Режим малювання (Shift + D) - Band 2 gain: - + + Erase mode (Shift+E) + Режим стирання (Shift+E) - Band 3 gain - + + Flip vertically + Перевернути вертикально - Band 3 gain: - + + Flip horizontally + Перевернути горизонтально - Band 4 gain - + + Click here and the pattern will be inverted.The points are flipped in the y direction. + Натисніть тут і мелодія перевернеться. Точки перевертаються в Y напрямку. - Band 4 gain: - + + Click here and the pattern will be reversed. The points are flipped in the x direction. + Натисніть тут і мелодія перевернеться в напрямку X. - Band 1 mute - + + Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. + При натиснені цієї кнопки активується режим малювання нот, в ньому ви можете додавати/переміщати і змінювати тривалість одиночних нот. Це основний режим і використовується більшу частину часу. +Для увімкнення цього режиму можна скористатися комбінацію клавіш Shift+D. - Mute band 1 - + + Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. + При натиснені цієї кнопки активується режим стирання. У цьому режимі ви можете видаляти ноти по одній. +Для увімкнення цього режиму можна скористатися комбінацію клавіш Shift+E. - Band 2 mute - + + Interpolation controls + Управління інтерполяцією - Mute band 2 - + + Discrete progression + Дискретна прогресія - Band 3 mute - + + Linear progression + Лінійна прогресія - Mute band 3 - + + Cubic Hermite progression + Кубічна Ермітова прогресія - Band 4 mute - + + Tension value for spline + Величина напруженості для сплайна - Mute band 4 - + + A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. + Більш висока напруженість може зробити криву більш м'якою, але перевантажить деякі величини. Низька напруженість зробить нахил кривої нижчою в кожній контрольній точці. - - - DelayControls - Feedback - Повернення + + Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. + Вибір дискретної прогресії для цього шаблону автоматизації. Кількість приєднаних об'єктів залишатиметься постійним між керуючими точками і буде встановлена на нове значення відразу після досягнення кожної керуючої точки. - Output gain - Вихідне підсилення + + Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. + Вибір лінійної прогресії для цього шаблону автоматизації. Кількість приєднаних об'єктів буде змінюватися з постійною швидкістю в часі між керуючими точками для досягнення точного значення в кожній керуючій точці без раптових змін. - Delay samples - + + Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. + Кубічна Ермітова прогресія для цього шаблону автоматизації. Кількість приєднаних об'єктів зміниться по згладженій кривій і пом'якшиться на піках і спадах. - LFO frequency - + + Tension: + Напруженість: - LFO amount - + + Cut selected values (%1+X) + Вирізати вибрані ноти (%1+X) - - - DelayControlsDialog - Gain - Підсилення + + Copy selected values (%1+C) + Копіювати вибрані ноти до буферу (%1+C) - DELAY - + + Paste values from clipboard (%1+V) + Вставити значення з буферу (%1+V) - FDBK - + + Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При натиснені цієї кнопки виділені ноти будуть вирізані до буферу. Пізніше ви можете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". - RATE - + + Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При натиснені цієї кнопки виділені ноти будуть скопійовано до буферу. Пізніше ви зможете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". - AMNT - ГЛИБ + + Click here and the values from the clipboard will be pasted at the first visible measure. + При натиснені цієї кнопки ноти з буферу будуть вставлені в перший видимий такт. + + + + Zoom controls + Управління масштабом + + + + Quantization controls + Управління квантуванням - Delay time - + + Quantization + Квантування - Feedback amount - + + Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. + Квантування. Встановлює найменший розмір кроку для точки автоматизації. За замовчуванням це також задає довжину, очищаючи інші точки діапазону. Натисніть <Ctrl>, щоб змінити цю поведінку. - LFO frequency - + + + Automation Editor - no pattern + Редактор автоматизації - немає шаблону - LFO amount - + + + Automation Editor - %1 + Редактор автоматизації - %1 - Out gain - + + Model is already connected to this pattern. + Модель вже підключена до цього шаблону. - DualFilterControlDialog + AutomationPattern - Filter 1 enabled - Фільтр 1 включено + + Drag a control while pressing <%1> + Тягніть контроль утримуючи <%1> + + + AutomationPatternView - Filter 2 enabled - Фільтр 2 включено + + double-click to open this pattern in automation editor + Двічі клацніть мишею щоб налаштувати автоматизацію для цього шаблону - FREQ - ЧАСТ + + Open in Automation editor + Відкрити в редакторі автоматизації - Cutoff frequency - Зріз частоти + + Clear + Очистити - RESO - РЕЗО + + Reset name + Скинути назву - Resonance - Резонанс + + Change name + Перейменувати - GAIN - ПІДС + + Set/clear record + Встановити/очистити запис - Gain - Підсилення + + Flip Vertically (Visible) + Перевернути вертикально (Видиме) - MIX - МІКС + + Flip Horizontally (Visible) + Перевернути горизонтально (Видиме) - Mix - Мікс + + %1 Connections + З'єднання %1 - Enable/disable filter 1 - + + Disconnect "%1" + Від'єднати «%1» - Enable/disable filter 2 - + + Model is already connected to this pattern. + Модель вже підключена до цього шаблону. - DualFilterControls + AutomationTrack - Filter 1 enabled - Фільтр 1 включено + + Automation track + Доріжка автоматизації + + + BBEditor - Filter 1 type - Тип фільтру + + Beat+Bassline Editor + Ритм Бас Редактор - Q/Resonance 1 - Кіл./Резонансу 1 + + Play/pause current beat/bassline (Space) + Грати/пауза поточної лінії ритму/басу (Пробіл) - Gain 1 - Підсилення 1 + + Stop playback of current beat/bassline (Space) + Зупинити відтворення поточної лінії ритм-басу (Пробіл) - Mix - Мікс + + Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. + Натисніть щоб програти поточну лінію ритм-басу. Вона буде повторена при досягненні кінця. - Filter 2 enabled - Фільтр 2 включено + + Click here to stop playing of current beat/bassline. + Зупинити відтворення (Пробіл). - Filter 2 type - Тип фільтру 2 + + Beat selector + Вибір ударних - Q/Resonance 2 - Кіл./Резонансу 2 + + Track and step actions + Дії для доріжки чи її частини - Gain 2 - Підсилення 2 + + Add beat/bassline + Додати ритм/бас - Notch - Смуго-загороджуючий + + Add sample-track + Додати доріжку запису - Moog - Муг + + Add automation-track + Додати доріжку автоматизації - 2x Moog - 2x Муг + + Remove steps + Видалити такти - SV Notch - SV Смуго-заг + + Add steps + Додати такти - Fast Formant - Швидка форманта + + Clone Steps + Клонувати такти + + + BBTCOView - Tripole - Тріполі + + Open in Beat+Bassline-Editor + Відкрити в редакторі ритму і басу - Cutoff frequency 1 - + + Reset name + Скинути назву - Cutoff frequency 2 - + + Change name + Перейменувати - Low-pass - + + Change color + Змінити колір - Hi-pass - + + Reset color to default + Відновити колір за замовчуванням + + + BBTrack - Band-pass csg - + + Beat/Bassline %1 + Ритм/Бас лінія %1 - Band-pass czpg - + + Clone of %1 + Копія %1 + + + BassBoosterControlDialog - All-pass - + + FREQ + ЧАСТ - 2x Low-pass - + + Frequency: + Частота: - RC Low-pass 12 dB/oct - + + GAIN + ПІДС - RC Band-pass 12 dB/oct - + + Gain: + Підсилення: - RC High-pass 12 dB/oct - + + RATIO + ВІДН - RC Low-pass 24 dB/oct - + + Ratio: + Відношення: + + + BassBoosterControls - RC Band-pass 24 dB/oct - + + Frequency + Частота - RC High-pass 24 dB/oct - + + Gain + Підсилення - Vocal Formant - + + Ratio + Відношення + + + BitcrushControlDialog - SV Low-pass - + + IN + ВХД - SV Band-pass - + + OUT + ВИХ - SV High-pass - + + + GAIN + ПІДС - - - EqControls - Input gain - Вхідне підсилення + + Input Gain: + Вхідне підсилення: - Output gain - Вихідне підсилення - - - Peak 1 gain - Пік 1 підсилення + + NOISE + ШУМ - Peak 2 gain - Пік 2 підсилення + + Input Noise: + Вхідний шум: - Peak 3 gain - Пік 3 підсилення + + Output Gain: + Вихідне підсилення: - Peak 4 gain - Пік 4 підсилення + + CLIP + ЗРІЗ - HP res - ВЧ резон + + Output Clip: + Вихідне відсічення: - Peak 1 BW - Пік 1 BW + + Rate Enabled + Частоту вибірки увімкнено - Peak 2 BW - Пік 2 BW + + Enable samplerate-crushing + Включити дроблення частоти дискретизації - Peak 3 BW - Пік 3 BW + + Depth Enabled + Глибина включена - Peak 4 BW - Пік 4 BW + + Enable bitdepth-crushing + Включити ​​дроблення глибини кольору - LP res - НЧ резон + + FREQ + ЧАСТ - HP freq - НЧ част + + Sample rate: + Частота дискретизації: - Peak 1 freq - Пік 1 част + + STEREO + СТЕРЕО - Peak 2 freq - Пік 2 част + + Stereo difference: + Стерео різниця: - Peak 3 freq - Пік 3 част + + QUANT + КВАНТ - Peak 4 freq - Пік 4 част + + Levels: + Рівні: + + + CaptionMenu - LP freq - НЧ част + + &Help + &H Довідка - HP active - ВЧ активна + + Help (not available) + Допомога (не доступно) + + + CarlaInstrumentView - Peak 1 active - Пік 1 активний + + Show GUI + Показати інтерфейс - Peak 2 active - Пік 2 активний + + Click here to show or hide the graphical user interface (GUI) of Carla. + Натисніть сюди щоб сховати чи показати графічний інтерфейс Carla. + + + Controller - Peak 3 active - Пік 3 активний + + Controller %1 + Контролер %1 + + + ControllerConnectionDialog - Peak 4 active - Пік 4 активний + + Connection Settings + Параметры соединения - LP active - НЧ активна + + MIDI CONTROLLER + MIDI-КОНТРОЛЕР - LP 12 - НЧ 12 + + Input channel + Канал введення - LP 24 - НЧ 24 + + CHANNEL + КАНАЛ - LP 48 - НЧ 48 + + Input controller + Контролер введення - HP 12 - ВЧ 12 + + CONTROLLER + КОНТРОЛЕР - HP 24 - ВЧ 24 + + + Auto Detect + Автовизначення - HP 48 - ВЧ 48 + + MIDI-devices to receive MIDI-events from + Пристрої MiDi для прийому подій - Analyse IN - Аналізувати ВХІД + + USER CONTROLLER + КОРИСТ. КОНТРОЛЕР - Analyse OUT - Аналізувати ВИХІД + + MAPPING FUNCTION + ПЕРЕВИЗНАЧЕННЯ - Low-shelf gain - + + OK + ОК - High-shelf gain - + + Cancel + Відміна - Low-shelf res - + + LMMS + ЛММС - High-shelf res - + + Cycle Detected. + Виявлено цикл. + + + ControllerRackView - Low-shelf freq - + + Controller Rack + Стійка контролерів - High-shelf freq - + + Add + Додати - Low-shelf active - + + Confirm Delete + Підтвердити видалення - High-shelf active - + + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. + Чи підтверджуєте видалення? Є можливі зв'язки з цим контролером, потім їх не можна буде повернути.. + + + ControllerView - Low-pass type - + + Controls + Управління - High-pass type - + + Controllers are able to automate the value of a knob, slider, and other controls. + Контролери можуть автоматизувати зміни значень регуляторів, повзунків та іншого управління. - - - EqControlsDialog - HP - ВЧ + + Rename controller + Перейменувати контролер - Peak 1 - Пік 1 + + Enter the new name for this controller + Введіть нову назву контролера - Peak 2 - Пік 2 + + LFO + LFO - Peak 3 - Пік 3 + + &Remove this controller + &R Видалити цей контролер - Peak 4 - Пік 4 + + Re&name this controller + &N Перейменувати цей контролер + + + CrossoverEQControlDialog - LP - НЧ + + Band 1/2 Crossover: + Смуга 1/2 кросовер: - Gain - Підсилення + + Band 2/3 Crossover: + Смуга 2/3 кросовер: - Bandwidth: - Ширина смуги: + + Band 3/4 Crossover: + Смуга 3/4 кросовер: - Resonance : - Резонанс: + + Band 1 Gain: + Смуга 1 підсилення: - Frequency: - Частота: + + Band 2 Gain: + Смуга 2 підсилення: - Octave - Октава + + Band 3 Gain: + Смуга 3 підсилення: - Low-shelf - + + Band 4 Gain: + Смуга 4 підсилення: - High-shelf - + + Band 1 Mute + Смуга 1 відключена - Input gain - Вхідне підсилення + + Mute Band 1 + Відключити смугу 1 - Output gain - Вихідне підсилення + + Band 2 Mute + Смуга 2 відключена - LP group - + + Mute Band 2 + Відключити смугу 2 - HP group - + + Band 3 Mute + Смуга 3 відключена - - - EqHandle - Reso: - Резон: + + Mute Band 3 + Відключити смугу 3 - BW: - ШС: + + Band 4 Mute + Смуга 4 відключена - Freq: - Част: + + Mute Band 4 + Відключити смугу 4 - FlangerControls - - Seconds - Секунд - + DelayControls - Regen - Перегенерувати + + Delay Samples + Затримка семплів - Noise - Шум + + Feedback + Повернення - Invert - Інвертувати + + Lfo Frequency + Частота LFO - Delay samples - + + Lfo Amount + Величина LFO - LFO frequency - + + Output gain + Вихідне підсилення - FlangerControlsDialog + DelayControlsDialog + DELAY - + ЗАТРИМ - RATE - - - - AMNT - ГЛИБ + + Delay Time + Час затримки - Amount: - + + FDBK + FDBK - FDBK - + + Feedback Amount + Величина повернення - NOISE - + + RATE + ЧАСТ - Invert - Інвертувати + + Lfo + LFO - Period: - + + AMNT + ГЛИБ - Delay time: - + + Lfo Amt + Вел LFO - Feedback amount: - + + Out Gain + Вих підсилення - White noise amount: - + + Gain + Підсилення - FreeBoyInstrument + DualFilterControlDialog - Sweep time - Час поширення + + + FREQ + ЧАСТ - Sweep direction - Напрям поширення + + + Cutoff frequency + Зріз частоти - Channel 1 volume - Гучність першого каналу + + + RESO + РЕЗО - Volume sweep direction - Обсяг напрямку поширення + + + Resonance + Резонанс - Length of each step in sweep - Довжина кожного такту в поширенні + + + GAIN + ПІДС - Channel 2 volume - Гучність другого каналу + + + Gain + Підсилення - Channel 3 volume - Гучність третього каналу + + MIX + МІКС - Channel 4 volume - Гучність четвертого каналу + + Mix + Мікс - Channel 1 to SO2 (Left) - Від першого каналу до SO2 (лівий канал) + + Filter 1 enabled + Фільтр 1 включено - Channel 2 to SO2 (Left) - Від другого каналу до SO2 (лівий канал) + + Filter 2 enabled + Фільтр 2 включено - Channel 3 to SO2 (Left) - Від третього каналу до SO2 (лівий канал) + + Click to enable/disable Filter 1 + Натиснути для включення/виключення Фільтру 1 - Channel 4 to SO2 (Left) - Від четвертого каналу до SO2 (лівий канал) + + Click to enable/disable Filter 2 + Натиснути для включення/виключення Фільтру 2 + + + DualFilterControls - Channel 1 to SO1 (Right) - Від першого каналу до SO1 (правий канал) + + Filter 1 enabled + Фільтр 1 включено - Channel 2 to SO1 (Right) - Від другого каналу до SO1 (правий канал) + + Filter 1 type + Тип фільтру - Channel 3 to SO1 (Right) - Від третього каналу до SO1 (правий канал) + + Cutoff 1 frequency + Зріз 1 частоти - Channel 4 to SO1 (Right) - Від четвертого каналу до SO1 (правий канал) + + Q/Resonance 1 + Кіл./Резонансу 1 - Treble - Дискант + + Gain 1 + Підсилення 1 - Bass - Бас + + Mix + Мікс - Shift Register width - Зміщення ширини регістра + + Filter 2 enabled + Фільтр 2 включено - Sweep rate shift amount - + + Filter 2 type + Тип фільтру 2 - Wave pattern duty cycle - + + Cutoff 2 frequency + Зріз 2 частоти - Right output level - + + Q/Resonance 2 + Кіл./Резонансу 2 - Left output level - + + Gain 2 + Підсилення 2 - - - FreeBoyInstrumentView - Length of each step in sweep: - Довжина кожного кроку в розгортці: + + + LowPass + Низ.ЧФ - Length of each step in sweep - Довжина кожного кроку в розгортці + + + HiPass + Вис.ЧФ - Treble: - Дискант: + + + BandPass csg + Серед.ЧФ csg - Treble - Дискант + + + BandPass czpg + Серед.ЧФ czpg - Bass: - Бас: + + + Notch + Смуго-загороджуючий - Bass - Бас + + + Allpass + Всі проходять - Sweep time: - + + + Moog + Муг - Sweep time - Час поширення + + + 2x LowPass + 2х Низ.ЧФ - Sweep rate shift amount: - + + + RC LowPass 12dB + RC Низ.ЧФ 12дБ - Sweep rate shift amount - + + + RC BandPass 12dB + RC Серед.ЧФ 12 дБ - Wave pattern duty cycle: - + + + RC HighPass 12dB + RC Вис.ЧФ 12дБ - Wave pattern duty cycle - + + + RC LowPass 24dB + RC Низ.ЧФ 24дБ - Square channel 1 volume: - + + + RC BandPass 24dB + RC Серед.ЧФ 24дБ - Square channel 1 volume - + + + RC HighPass 24dB + RC Вис.ЧФ 24дБ - Square channel 2 volume: - + + + Vocal Formant Filter + Фільтр Вокальної форманти - Square channel 2 volume - + + + 2x Moog + 2x Муг - Wave pattern channel volume: - + + + SV LowPass + SV Низ.ЧФ - Wave pattern channel volume - + + + SV BandPass + SV Серед.ЧФ - Noise channel volume: - + + + SV HighPass + SV Вис.ЧФ - Noise channel volume - + + + SV Notch + SV Смуго-заг - SO1 volume (Right): - + + + Fast Formant + Швидка форманта - SO1 volume (Right) - + + + Tripole + Тріполі + + + Editor - SO2 volume (Left): - + + Transport controls + Управління засобами сполучення - SO2 volume (Left) - + + Play (Space) + Грати (Пробіл) - Sweep direction - Напрям поширення + + Stop (Space) + Зупинити (Пробіл) - Volume sweep direction - Обсяг напрямку поширення + + Record + Запис - Shift register width - + + Record while playing + Запис під час програвання + + + Effect - Channel 1 to SO1 (Right) - Від першого каналу до SO1 (правий канал) + + Effect enabled + Ефект включений - Channel 2 to SO1 (Right) - Від другого каналу до SO1 (правий канал) + + Wet/Dry mix + Насиченість - Channel 3 to SO1 (Right) - Від третього каналу до SO1 (правий канал) + + Gate + Шлюз - Channel 4 to SO1 (Right) - Від четвертого каналу до SO1 (правий канал) + + Decay + Згасання + + + EffectChain - Channel 1 to SO2 (Left) - Від першого каналу до SO2 (лівий канал) + + Effects enabled + Ефекти включені + + + EffectRackView - Channel 2 to SO2 (Left) - Від другого каналу до SO2 (лівий канал) + + EFFECTS CHAIN + МЕРЕЖА ЕФЕКТІВ - Channel 3 to SO2 (Left) - Від третього каналу до SO2 (лівий канал) + + Add effect + Додати ефект + + + EffectSelectDialog - Channel 4 to SO2 (Left) - Від четвертого каналу до SO2 (лівий канал) + + Add effect + Додати ефект - Wave pattern graph - + + + Name + І'мя - - - GigInstrument - Bank - Банк + + Type + Тип - Patch - Патч + + Description + Опис - Gain - Підсилення + + Author + Автор - GigInstrumentView + EffectView - Open GIG file - Відкрити GIG файл + + Toggles the effect on or off. + Увімк/Вимк ефект. - GIG Files (*.gig) - GIG Файли (*.gig) + + On/Off + Увімк/Вимк - Choose patch - + + W/D + НАСИЧ - Gain: - Підсилення: + + Wet Level: + Рівень насиченості: - - - InstrumentTrack - Default preset - Основна предустановка + + The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. + Регулятор насиченості визначає частку обробленого сигналу, яка буде на виході. - - - LadspaControlDialog - Link Channels - Зв'язати канали + + DECAY + - Channel - Канал + + Time: + Час: - - - LadspaEffect - Unknown LADSPA plugin %1 requested. - Запитаний невідомий модуль LADSPA «%1». + + The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. + Decay (затихання) управляє кількістю буферів тиші, які повинні пройти до кінця роботи плагіна. Менші величини знижують перевантаження процесора, але виникає ризик появи потріскування або підрізання в хвості на перетримці (delay) або відлуння (reverb) ефектах. - - - MidiImport - Setup incomplete - Установку не завершено + + GATE + ШЛЮЗ - You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. - Ви не увімкнули підтримку програвача SoundFont2 при компіляції LMMS, він використовується для додавання основного звуку в імпортовані Міді файли, тому після імпорту цього міді файлу звуку не буде. + + Gate: + Шлюз: - Track - Трек + + The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. + GATE (Шлюз) визначає рівень сигналу, який буде вважатися "тишею" при визначенні зупинки оброблення сигналів. + + + + Controls + Управління - You have not set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. - + + Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. + +The On/Off switch allows you to bypass a given plugin at any point in time. + +The Wet/Dry knob controls the balance between the input signal and the effected signal that is the resulting output from the effect. The input for the stage is the output from the previous stage. So, the 'dry' signal for effects lower in the chain contains all of the previous effects. + +The Decay knob controls how long the signal will continue to be processed after the notes have been released. The effect will stop processing signals when the volume has dropped below a given threshold for a given length of time. This knob sets the 'given length of time'. Longer times will require more CPU, so this number should be set low for most effects. It needs to be bumped up for effects that produce lengthy periods of silence, e.g. delays. + +The Gate knob controls the 'given threshold' for the effect's auto shutdown. The clock for the 'given length of time' will begin as soon as the processed signal level drops below the level specified with this knob. + +The Controls button opens a dialog for editing the effect's parameters. + +Right clicking will bring up a context menu where you can change the order in which the effects are processed or delete an effect altogether. + Сигнал проходить послідовно через всі встановлені фільтри (зверху вниз). + +Перемикач Увімк/Вимк дозволяє в будь-який момент вмикати / вимикати фільтр. + +Регулятор (wet / dry) насиченості визначає баланс між вхідним сигналом і сигналом після ефекту, який стає вихідним сигналом ефекту. Вхідний сигнал кожного фільтра є виходом попереднього, так що частка чистого сигналу при проходженні по ланцюжку постійно падає. + +Регулятор (decay) затихання визначає час, який буде діяти фільтр після того як ноти були відпущені. +Ефект перестане обробляти сигнали, коли гучність впаде нижче порогу для заданої довжини часу. Ця ручка (Knob) встановлює "задану довжину часу" Чим менше значення, тим менші вимоги до ЦП, тому краще ставити це число низьким для більшості ефектів. однак це може викликати обрізку звуку при використанні ефектів з тривалими періодами тиші, типу затримки. + +Регулятор шлюзу служить для вказівки порогу сигналу для авто-відключення ефекту, відлік для "заданої довжини часу" почнеться як тільки опрацьований сигнал впаде нижче зазначеного цим регулятором рівня. + +Кнопка "Управління" відкриває вікно зміни параметрів ефекту. + +Контекстне меню, яке викликається клацанням правою кнопкою миші, дозволяє змінювати порядок проходження фільтрів або видаляти їх разом з іншими. + + + + Move &up + &u Перемістити вище + + + + Move &down + &d Перемістити нижче + + + + &Remove this plugin + &R Видалити цей плагін - MonstroInstrument + EnvelopeAndLfoParameters - Osc 3 Stereo phase offset - Зміщення стерео-фази осциллятора 3 + + Predelay + Затримка - Selected view - Перегляд обраного + + Attack + Вступ - Sine wave - Синусоїда + + Hold + Утримання - Bandlimited Triangle wave - Трикутна хвиля з обмеженою смугою + + Decay + Згасання - Bandlimited Saw wave - Зигзаг хвиля з обмеженою смугою + + Sustain + Витримка - Bandlimited Ramp wave - Спадаюча хвиля з обмеженою смугою + + Release + Зменшення - Bandlimited Square wave - Квадратна хвиля з обмеженою смугою + + Modulation + Модуляція - Bandlimited Moog saw wave - Муг-зигзаг хвиля з обмеженою смугою + + LFO Predelay + Затримка LFO - Soft square wave - М'яка прямокутна хвиля + + LFO Attack + Вступ LFO - Absolute sine wave - Абсолютна синусоїдна хвиля + + LFO speed + Швидкість LFO - Exponential wave - Експоненціальна хвиля + + LFO Modulation + Модуляція LFO - White noise - Білий шум + + LFO Wave Shape + Форма сигналу LFO - Digital Triangle wave - Цифрова трикутна хвиля + + Freq x 100 + ЧАСТ x 100 - Digital Saw wave - Цифрова зигзаг хвиля + + Modulate Env-Amount + Модулювати обвідну + + + EnvelopeAndLfoView - Digital Ramp wave - Цифрова спадна хвиля + + + DEL + DEL - Digital Square wave - Цифрова квадратна хвиля + + Predelay: + Предзатримка: - Digital Moog saw wave - Цифрова Муг-зигзаг хвиля + + Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. + Ця ручка визначає затримку обвідної. Чим більша ця величина, тим довший час до старту поточної обвідної. - Triangle wave - Трикутна хвиля + + + ATT + ATT - Saw wave - Зигзаг + + Attack: + Вступ: - Ramp wave - Спадна хвиля + + Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. + Ця ручка встановлює час зростання для поточної обвідної. Чим більше значення, тим довше характеристика (н-д, гучність) зростає до максимуму. Для інструменов нашталт піаніно характерний малий час наростання, а для струнних - великий. - Square wave - Квадратна хвиля + + HOLD + HOLD - Moog saw wave - Муг-зигзаг хвиля + + Hold: + Утримання: - Abs. sine wave - Синусоїда по модулю + + Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. + Ця ручка встановлює тривалість обвідної. Чим більше значення, тим довше обвідна тримається на найвищому рівні. - Random - Випадково + + DEC + DEC - Random smooth - Випадкове зглажування + + Decay: + Згасання: - Osc 1 volume - + + Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. + Ця ручка встановлює час згасання для поточної обвідної. Чим більше значення, тим довше обвідна повинна зменшуватися від вступу до рівня витримки. Для інструментів накшталт піаніно слід вибирати невеликі значення. - Osc 1 panning - + + SUST + SUST - Osc 1 coarse detune - + + Sustain: + Витримка: - Osc 1 fine detune left - + + Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. + Ця ручка встановлює рівень витримки. Чим більша ця величина, тим вище рівень на якому залишається обвідна, перш ніж опуститися до нуля. - Osc 1 fine detune right - + + REL + REL - Osc 1 stereo phase offset - + + Release: + Зменшення: - Osc 1 pulse width - + + Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. + Ця ручка встановлює час відпускання для поточної обвідної. Чим більше значення, тим довша характеристика (н-д, гучність) зменшується від рівня витримки до нуля. Для струнних інструментів слід вибирати великі значення. - Osc 1 sync send on rise - + + + AMT + AMT - Osc 1 sync send on fall - + + + Modulation amount: + Глибина модуляції: - Osc 2 volume - + + Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. + Ця ручка встановлює глибину модуляції для поточної обвідної. Чим більше значення, тим більшою мірою обрана характеристика (н-д, гучність або частота зрізу) буде залежати від цієї обвідної. - Osc 2 panning - + + LFO predelay: + Предзатримка LFO: - Osc 2 coarse detune - + + Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. + Ця ручка визначає затримку перед запуском LFO (LFO - низькочастотний осциллятор (генератор)). Чим більша величина, тим більше часу до того як LFO почне працювати. - Osc 2 fine detune left - + + LFO- attack: + Вступ LFO: - Osc 2 fine detune right - + + Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. + Використовуйте цю ручку для встановлення часу вступу цього LFO. Чим більше значення, тим довше LFO потребує збільшення своєї амплітуди до максимуму. - Osc 2 stereo phase offset - + + SPD + SPD - Osc 2 waveform - + + LFO speed: + Швидкість LFO: - Osc 2 sync hard - + + Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. + Ця ручка встановлює швидкість поточного LFO. Чим більше значення, тим швидше LFO коливається і швидше виробляється ефект. - Osc 2 sync reverse - + + Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. + Ця ручка встановлює глибину модуляції для поточного LFO. Чим більше значення, тим більшою мірою обрана характеристика (н-д, гучність або частота зрізу) залежатиме від цього LFO. - Osc 3 volume - + + Click here for a sine-wave. + Синусоїда. - Osc 3 panning - + + Click here for a triangle-wave. + Згенерувати трикутний сигнал. - Osc 3 coarse detune - + + Click here for a saw-wave for current. + Згенерувати зигзагоподібний сигнал. - Osc 3 sub-oscillator mix - + + Click here for a square-wave. + Згенерувати квадратний сигнал. - Osc 3 waveform 1 - + + Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. + Задати свою форму сигналу. Згодом, перетягнути відповідний файл із записом в граф LFO. - Osc 3 waveform 2 - + + Click here for random wave. + Натисніть сюди для випадкової хвилі. - Osc 3 sync hard - + + FREQ x 100 + ЧАСТОТА x 100 - Osc 3 Sync reverse - + + Click here if the frequency of this LFO should be multiplied by 100. + Натисніть, щоб помножити частоту цього LFO на 100. - LFO 1 waveform - + + multiply LFO-frequency by 100 + Помножити частоту LFO на 100 - LFO 1 attack - + + MODULATE ENV-AMOUNT + МОДЕЛЮВ ОБВІДНУ - LFO 1 rate - + + Click here to make the envelope-amount controlled by this LFO. + Натисніть сюди, щоб глибина модуляції обвідної задавалася цим LFO. - LFO 1 phase - + + control envelope-amount by this LFO + Дозволити цьому LFO задавати значення обвідної - LFO 2 waveform - + + ms/LFO: + мс/LFO: - LFO 2 attack - + + Hint + Підказка - LFO 2 rate - + + Drag a sample from somewhere and drop it in this window. + Перетягніть в це вікно який-небудь запис. + + + EqControls - LFO 2 phase - + + Input gain + Вхідне підсилення - Env 1 pre-delay - + + Output gain + Вихідне підсилення - Env 1 attack - + + Low shelf gain + Мала ступінь підсилення - Env 1 hold - + + Peak 1 gain + Пік 1 підсилення - Env 1 decay - + + Peak 2 gain + Пік 2 підсилення - Env 1 sustain - + + Peak 3 gain + Пік 3 підсилення - Env 1 release - + + Peak 4 gain + Пік 4 підсилення - Env 1 slope - + + High Shelf gain + Висока ступінь підсилення - Env 2 pre-delay - + + HP res + ВЧ резон - Env 2 attack - + + Low Shelf res + Мала ступінь резон - Env 2 hold - + + Peak 1 BW + Пік 1 BW - Env 2 decay - + + Peak 2 BW + Пік 2 BW - Env 2 sustain - + + Peak 3 BW + Пік 3 BW - Env 2 release - + + Peak 4 BW + Пік 4 BW - Env 2 slope - + + High Shelf res + Висока ступінь резон - Osc 2+3 modulation - + + LP res + НЧ резон - Osc 1 - Vol env 1 - + + HP freq + НЧ част - Osc 1 - Vol env 2 - + + Low Shelf freq + Низька ступінь част - Osc 1 - Vol LFO 1 - + + Peak 1 freq + Пік 1 част - Osc 1 - Vol LFO 2 - + + Peak 2 freq + Пік 2 част - Osc 2 - Vol env 1 - + + Peak 3 freq + Пік 3 част - Osc 2 - Vol env 2 - + + Peak 4 freq + Пік 4 част - Osc 2 - Vol LFO 1 - + + High shelf freq + Висока ступінь част - Osc 2 - Vol LFO 2 - + + LP freq + НЧ част - Osc 3 - Vol env 1 - + + HP active + ВЧ активна - Osc 3 - Vol env 2 - + + Low shelf active + Мала ступінь активна - Osc 3 - Vol LFO 1 - + + Peak 1 active + Пік 1 активний - Osc 3 - Vol LFO 2 - + + Peak 2 active + Пік 2 активний - Osc 1 - Phs env 1 - + + Peak 3 active + Пік 3 активний - Osc 1 - Phs env 2 - + + Peak 4 active + Пік 4 активний - Osc 1 - Phs LFO 1 - + + High shelf active + Висока ступінь активна - Osc 1 - Phs LFO 2 - + + LP active + НЧ активна - Osc 2 - Phs env 1 - + + LP 12 + НЧ 12 - Osc 2 - Phs env 2 - + + LP 24 + НЧ 24 - Osc 2 - Phs LFO 1 - + + LP 48 + НЧ 48 - Osc 2 - Phs LFO 2 - + + HP 12 + ВЧ 12 - Osc 3 - Phs env 1 - + + HP 24 + ВЧ 24 - Osc 3 - Phs env 2 - + + HP 48 + ВЧ 48 - Osc 3 - Phs LFO 1 - + + low pass type + Тип низької частоти - Osc 3 - Phs LFO 2 - + + high pass type + Тип високої частоти - Osc 1 - Pit env 1 - + + Analyse IN + Аналізувати ВХІД - Osc 1 - Pit env 2 - + + Analyse OUT + Аналізувати ВИХІД + + + EqControlsDialog - Osc 1 - Pit LFO 1 - + + HP + ВЧ - Osc 1 - Pit LFO 2 - + + Low Shelf + Мала ступінь - Osc 2 - Pit env 1 - + + Peak 1 + Пік 1 - Osc 2 - Pit env 2 - + + Peak 2 + Пік 2 - Osc 2 - Pit LFO 1 - + + Peak 3 + Пік 3 - Osc 2 - Pit LFO 2 - + + Peak 4 + Пік 4 - Osc 3 - Pit env 1 - + + High Shelf + Висока ступінь - Osc 3 - Pit env 2 - + + LP + НЧ - Osc 3 - Pit LFO 1 - + + In Gain + Вхід підсилення - Osc 3 - Pit LFO 2 - - + + + + Gain + Підсилення + + + + Out Gain + Вих підсилення + + + + Bandwidth: + Ширина смуги: + - Osc 1 - PW env 1 - + + Octave + Октава - Osc 1 - PW env 2 - + + Resonance : + Резонанс: - Osc 1 - PW LFO 1 - + + Frequency: + Частота: - Osc 1 - PW LFO 2 - + + lp grp + нч grp - Osc 3 - Sub env 1 - + + hp grp + вч grp + + + EqHandle - Osc 3 - Sub env 2 - + + Reso: + Резон: - Osc 3 - Sub LFO 1 - + + BW: + ШС: - Osc 3 - Sub LFO 2 - + + + Freq: + Част: - MonstroView + ExportProjectDialog - Operators view - Операторский вид + + Export project + Експорт проекту - Matrix view - Матричний вигляд + + Output + Вивід - Volume - Гучність + + File format: + Формат файла: - Panning - Баланс + + Samplerate: + Частота дискретизації: - Coarse detune - Грубе підстроювання + + 44100 Hz + 44.1 КГц - semitones - півтон(а,ів) + + 48000 Hz + 48 КГц - cents - відсотків + + 88200 Hz + 88.2 КГц - Stereo phase offset - Зміщення стерео-фази + + 96000 Hz + 96 КГц - deg - град + + 192000 Hz + 192 КГц - Pulse width - Довжина імпульсу + + Depth: + Глибина: - Send sync on pulse rise - Відправляти синхронізацію на підйомі імпульсу + + 16 Bit Integer + 16 Біт ціле - Send sync on pulse fall - Відправити синхронізацію на падінні пульсу + + 24 Bit Integer + 24 Біт ціле - Hard sync oscillator 2 - Жорстка синхронізація осциллятора 2 + + 32 Bit Float + 32 Біт плаваюча - Reverse sync oscillator 2 - Верерс синхронізація осциллятора 2 + + Stereo mode: + Стерео режим: - Sub-osc mix - Мікс суб-осциляторів + + Stereo + Стерео - Hard sync oscillator 3 - Жорстка синхронізація осциллятора 3 + + Joint Stereo + Об'єднане стерео - Reverse sync oscillator 3 - Верерс синхронізація осциллятора 3 + + Mono + Моно - Attack - Вступ + + Bitrate: + Бітрейт: - Rate - Частота вибірки + + 64 KBit/s + 64 КБіт/с - Phase - Фаза + + 128 KBit/s + 128 КБіт/с - Pre-delay - Передзатримка + + 160 KBit/s + 160 КБіт/с - Hold - Утримання + + 192 KBit/s + 192 КБіт/с - Decay - Згасання + + 256 KBit/s + 256 КБіт/с - Sustain - Витримка + + 320 KBit/s + 320 КБіт/с - Release - Зменшення + + Use variable bitrate + Використовувати змінний бітрейт - Slope - Нахил + + Quality settings + Налаштування якості - Modulation amount - Глибина модуляції + + Interpolation: + Інтерполяція: - Fine tune left - + + Zero Order Hold + Нульова затримка - Fine tune right - + + Sinc Fastest + Синхр. Швидка - Mix osc 2 with osc 3 - + + Sinc Medium (recommended) + Синхр. Середня (рекомендовано) - Modulate amplitude of osc 3 by osc 2 - + + Sinc Best (very slow!) + Синхр. краща (дуже повільно!) - Modulate frequency of osc 3 by osc 2 - + + Oversampling (use with care!): + Передискретизація (використовувати обережно!): - Modulate phase of osc 3 by osc 2 - + + 1x (None) + 1х (Ні) - - - MultitapEchoControlDialog - Length - Довжина + + 2x + - Step length: - Довжина кроку: + + 4x + - Dry - Сухий + + 8x + - Stages - Етапи + + Export as loop (remove end silence) + Експортувати як петлю (прибрати тишу в кінці) - Swap inputs - Обмін входами + + Export between loop markers + Експорт між маркерами циклу - Dry gain: - + + Start + Почати - Low-pass stages: - + + Cancel + Відміна - Swap left and right input channels for reflections - + + Could not open file + Не можу відкрити файл - - - NesInstrument - Channel 2 Coarse detune - Грубе підстроювання 2 каналу + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Не вдалось відкрити файл %1 для запису. +Перевірте, чи маєте ви права на запис файлу і каталог що його містить і спробуйте знову! - Channel 2 Volume - Гучність 2 каналу + + Export project to %1 + Експорт проекту в %1 - Master volume - Основна гучність + + Error + Помилка - Vibrato - Вібрато + + Error while determining file-encoder device. Please try to choose a different output format. + Помилка при визначенні кодека файлу. Спробуйте вибрати інший формат виводу. - Channel 1 coarse detune - + + Rendering: %1% + Обробка: %1% - Channel 1 volume - Гучність першого каналу + Compression level: + - Channel 1 envelope length - + (fastest) + - Channel 1 duty cycle - + (default) + - Channel 1 sweep amount - + (smallest) + + + + Expressive - Channel 1 sweep rate - + Selected graph + Обраний графік - Channel 2 envelope length - + A1 + - Channel 2 duty cycle - + A2 + - Channel 2 sweep amount - + A3 + - Channel 2 sweep rate - + W1 smoothing + - Channel 3 coarse detune - + W2 smoothing + - Channel 3 volume - Гучність третього каналу + W3 smoothing + - Channel 4 volume - Гучність четвертого каналу + PAN1 + - Channel 4 envelope length - + PAN2 + - Channel 4 noise frequency - + REL TRANS + + + + Fader - Channel 4 noise frequency sweep - + + + Please enter a new value between %1 and %2: + Введіть нове значення від %1 до %2: - NesInstrumentView + FileBrowser - Volume - Гучність + + Browser + Оглядач файлів - Coarse detune - Грубе підстроювання + Search + - Envelope length - Довжина обвідної + Refresh list + + + + FileBrowserTreeWidget - Enable channel 1 - Увімкнути канал 1 + + Send to active instrument-track + З'єднати з активним інструментом-доріжкою - Enable envelope 1 - Увімкнути обвідну 1 + + Open in new instrument-track/Song Editor + Відкрити в новій інструментальній доріжці/Музичному редакторі - Enable envelope 1 loop - Увімкнти повтор обвідної 1 + + Open in new instrument-track/B+B Editor + Відкрити в новій інструментальній доріжці/Біт + Бас редакторі - Enable sweep 1 - Увімкнути розгортку 1 + + Loading sample + Завантаження запису - Sweep amount - Кількість розгортки + + Please wait, loading sample for preview... + Будь-ласка почекайте, запис завантажується для перегляду ... - Sweep rate - Темп розгортки + + Error + Помилка - 12.5% Duty cycle - 12.5% Робочого циклу + + does not appear to be a valid + не являється дійсним - 25% Duty cycle - 25% Робочого циклу + + file + файл - 50% Duty cycle - 50% Робочого циклу + + --- Factory files --- + --- Заводські файли --- + + + FlangerControls - 75% Duty cycle - 75% Робочого циклу + + Delay Samples + Затримка семплів - Enable channel 2 - Увімкнути канал 2 + + Lfo Frequency + Частота LFO - Enable envelope 2 - Увімкнути обвідну 2 + + Seconds + Секунд - Enable envelope 2 loop - Увімкнти повтор обвідної 2 + + Regen + Перегенерувати - Enable sweep 2 - Увімкнути розгортку 2 + + Noise + Шум - Enable channel 3 - Увімкнути канал 3 + + Invert + Інвертувати + + + FlangerControlsDialog - Noise Frequency - Частота шуму + + DELAY + ЗАТРИМ - Frequency sweep - Частота темпу + + Delay Time: + Час затримки: - Enable channel 4 - Увімкнути канал 4 + + RATE + ЧАСТ - Enable envelope 4 - Увімкнути обвідну 4 + + Period: + Період: - Enable envelope 4 loop - Увімкнти повтор обвідної 4 + + AMNT + ГЛИБ - Quantize noise frequency when using note frequency - Квантування частоту шуму при використанні частоти ноти + + Amount: + Величина: - Use note frequency for noise - Використовувати частоту ноти для шуму + + FDBK + FDBK - Noise mode - Форма шуму + + Feedback Amount: + Величина повернення: - Vibrato - Вібрато + + NOISE + ШУМ - Master volume - Основна гучність + + White Noise Amount: + Об'єм білого шуму: + + + + Invert + Інвертувати - OpulenzInstrument + FxLine - Patch - Патч + + Channel send amount + Величина відправки каналу - Op 1 attack - + + The FX channel receives input from one or more instrument tracks. + It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. + +In order to route the channel to another channel, select the FX channel and click on the "send" button on the channel you want to send to. The knob under the send button controls the level of signal that is sent to the channel. + +You can remove and move FX channels in the context menu, which is accessed by right-clicking the FX channel. + + Канал ефектів (ЕФ) отримує сигнал на вхід від однієї або декількох інструментальних доріжок. +У свою чергу його можна підключити до декількох інших каналам ефектів. ЛММС автоматично запобігає нескінченному повтореню і не дозволяє створювати з'єднання, які приведуть до нескінченного повторення. +Щоб з'єднати один канал з іншим, виберіть канал ефектів і натисніть кнопку надіслати на каналі, в який потрібно надіслати. Регулятор під кнопкою "надіслати" контролює рівень сигналу, що посилається на канал. +Можна прибирати і рухати канали ефектів через контекстне меню, якщо натиснути правою кнопкою миші по каналу ефектів. - Op 1 decay - + + Move &left + Рухати вліво &L - Op 1 sustain - + + Move &right + Рухати вправо &R - Op 1 release - + + Rename &channel + Перейменувати канал &C - Op 1 level - + + R&emove channel + Видалити канал &e - Op 1 level scaling - + + Remove &unused channels + Видалити канали які &не використовуються + + + FxMixer - Op 1 frequency multiplier - + + Master + Головний - Op 1 feedback - + + + + FX %1 + Ефект %1 - Op 1 key scaling rate - + + Volume + Гучність - Op 1 percussive envelope - + + Mute + Тиша - Op 1 tremolo - + + Solo + Соло + + + FxMixerView - Op 1 vibrato - + + FX-Mixer + Мікшер Ефектів - Op 1 waveform - + + FX Fader %1 + Повзунок Ефекту %1 - Op 2 attack - + + Mute + Тиша - Op 2 decay - + + Mute this FX channel + Тиша на цьому каналі Ефекту - Op 2 sustain - + + Solo + Соло - Op 2 release - + + Solo FX channel + Соло каналу ЕФ + + + FxRoute - Op 2 level - + + + Amount to send from channel %1 to channel %2 + Величина відправки з каналу %1 на канал %2 + + + GigInstrument - Op 2 level scaling - + + Bank + Банк - Op 2 frequency multiplier - + + Patch + Патч - Op 2 key scaling rate - + + Gain + Підсилення + + + GigInstrumentView - Op 2 percussive envelope - + + Open other GIG file + Відкрити інший GIG файл - Op 2 tremolo - + + Click here to open another GIG file + Натисніть, щоб відкрити інший GIG файл - Op 2 vibrato - + + Choose the patch + Вибрати патч - Op 2 waveform - + + Click here to change which patch of the GIG file to use + Натисніть для зміни використовуваного патчу GIG файлу - FM - FM + + + Change which instrument of the GIG file is being played + Змінити інструмент, який відтворює GIG файл - Vibrato depth - + + Which GIG file is currently being used + Який GIG файл зараз використовується - Tremolo depth - + + Which patch of the GIG file is currently being used + Який патч GIG файлу зараз використовується - - - OpulenzInstrumentView - Attack - Вступ + + Gain + Підсилення - Decay - Згасання + + Factor to multiply samples by + Фактор множення семплів - Release - Зменшення + + Open GIG file + Відкрити GIG файл - Frequency multiplier - Множник частоти + + GIG Files (*.gig) + GIG Файли (*.gig) - OscillatorObject + GuiApplication - Osc %1 volume - Гучність осциллятора %1 + + Working directory + Робочий каталог LMMS - Osc %1 panning - Стереобаланс для осциллятора %1 + + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. + Робочий каталог LMMS (%1) не існує. Створити його? Пізніше ви зможете змінити його через Правку -> Параметри. - Osc %1 coarse detuning - Підстроювання осциллятора %1 грубе + + Preparing UI + Підготовка користувацького інтерфейсу - Osc %1 fine detuning left - Точне підстроювання лівого каналу осциллятора %1 + + Preparing song editor + Підготовка музичного редактора - Osc %1 fine detuning right - Підстроювання правого каналу осциллятора %1 тонка + + Preparing mixer + Підготовка міксера - Osc %1 phase-offset - Зміщення фази осциллятора %1 + + Preparing controller rack + Підготовка стійки контролерів - Osc %1 stereo phase-detuning - Підстроювання стерео-фази осциллятора %1 + + Preparing project notes + Підготовка заміток проекту - Osc %1 wave shape - Гладкість сигналу осциллятора %1 - - - Modulation type %1 - Тип модуляції %1 + + Preparing beat/bassline editor + Підготовка ритм/бас редактора - Osc %1 waveform - Форма сигналу осциллятора %1 + + Preparing piano roll + Підготовка нотного редактора - Osc %1 harmonic - Осц %1 гармонійний + + Preparing automation editor + Підготовка редактора автоматизації - PatchesDialog + InstrumentFunctionArpeggio - Qsynth: Channel Preset - Q-Синтезатор: Канал передустановлено + + Arpeggio + Арпеджіо - Bank selector - Селектор банку + + Arpeggio type + Тип арпеджіо - Bank - Банк + + Arpeggio range + Діапазон арпеджіо - Program selector - Селектор програм + + Cycle steps + Зациклити такти - Patch - Патч + + Skip rate + Частота пропуску - Name - І'мя + + Miss rate + Частота пропуску - OK - ОК + + Arpeggio time + Період арпеджіо - Cancel - Скасувати + + Arpeggio gate + Шлюз арпеджіо - - - PatmanView - Loop - Повтор + + Arpeggio direction + Напрямок арпеджіо - Loop mode - Режим повтору + + Arpeggio mode + Режим арпеджіо - Tune - Підлаштувати + + Up + Вгору - Tune mode - Тип підстроювання + + Down + Вниз - No file selected - Файл не вибрано + + Up and down + Вгору та вниз - Open patch file - Відкрити патч-файл + + Down and up + Вниз та вгору - Patch-Files (*.pat) - Патч-файли (*.pat) + + Random + Випадково + + + + Free + Вільно - Open patch - + + Sort + Сортувати + + + + Sync + Синхронізувати - PeakControllerEffectControlDialog + InstrumentFunctionArpeggioView - BASE - БАЗА + + ARPEGGIO + ARPEGGIO - Modulation amount: - Глибина модуляції: + + An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. + Арпеджіо - різновид виконання акордів на фортепіано і струнних інструментах, який оживляє звучання. Струни таких інструментів граються перебором по акордах, як на арфі, коли звуки акорду слідують один за іншим. Типові арпеджіо - мажорні та мінорні тріади, серед яких можна вибрати й інші. - Attack: - Вступ: + + RANGE + RANGE - Release: - Зменшення: + + Arpeggio range: + Діапазон арпеджіо: - AMNT - ГЛИБ + + octave(s) + Октав(а/и) - MULT - МНОЖ + + Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. + Використовуйте цю ручку, щоб встановити діапазон арпеджіо (в октавах). Обраний тип арпеджіо охоплюватиме вказану кількість октав. - ATCK - ВСТУП + + CYCLE + ЦИКЛ - DCAY - ЗГАС + + Cycle notes: + Зациклити ноти: - Treshold: - Поріг: + + note(s) + нота(и) - TRSH - + + Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. + - Base: - + + SKIP + ПРОПУСК - Amount multiplicator: - + + Skip rate: + Частота пропуску: - Mute output - Заглушити вивід + + + + % + % - Absolute value - + + The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. + - - - PeakControllerEffectControls - Base value - Опорне значення + + MISS + ПРОПУСК - Modulation amount - Глибина модуляції + + Miss rate: + Частота пропуску: - Mute output - Заглушити вивід + + The miss function will make the arpeggiator miss the intended note. + Функція пропуску змусить арпеджіатор пропустити бажану ноту. - Attack - Вступ + + TIME + TIME - Release - Зменшення + + Arpeggio time: + Період арпеджіо: - Treshold - Поріг + + ms + мс - Absolute value - + + Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. + Регулювання періоду арпеджіо - час (в мілісекундах), який має звучати кожен тон арпеджіо. - Amount multiplicator - + + GATE + GATE - - - QWidget - Name: - І'мя: + + Arpeggio gate: + Шлюз арпеджіо: - Maker: - Розробник: + + Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. + Регулювання шлюзу арпеджіо, показує процентну частку кожного тону арпеджіо, яка буде відтворена. Простий спосіб створювати стаккато-арпеджіо. - Copyright: - Авторське право: + + Chord: + Акорд: - Requires Real Time: - Потрібна обробка в реальному часі: + + Direction: + Напрямок: - Yes - Так + + Mode: + Режим: + + + InstrumentFunctionNoteStacking - No - Ні + + octave + Октава - Real Time Capable: - Робота в реальному часі: + + + Major + Мажорний - In Place Broken: - Замість зламаного: + + Majb5 + Majb5 - Channels In: - Канали в: + + minor + мінорний - Channels Out: - Канали з: + + minb5 + minb5 - File: - Файл: + + sus2 + sus2 - File: %1 - Файл: %1 + + sus4 + sus4 - - - ReverbSCControlDialog - Input - Ввід + + aug + aug - Size - + + augsus4 + augsus4 - Size: - + + tri + tri - Color - + + 6 + 6 - Color: - + + 6sus4 + 6sus4 - Output - Вивід + + 6add9 + 6add9 - Input gain: - Вхідне підсилення: + + m6 + m6 - Output gain: - Вихідне підсилення: + + m6add9 + m6add9 - - - ReverbSCControls - Size - + + 7 + 7 - Color - + + 7sus4 + 7sus4 - Input gain - Вхідне підсилення + + 7#5 + 7#5 - Output gain - Вихідне підсилення + + 7b5 + 7b5 - - - SpectrumAnalyzerControlDialog - Linear spectrum - Лінійний спектр + + 7#9 + 7#9 - Linear Y axis - Лінійна вісь ординат + + 7b9 + 7b9 - - - SpectrumAnalyzerControls - Linear spectrum - Лінійний спектр + + 7#5#9 + 7#5#9 - Linear Y axis - Лінійна вісь ординат + + 7#5b9 + 7#5b9 - Channel mode - Режим каналу + + 7b5b9 + 7b5b9 - - - TrackContainer - Cancel - Скасувати + + 7add11 + 7add11 - Please wait... - Зачекайте будь-ласка ... + + 7add13 + 7add13 - Importing MIDI-file... - Імпортую файл MIDI... + + 7#11 + 7#11 - - - TripleOscillatorView - Synchronize oscillator 1 with oscillator 2 - Синхронізувати 1 осциллятор по 2 + + Maj7 + Maj7 - Synchronize oscillator 2 with oscillator 3 - Синхронізувати осциллятор 2 і 3 + + Maj7b5 + Maj7b5 - Osc %1 volume: - Гучність осциллятора %1: + + Maj7#5 + Maj7#5 - Osc %1 panning: - Баланс для осциллятора %1: + + Maj7#11 + Maj7#11 - Osc %1 coarse detuning: - Грубе підстроювання осциллятора %1: + + Maj7add13 + Maj7add13 - semitones - півтон(а,ів) + + m7 + m7 - Osc %1 fine detuning left: - Точне підстроювання лівого каналу осциллятора %1: + + m7b5 + m7b5 - cents - Відсотки + + m7b9 + m7b9 - Osc %1 fine detuning right: - Точна підстройка правого канала осциллятора %1: + + m7add11 + m7add11 - Osc %1 phase-offset: - Зміщення фази осциллятора %1: + + m7add13 + m7add13 - degrees - градуси + + m-Maj7 + m-Maj7 - Osc %1 stereo phase-detuning: - Підстроювання стерео фази осциллятора %1: + + m-Maj7add11 + m-Maj7add11 - Modulate phase of oscillator 1 by oscillator 2 - + + m-Maj7add13 + m-Maj7add13 - Modulate amplitude of oscillator 1 by oscillator 2 - + + 9 + 9 - Mix output of oscillators 1 & 2 - + + 9sus4 + 9sus4 - Modulate frequency of oscillator 1 by oscillator 2 - + + add9 + add9 - Modulate phase of oscillator 2 by oscillator 3 - + + 9#5 + 9#5 - Modulate amplitude of oscillator 2 by oscillator 3 - + + 9b5 + 9b5 - Mix output of oscillators 2 & 3 - + + 9#11 + 9#11 - Modulate frequency of oscillator 2 by oscillator 3 - + + 9b13 + 9b13 - Sine wave - Синусоїда + + Maj9 + Maj9 - Triangle wave - + + Maj9sus4 + Maj9sus4 - Saw wave - Зигзаг + + Maj9#5 + Maj9#5 - Square wave - + + Maj9#11 + Maj9#11 - Moog-like saw wave - + + m9 + m9 - Exponential wave - Експоненціальна хвиля + + madd9 + madd9 - White noise - Білий шум + + m9b5 + m9b5 - User-defined wave - + + m9-Maj7 + m9-Maj7 - - - VestigeInstrumentView - Show/hide GUI - Показати / приховати інтерфейс + + 11 + 11 - Turn off all notes - Вимкнути всі ноти + + 11b9 + 11b9 - DLL-files (*.dll) - Бібліотеки DLL (*.dll) + + Maj11 + Maj11 - EXE-files (*.exe) - Програми EXE (*.exe) + + m11 + m11 - Previous (-) - Попередній <-> + + m-Maj11 + m-Maj11 - Save preset - Зберегти передустановку + + 13 + 13 - Next (+) - Наступний <+> + + 13#9 + 13#9 - Preset - Передустановка + + 13b9 + 13b9 - by - від + + 13b5b9 + 13b5b9 - - VST plugin control - - Управління VST плагіном + + Maj13 + Maj13 - Open VST plugin - + + m13 + m13 - Control VST plugin from LMMS host - + + m-Maj13 + m-Maj13 - Open VST plugin preset - + + Harmonic minor + Гармонійний мінор - No VST plugin loaded - + + Melodic minor + Мелодійний мінор - - - VstEffectControlDialog - Show/hide - Показати/Сховати + + Whole tone + Цілий тон - Previous (-) - Попередній <-> + + Diminished + Понижений - Next (+) - Наступний <+> + + Major pentatonic + Пентатонік major - Save preset - Зберегти налаштування + + Minor pentatonic + Пентатонік major - Effect by: - Ефекти по: + + Jap in sen + Япон in sen - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + + Major bebop + Major Бібоп - Control VST plugin from LMMS host - + + Dominant bebop + Домінтний бібоп - Open VST plugin preset - + + Blues + Блюз - - - VstPlugin - Loading plugin - Завантаження модуля + + Arabic + Арабська - Open Preset - Відкрити предустановку + + Enigmatic + Загадкова - Vst Plugin Preset (*.fxp *.fxb) - Передустановка VST плагіна (*.fxp *.fxb) + + Neopolitan + Неаполітанська - : default - : основні + + Neopolitan minor + Неаполітанський мінор - " - " + + Hungarian minor + Угорський мінор - ' - ' + + Dorian + Дорійська - Save Preset - Зберегти предустановку + + Phrygian + Фрігійський - .fxp - .fxp + + Lydian + Лідійська - .FXP - .FXP + + Mixolydian + Міксолідійська - .FXB - .FXB + + Aeolian + Еолійська - .fxb - .fxb + + Locrian + Локріанська - Please wait while loading VST plugin... - Будь ласка, зачекайте доки завантажується VST плагін ... + + Minor + Мінор - The VST plugin %1 could not be loaded. - VST плагін %1 не може бути завантажено. + + Chromatic + Хроматична - - - WatsynInstrument - Volume A1 - Гучність A1 + + Half-Whole Diminished + Напів-зниження - Volume A2 - Гучність A2 + + 5 + 5 - Volume B1 - Гучність B1 + + Phrygian dominant + Фрігійська домінанта - Volume B2 - Гучність B2 + + Persian + Перська - Panning A1 - Баланс A1 + + Chords + Акорди - Panning A2 - Баланс A2 + + Chord type + Тип акорду - Panning B1 - Баланс B1 + + Chord range + Діапазон акорду + + + InstrumentFunctionNoteStackingView - Panning B2 - Баланс B2 + + STACKING + Стиковка - Freq. multiplier A1 - Множник частоти A1 + + Chord: + Акорд: - Freq. multiplier A2 - Множник частоти A2 + + RANGE + ДІАПАЗОН - Freq. multiplier B1 - Множник частоти B1 + + Chord range: + Діапазон акорду: - Freq. multiplier B2 - Множник частоти B2 + + octave(s) + Октав[а/и] - Left detune A1 - Ліве підстроювання A1 + + Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. + Ця ручка змінює діапазон акорду, який буде містити вказане число октав. + + + InstrumentMidiIOView - Left detune A2 - Ліве підстроювання A2 + + ENABLE MIDI INPUT + УВІМК MIDI ВХІД - Left detune B1 - Ліве підстроювання B1 + + + CHANNEL + CHANNEL - Left detune B2 - Ліве підстроювання B2 + + + VELOCITY + VELOCITY - Right detune A1 - Праве підстроювання A1 + + ENABLE MIDI OUTPUT + УВІМК MIDI ВИВІД - Right detune A2 - Праве підстроювання A2 + + PROGRAM + PROGRAM - Right detune B1 - Праве підстроювання B1 + + NOTE + NOTE - Right detune B2 - Праве підстроювання B2 + + MIDI devices to receive MIDI events from + MiDi пристрої-джерела подій - A-B Mix - A-B Мікс + + MIDI devices to send MIDI events to + MiDi пристрої для відправки подій на них - A-B Mix envelope amount - A-B Мікс кіл. обвідної + + CUSTOM BASE VELOCITY + СВОЯ БАЗОВА ШВИДКІСТЬ - A-B Mix envelope attack - A-B Мікс атаки обвідної + + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity + Визначає базову швидкість нормальізаціі для MiDi інструментів при гучності ноти 100% - A-B Mix envelope hold - A-B Мікс утримання обвідної + + BASE VELOCITY + БАЗОВА ШВИДКІСТЬ + + + InstrumentMiscView - A-B Mix envelope decay - A-B Мікс згасання обвідної + + MASTER PITCH + ОСНОВНА ТОНАЛЬНІСТЬ - A1-B2 Crosstalk - Перехресні перешкоди A1-B2 + + Enables the use of Master Pitch + Включає використання основної тональності + + + InstrumentSoundShaping - A2-A1 modulation - Модуляція A2-A1 + + VOLUME + VOLUME - B2-B1 modulation - Модуляція B2-B1 + + Volume + Гучність - Selected graph - Обраний графік + + CUTOFF + CUTOFF - - - WatsynView - Select oscillator A1 - Виберіть генератор A1 + + + Cutoff frequency + Зріз частоти - Select oscillator A2 - Виберіть генератор A2 + + RESO + RESO - Select oscillator B1 - Виберіть генератор B1 + + Resonance + Резонанс - Select oscillator B2 - Виберіть генератор B2 + + Envelopes/LFOs + Обвідні/LFO - Mix output of A2 to A1 - Змішати виходи A2 до A1 + + Filter type + Тип фільтру - Mix output of B2 to B1 - Змішати виходи В2 до В1 + + Q/Resonance + Кіл./Резонансу - Draw your own waveform here by dragging your mouse on this graph. - Тут ви можете малювати власний сигнал. + + LowPass + Низ.ЧФ - Load waveform - Завантаження форми звуку + + HiPass + Вис.ЧФ - Phase left - Фаза зліва + + BandPass csg + Серед.ЧФ csg - Phase right - Фаза праворуч + + BandPass czpg + Серед.ЧФ czpg - Normalize - Нормалізувати + + Notch + Смуго-загороджуючий - Invert - Інвертувати + + Allpass + Всі проходять - Smooth - Згладити + + Moog + Муг - Sine wave - Синусоїда + + 2x LowPass + 2х Низ.ЧФ - Triangle wave - Трикутна хвиля + + RC LowPass 12dB + RC Низ.ЧФ 12дБ - Square wave - Квадратна хвиля + + RC BandPass 12dB + RC Серед.ЧФ 12 дБ - Volume - Гучність + + RC HighPass 12dB + RC Вис.ЧФ 12дБ - Panning - Баланс + + RC LowPass 24dB + RC Низ.ЧФ 24дБ - Freq. multiplier - Множник частоти + + RC BandPass 24dB + RC Серед.ЧФ 24дБ - Left detune - Ліве підстроювання + + RC HighPass 24dB + RC Вис.ЧФ 24дБ - cents - відсотків + + Vocal Formant Filter + Фільтр Вокальної форманти - Right detune - Праве підстроювання + + 2x Moog + 2x Муг - A-B Mix - A-B Мікс + + SV LowPass + SV Низ.ЧФ - Mix envelope amount - Мікс кількості обвідної + + SV BandPass + SV Серед.ЧФ - Mix envelope attack - A-B Мікс вступу обвідної + + SV HighPass + SV Вис.ЧФ - Mix envelope hold - A-B Мікс утримання обвідної + + SV Notch + SV Смуго-заг - Mix envelope decay - A-B Мікс згасання обвідної + + Fast Formant + Швидка форманта - Crosstalk - Перехід + + Tripole + Тріполі + + + + InstrumentSoundShapingView + + + TARGET + ЦЕЛЬ + + + + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + Ця вкладка дозволяє вам налаштувати обвідні. Вони дуже важливі для налаштування звучання. +Наприклад, за допомогою обвідної гучності ви можете задати залежність гучності звучання від часу. Якщо вам знадобиться емулювати м'які струнні, просто задайте більше часу наростання і зникнення звуку. За допомогою обвідних і низькочастотного осциллятора (LFO) ви в кілька кліків миші зможете створити просто неймовірні звуки! - Modulate amplitude of A1 by output of A2 - + + FILTER + ФИЛЬТР - Ring modulate A1 and A2 - + + Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. + Здесь вы можете выбрать фильтр для дорожки этого инструмента. Фильтры могут довольно сильно менять звучание. - Modulate phase of A1 by output of A2 - + + FREQ + ЧАСТ - Modulate amplitude of B1 by output of B2 - + + cutoff frequency: + Срез частот: - Ring modulate B1 and B2 - + + Hz + Гц - Modulate phase of B1 by output of B2 - + + Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... + Эта ручка устанавливает частоту среза для выбранного фильтра. К примеру, ФНЧ будет срезать сигнал на частотах выше частоты среза, полосно-пропускающий фильтр будет хорошо пропускать сигнал только на заданной частоте и так далее... - Load a waveform from a sample file - + + RESO + РЕЗО - Shift phase by -15 degrees - + + Resonance: + Підсилення: - Shift phase by +15 degrees - + + Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. + Эта ручка задаёт количество резонанса для фильтра, этим определяется насколько нужно усилить ближайшие к отрезанным частоты. - Saw wave - Зигзаг + + Envelopes, LFOs and filters are not supported by the current instrument. + Обвідні, LFO і фільтри не підтримуються цим інструментом. - Xpressive + InstrumentTrack - Selected graph - Обраний графік + + With this knob you can set the volume of the opened channel. + Регулювання гучності поточного каналу. - A1 - + + + unnamed_track + безіменна_доріжка - A2 - + + Base note + Опорна нота - A3 - + + Volume + Гучність - W1 smoothing - + + Panning + Стерео - W2 smoothing - + + Pitch + Тональність - W3 smoothing - + + Pitch range + Діапазон тональності - Panning 1 - + + FX channel + Канал ЕФ - Panning 2 - + + Master Pitch + Основна тональність - Rel trans - + + + Default preset + Основна предустановка - XpressiveView + InstrumentTrackView - Draw your own waveform here by dragging your mouse on this graph. - Тут ви можете малювати власний сигнал. + + Volume + Гучність - Select oscillator W1 - + + Volume: + Гучність: - Select oscillator W2 - + + VOL + ГУЧН - Select oscillator W3 - + + Panning + Баланс - Select output O1 - + + Panning: + Баланс: - Select output O2 - + + PAN + БАЛ - Open help window - + + MIDI + MIDI - Sine wave - Синусоїда + + Input + Вхід - Moog-saw wave - + + Output + Вихід - Exponential wave - Експоненціальна хвиля + + FX %1: %2 + ЕФ %1: %2 + + + InstrumentTrackWindow - Saw wave - Зигзаг + + GENERAL SETTINGS + ОСНОВНІ НАЛАШТУВАННЯ - User-defined wave - + + Use these controls to view and edit the next/previous track in the song editor. + Використовуйте ці елементи керування для перегляду і редагування наступного/попереднього треку в музичному редакторі. - Triangle wave - + + Instrument volume + Гучність інструменту - Square wave - + + Volume: + Гучність: - White noise - Білий шум + + VOL + ГУЧН - WaveInterpolate - + + Panning + Баланс - ExpressionValid - + + Panning: + Стереобаланс: - General purpose 1: - + + PAN + БАЛ - General purpose 2: - + + Pitch + Тональність - General purpose 3: - + + Pitch: + Тональність: - O1 panning: - + + cents + відсотків - O2 panning: - + + PITCH + ТОН - Release transition: - + + Pitch range (semitones) + Діапазон тональності (півтону) - Smoothness - + + RANGE + ДІАПАЗОН - - - ZynAddSubFxInstrument - Portamento - Портаменто + + FX channel + Канал ЕФ - Bandwidth - Ширина смуги + + FX + ЕФ - Filter frequency - + + Save current instrument track settings in a preset file + Зберегти поточну інструментаьную доріжку в файл предустановок - Filter resonance - + + Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. + Нитисніть тут, щоб зберегти налаштування поточної інстр. доріжки в файл предустановок. Пізніше можна завантажити цю передустановку подвійним кліком в браузері предустановок. - FM gain - + + SAVE + ЗБЕРЕГТИ - Resonance center frequency - + + Envelope, filter & LFO + Обвідна, фільтр & LFO - Resonance bandwidth - + + Chord stacking & arpeggio + Укладання акордів & арпеджіо - Forward MIDI control change events - + + Effects + Ефекти - - - ZynAddSubFxView - Show GUI - Показати інтерфейс + + MIDI settings + Параметри MIDI - Portamento: - Портаменто: + + Miscellaneous + Різне - PORT - PORT + + Save preset + Зберегти передустановку - FREQ - FREQ + + XML preset file (*.xpf) + XML файл налаштувань (*.xpf) - RES - RES + + Plugin + Модуль + + + Knob - Bandwidth: - Смуга пропускання: + + Set linear + Встановити лінійний - BW - BW + + Set logarithmic + Встановити логарифмічний - FM GAIN - FM GAIN + + Please enter a new value between -96.0 dBFS and 6.0 dBFS: + Введіть нове значення від -96,0 дБFS до 6,0 дБFS: - Resonance center frequency: - Частота центру резонансу: + + Please enter a new value between %1 and %2: + Введіть нове значення від %1 до %2: + + + LadspaControl - RES CF - RES CF + + Link channels + Зв'язати канали + + + LadspaControlDialog - Resonance bandwidth: - Ширина смуги резонансу: + + Link Channels + Зв'язати канали - RES BW - RES BW + + Channel + Канал + + + LadspaControlView - Filter frequency: - + + Link channels + Зв'язати канали - Filter resonance: - + + Value: + Значення: - FM gain: - + + Sorry, no help available. + Вибачте, довідки немає. + + + LadspaEffect - Forward MIDI control changes - + + Unknown LADSPA plugin %1 requested. + Запитаний невідомий модуль LADSPA «%1». - audioFileProcessor + LcdSpinBox - Amplify - Підсилення + + Please enter a new value between %1 and %2: + Введіть нове значення від %1 до %2: + + + LeftRightNav - Start of sample - Початок запису + + + + Previous + Попередній - End of sample - Кінець запису + + + + Next + Наступний - Reverse sample - Перевернути запис + + Previous (%1) + Попередній (%1) - Stutter - Заїкання + + Next (%1) + Наступний (%1) + + + LfoController - Loopback point - Точка повернення з повтору + + LFO Controller + Контролер LFO - Loop mode - Режим повтору + + Base value + Основне значення - Interpolation mode - Режим Інтерполяції + + Oscillator speed + Швидкість хвилі - None - Нічого + + Oscillator amount + Розмір хвилі - Linear - Лінійний + + Oscillator phase + Фаза хвилі - Sinc - Синхронізований + + Oscillator waveform + Форма хвилі - Sample not found: %1 - Запис не знайдено: %1 + + Frequency Multiplier + Множник частоти - bitInvader + LfoControllerDialog - Sample length - + + LFO + LFO - - - bitInvaderView - Sine wave - Синусоїда + + LFO Controller + Контролер LFO - Triangle wave - Трикутник + + BASE + БАЗА - Saw wave - Зигзаг + + Base amount: + Базове значення: - Square wave - Квадрат + + todo + доробити - Interpolation - Інтерполяція + + SPD + ШВИД - Normalize - Нормалізувати + + LFO-speed: + Швидкість LFO: - Draw your own waveform here by dragging your mouse on this graph. - Тут ви можете малювати власний сигнал. + + Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. + Ця ручка встановлює швидкість LFO. Чим більше значення, тим більша частота осциллятора. - Sample length - + + AMNT + ГЛИБ - White noise - Білий шум + + Modulation amount: + Кількість модуляції: - User-defined wave - + + Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. + Ця ручка встановлює глибину модуляції для LFO. Чим більше значення, тим більшою мірою обрана характеристика (н-д, гучність або частота зрізу) буде залежати від ГНЧ (LFO). - Smooth waveform - Згладжений сигнал + + PHS + ФАЗА - - - dynProcControlDialog - INPUT - ВХІД + + Phase offset: + Зсув фази: - Input gain: - Вхідне підсилення: + + degrees + градуси - OUTPUT - ВИХІД + + With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + Ця ручка встановлює початкову фазу НизькоЧастотного Осциллятора (LFO), т. б. Точку, з якої осциллятор починає виробляти сигнал. Наприклад, якщо ви задали синусоїдальну форму сигналу і початкову фазу 180º, хвиля спочатку піде вниз, а не вгору, так само як і для квадратної хвилі. - Output gain: - Вихідне підсилення: + + Click here for a sine-wave. + Синусоїда. - ATTACK - ВСТУП + + Click here for a triangle-wave. + Згенерувати трикутний сигнал. - Peak attack time: - Час пікової атаки: + + Click here for a saw-wave. + Згенерувати зигзаг. - RELEASE - ЗМЕНШЕННЯ + + Click here for a square-wave. + Згенерувати квадратний сигнал. - Peak release time: - Час відпуску піку: + + Click here for a moog saw-wave. + Натисніть для зигзагоподібної муг-хвилі. - Process based on the maximum of both stereo channels - Процес заснований на максимумі від обох каналів + + Click here for an exponential wave. + Генерувати експонентний сигнал. - Process based on the average of both stereo channels - Процес заснований на середньому обох каналів + + Click here for white-noise. + Згенерувати білий шум. - Process each stereo channel independently - Обробляє кожен стерео канал незалежно + + Click here for a user-defined shape. +Double click to pick a file. + Натисніть тут для визначення своєї форми. +Подвійне натискання для вибору файлу. + + + LmmsCore - Reset wavegraph - + + Generating wavetables + Генерування синтезатора звукозаписів - Smooth wavegraph - + + Initializing data structures + Ініціалізація структур даних - Increase wavegraph amplitude by 1 dB - + + Opening audio and midi devices + Відкриття аудіо та міді пристроїв - Decrease wavegraph amplitude by 1 dB - + + Launching mixer threads + Запуск потоків міксера + + + MainWindow - Stereo mode: maximum - + + Configuration file + Файл налаштувань - Stereo mode: average - + + Error while parsing configuration file at line %1:%2: %3 + Помилка під час обробки файлу налаштувань в рядку %1:%2:%3 - Stereo mode: unlinked - + + Could not open file + Не можу відкрити файл - - - dynProcControls - Input gain - Вхідне підсилення + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + Не вдалось відкрити файл %1 для запису. +Перевірте, чи маєте ви права на запис файлу і каталог що його містить і спробуйте знову! - Output gain - Вихідне підсилення + + Project recovery + Відновлення проекту - Attack time - Час вступу + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + Присутній файл відновлення. Схоже, остання сесія не закінчилася належним чином або інший екземпляр LMMS вже запущений. Ви хочете, відновити проект цієї сесії? - Release time - Час зменшення + + + + Recover + Відновлення - Stereo mode - Стерео режим + + Recover the file. Please don't run multiple instances of LMMS when you do this. + Відновлення файлу. Будь ласка, не запускайте кілька копій LMMS під час цієї операції. - - - kickerInstrument - Start frequency - Початкова частота + + + + Discard + Відкинути - End frequency - Кінцева частота + + Launch a default session and delete the restored files. This is not reversible. + Запуск за замовчуванням з видаленням файла відновлення. Ця дія не відворотня. - Gain - Підсилення + + Version %1 + Версія %1 - Length - Довжина + + Preparing plugin browser + Підготовка браузера плагінів - Noise - Шум + + Preparing file browsers + Підготовка переглядача файлів - Click - Натисніть + + My Projects + Мої проекти - Start from note - Почати з замітки + + My Samples + Мої записи - End to note - Закінчити заміткою + + My Presets + Мої передустановки - Start distortion - + + My Home + Моя домашня тека - End distortion - + + Root directory + Кореневий каталог - Envelope slope - + + Volumes + Гучності - Frequency slope - + + My Computer + Мій комп'ютер - - - kickerInstrumentView - Start frequency: - Початкова частота: + + Loading background artwork + Завантаження фонового зображення - End frequency: - Кінцева частота: + + &File + &Файл - Gain: - Підсилення: + + &New + &N Новий - Click: - Натиснення: + + New from template + Новий проект по шаблону - Noise: - Шум: + + &Open... + &O Відкрити... - Frequency slope: - + + &Recently Opened Projects + &Нещодавно відкриті проекти - Envelope length: - + + &Save + &S Зберегти - Envelope slope: - + + Save &As... + &A Зберегти як... - Start distortion: - + + Save as New &Version + Зберегти як нову &Версію - End distortion: - + + Save as default template + Зберегти як шаблон за замовчуванням - - - ladspaBrowserView - Available Effects - Доступні ефекти + + Import... + Імпорт... - Unavailable Effects - Недоступні ефекти + + E&xport... + &X Експорт ... - Instruments - Інструменти + + E&xport Tracks... + &Експортувати треки ... - Analysis Tools - Аналізатори + + Export &MIDI... + Експорт в &MIDI ... - Don't know - Невідомі + + &Quit + &Q Вийти - Type: - Тип: + + &Edit + &E Редагування - - - ladspaDescription - Plugins - Модулі + + Undo + Скасувати - Description - Опис + + Redo + Повторити - - - ladspaPortDialog - Ports - Порти + + Settings + Параметри - Name - І'мя + + &View + &V Перегляд - Rate - Частота вибірки + + &Tools + &T Сервіс - Direction - Напрямок + + &Help + &H Довідка - Type - Тип + + Online Help + Онлайн Допомога - Min < Default < Max - Менше < Стандарт <Більше + + Help + Довідка - Logarithmic - Логарифмічний + + What's This? + Що це? - SR Dependent - Залежність від SR + + About + Про програму - Audio - Аудіо + + Create new project + Створити новий проект - Control - Управління + + Create new project from template + Створити новий проект по шаблону - Input - Ввід + + Open existing project + Відкрити існуючий проект - Output - Вивід + + Recently opened projects + Нещодавні проекти - Toggled - Увімкнено + + Save current project + Зберегти поточний проект - Integer - Ціле + + Export current project + Експорт проекту - Float - Дробове + + What's this? + Що це? - Yes - Так + + Toggle metronome + Переключити метроном - - - lb302Synth - VCF Cutoff Frequency - Частота зрізу VCF + + Show/hide Song-Editor + Показати/сховати музичний редактор - VCF Resonance - Посилення VCF + + By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. + Показати чи сховати музичний редактор. З його допомогою ви можете редагувати композицію і задавати час відтворення кожної доріжки. +Також ви можете вставляти і пересувати записи прямо у списку відтворення. - VCF Envelope Mod - Модуляція обвідної VCF + + Show/hide Beat+Bassline Editor + Показати/сховати ритм-бас редактор - VCF Envelope Decay - Спад обвідної VCF + + By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. + Показати чи сховати ритм-бас редактор. Він необхідний для установки ритму, відкриття, додавання і видалення каналів, а також вирізання, копіювання і вставки ритм-бас шаблонів і схожих речей. - Distortion - Спотворення + + Show/hide Piano-Roll + Показати/сховати нотний редактор - Waveform - Форма хвилі + + Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. + Запуск редатора нот. З його допомогою ви можете легко редагувати мелодії. - Slide Decay - Зміщення згасання + + Show/hide Automation Editor + Показати/сховати редактор автоматизації - Slide - Зміщення + + Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. + Показати / сховати вікно редактора автоматизації. З його допомогою ви можете легко редагувати динаміку обраних величин. - Accent - Акцент + + Show/hide FX Mixer + Показати/сховати мікшер ЕФ - Dead - Глухо + + Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. + Сховати / показати мікшер ефектів. Він є потужним інструментом для управління ефектами. Ви можете вставляти ефекти в різні канали. - 24dB/oct Filter - 24дБ/окт фільтр + + Show/hide project notes + Показати/сховати замітки до проекту - - - lb302SynthView + + Click here to show or hide the project notes window. In this window you can put down your project notes. + Ця кнопка показує / ховає вікно з нотатками. У цьому вікні ви можете поміщати будь-які коментарі до своєї композиції. + + + + Show/hide controller rack + Показати/сховати керування контролерами + + + + Untitled + Без назви + + + + Recover session. Please save your work! + Відновлення сесії. Будь ласка, збережіть свою роботу! + + + + LMMS %1 + LMMS %1 + + + + Recovered project not saved + Відновлений проект не збережено + + + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + Цей проект буво відновлено з попередньої сесії. В даний час він не збережений і буде втрачений, якщо ви його не збережете. Ви хочете, зберегти його зараз? + + + + Project not saved + Проект не збережений + + + + The current project was modified since last saving. Do you want to save it now? + Проект був змінений. Зберегти його зараз? + + + + Open Project + Відкрити проект + + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + + Save Project + Зберегти проект + + + + LMMS Project + LMMS проект + + + + LMMS Project Template + Шаблон LMMS проекту + + + + Save project template + Зберегти шаблон проекту + + + + Overwrite default template? + Переписати шаблон за замовчуванням? + + + + This will overwrite your current default template. + Це перезапише поточний шаблон за замовчуванням. + + + + Help not available + Довідка недоступна + + + + Currently there's no help available in LMMS. +Please visit http://lmms.sf.net/wiki for documentation on LMMS. + Поки що довідка для LMMS не написана. +Ймовірно, Ви зможете знайти потрібні матеріали на http://lmms.sf.net/wiki. + + + + Song Editor + Музичний редактор + + + + Beat+Bassline Editor + Редактор шаблонів + + + + Piano Roll + Нотний редактор + + + + Automation Editor + Редактор автоматизації + + + + FX Mixer + Мікшер Ефектів + + + + Project Notes + Примітки проекту + + + + Controller Rack + Стійка контролерів + + + + Volume as dBFS + Відображати гучність в децибелах + + + + Smooth scroll + Плавне прокручування + + + + Enable note labels in piano roll + Включити позначення нот у музичному редакторі + + + + MeterDialog + + + + Meter Numerator + Шкала чисел + + + + + Meter Denominator + Шкала поділів + + + + TIME SIG + ПЕРІОД + + + + MeterModel + + + Numerator + Чисельник + + + + Denominator + Знаменник + + + + MidiController + + + MIDI Controller + Контролер MIDI + + + + unnamed_midi_controller + нерозпізнаний міді контролер + + + + MidiImport + + + + Setup incomplete + Установку не завершено + + + + You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. + Ви не встановили SoundFont за замовчуванням в налаштуваннях (Правка-> Налаштування), тому після імпорту міді файлу звук відтворюватися не буде. +Вам слід завантажити основний MiDi SoundFont, вказати його в налаштуваннях і спробувати знову. + + + + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. + Ви не увімкнули підтримку програвача SoundFont2 при компіляції LMMS, він використовується для додавання основного звуку в імпортовані Міді файли, тому після імпорту цього міді файлу звуку не буде. + + + + Track + Трек + + + + MidiJack + + + JACK server down + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) + JACK-сервер не доступний + + + + The JACK server seems to be shuted down. + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) + Здається, сервер JACK відключений. + + + + MidiPort + + + Input channel + Вхід + + + + Output channel + Вихід + + + + Input controller + Контролер входу + + + + Output controller + Контролер виходу + + + + Fixed input velocity + Постійна швидкість введення + + + + Fixed output velocity + Постійна швидкість виведення + + + + Fixed output note + Постійний вихід нот + + + + Output MIDI program + Програма для виведення MiDi + + + + Base velocity + Базова швидкість + + + + Receive MIDI-events + Приймати події MIDI + + + + Send MIDI-events + Відправляти події MIDI + + + + MidiSetupWidget + + + DEVICE + ПРИСТРІЙ + + + + MonstroInstrument + + + Osc 1 Volume + Гучність осциллятора 1 + + + + Osc 1 Panning + Баланс осциллятора 1 + + + + Osc 1 Coarse detune + Грубе підстроювання осциллятора 1 + + + + Osc 1 Fine detune left + Точне підстроювання лівого каналу осциллятора 1 + + + + Osc 1 Fine detune right + Точне підстроювання правого каналу осциллятора 1 + + + + Osc 1 Stereo phase offset + Зміщення стерео-фази осциллятора 1 + + + + Osc 1 Pulse width + Довжина імпульсу осциллятора 1 + + + + Osc 1 Sync send on rise + Синхронізація підйому осциллятора 1 + + + + Osc 1 Sync send on fall + Синхронізація падіння осциллятора 1 + + + + Osc 2 Volume + Гучність осциллятора 2 + + + + Osc 2 Panning + Баланс осциллятора 2 + + + + Osc 2 Coarse detune + Грубе підстроювання осциллятора 2 + + + + Osc 2 Fine detune left + Точне підстроювання лівого каналу осциллятора 2 + + + + Osc 2 Fine detune right + Точне підстроювання правого каналу осциллятора 2 + + + + Osc 2 Stereo phase offset + Зміщення стерео-фази осциллятора 2 + + + + Osc 2 Waveform + Форма сигналу осциллятора 2 + + + + Osc 2 Sync Hard + Жорстка синхронізація осциллятора 2 + + + + Osc 2 Sync Reverse + Верерс синхронізація осциллятора 2 + + + + Osc 3 Volume + Гучність осциллятора 3 + + + + Osc 3 Panning + Баланс осциллятора 3 + + + + Osc 3 Coarse detune + Грубе підстроювання осциллятора 3 + + + + Osc 3 Stereo phase offset + Зміщення стерео-фази осциллятора 3 + + + + Osc 3 Sub-oscillator mix + Змішення суб-генератора осциллятора 3 + + + + Osc 3 Waveform 1 + Форма 1 сигналу осциллятора 3 + + + + Osc 3 Waveform 2 + Форма 2 сигналу осциллятора 3 + + + + Osc 3 Sync Hard + Жорстка синхронізація осциллятора 3 + + + + Osc 3 Sync Reverse + Верерс синхронізація осциллятора 3 + + + + LFO 1 Waveform + Форма сигналу LFO 1 + + + + LFO 1 Attack + Вступ LFO 1 + + + + LFO 1 Rate + Темп LFO 1 + + + + LFO 1 Phase + Фаза LFO 1 + + + + LFO 2 Waveform + Форма сигналу LFO 2 + + + + LFO 2 Attack + Вступ LFO 2 + + + + LFO 2 Rate + Темп LFO 2 + + + + LFO 2 Phase + Фаза LFO 2 + + + + Env 1 Pre-delay + Затримка обвідної 1 + + + + Env 1 Attack + Вступ обвідної 1 + + + + Env 1 Hold + Утримання обвідної 1 + + + + Env 1 Decay + Згасання обвідної 1 + + + + Env 1 Sustain + Витримка обвідної 1 + + + + Env 1 Release + Зменшення обвідної 1 + + + + Env 1 Slope + Нахил обвідної 1 + + + + Env 2 Pre-delay + Затримка обвідної 2 + + + + Env 2 Attack + Вступ обвідної 2 + + + + Env 2 Hold + Утримання обвідної 2 + + + + Env 2 Decay + Згасання обвідної 2 + + + + Env 2 Sustain + Витримка обвідної 2 + + + + Env 2 Release + Зменшення обвідної 2 + + + + Env 2 Slope + Нахил обвідної 2 + + + + Osc2-3 modulation + Модуляція осцилляторів 2-3 + + + + Selected view + Перегляд обраного + + + + Vol1-Env1 + Гучн1-Обв1 + + + + Vol1-Env2 + Гучн1-Обв2 + + + + Vol1-LFO1 + Гучн1-LFO1 + + + + Vol1-LFO2 + Гучн1-LFO2 + + + + Vol2-Env1 + Гучн2-Обв1 + + + + Vol2-Env2 + Гучн2-Обв2 + + + + Vol2-LFO1 + Гучн2-LFO1 + + + + Vol2-LFO2 + Гучн2-LFO2 + + + + Vol3-Env1 + Гучн3-Обв1 + + + + Vol3-Env2 + Гучн3-Обв2 + + + + Vol3-LFO1 + Гучн3-LFO1 + + + + Vol3-LFO2 + Гучн3-LFO2 + + + + Phs1-Env1 + Фаз1-Обв1 + + + + Phs1-Env2 + Фаз1-Обв2 + + + + Phs1-LFO1 + Фаз1-LFO1 + + + + Phs1-LFO2 + Фаз1-LFO2 + + + + Phs2-Env1 + Фаз2-Обв1 + + + + Phs2-Env2 + Фаз2-Обв2 + + + + Phs2-LFO1 + Фаз2-LFO1 + + + + Phs2-LFO2 + Фаз2-LFO2 + + + + Phs3-Env1 + Фаз3-Обв1 + + + + Phs3-Env2 + Фаз3-Обв2 + + + + Phs3-LFO1 + Фаз3-LFO1 + + + + Phs3-LFO2 + Фаз3-LFO2 + + + + Pit1-Env1 + Тон1-Обв1 + + + + Pit1-Env2 + Тон1-Обв2 + + + + Pit1-LFO1 + Тон1-LFO1 + + + + Pit1-LFO2 + Тон1-LFO2 + + + + Pit2-Env1 + Тон2-Обв1 + + + + Pit2-Env2 + Тон2-Обв2 + + + + Pit2-LFO1 + Тон2-LFO1 + + + + Pit2-LFO2 + Тон2-LFO2 + + + + Pit3-Env1 + Тон3-Обв1 + + + + Pit3-Env2 + Тон3-Обв2 + + + + Pit3-LFO1 + Тон3-LFO1 + + + + Pit3-LFO2 + Тон3-LFO2 + + + + PW1-Env1 + PW1-Обв1 + + + + PW1-Env2 + PW1-Обв2 + + + + PW1-LFO1 + PW1-LFO1 + + + + PW1-LFO2 + PW1-LFO2 + + + + Sub3-Env1 + Sub3-Обв1 + + + + Sub3-Env2 + Sub3-Обв2 + + + + Sub3-LFO1 + Sub3-LFO1 + + + + Sub3-LFO2 + Sub3-LFO2 + + + + + Sine wave + Синусоїда + + + + Bandlimited Triangle wave + Трикутна хвиля з обмеженою смугою + + + + Bandlimited Saw wave + Зигзаг хвиля з обмеженою смугою + + + + Bandlimited Ramp wave + Спадаюча хвиля з обмеженою смугою + + + + Bandlimited Square wave + Квадратна хвиля з обмеженою смугою + + + + Bandlimited Moog saw wave + Муг-зигзаг хвиля з обмеженою смугою + + + + + Soft square wave + М'яка прямокутна хвиля + + + + Absolute sine wave + Абсолютна синусоїдна хвиля + + + + + Exponential wave + Експоненціальна хвиля + + + + White noise + Білий шум + + + + Digital Triangle wave + Цифрова трикутна хвиля + + + + Digital Saw wave + Цифрова зигзаг хвиля + + + + Digital Ramp wave + Цифрова спадна хвиля + + + + Digital Square wave + Цифрова квадратна хвиля + + + + Digital Moog saw wave + Цифрова Муг-зигзаг хвиля + + + + Triangle wave + Трикутна хвиля + + + + Saw wave + Зигзаг + + + + Ramp wave + Спадна хвиля + + + + Square wave + Квадратна хвиля + + + + Moog saw wave + Муг-зигзаг хвиля + + + + Abs. sine wave + Синусоїда по модулю + + + + Random + Випадково + + + + Random smooth + Випадкове зглажування + + + + MonstroView + + + Operators view + Операторский вид + + + + The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. + +Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. + Операторський вид містить всі оператори. Вони включають і оператори що звучать (осциллятори) і беззвучні оператори або модулятори: Низько-частотні осциллятори і обвідні. + +Регулятори й інші віджети в операторському вигляді мають свої підписи "Що це?", Таким чином по ним можна отримати більш детальну довідку. + + + + Matrix view + Матричний вигляд + + + + The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. + +The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. + +Each modulation target has 4 knobs, one for each modulator. By default the knobs are at 0, which means no modulation. Turning a knob to 1 causes that modulator to affect the modulation target as much as possible. Turning it to -1 does the same, but the modulation is inversed. + Матричний вид містить матрицю модуляції. Тут можна визначити модуляційні відношення між різними операторами. Кожен чутний оператор (осциллятори 1-3) мають 3-4 властивості, які можна модулювати будь-якими модуляторами. Використовуючи більше модуляцій збільшується навантаження на процесор. + +Вид ділиться на цілі модуляції, згруповані на цільовий осциллятор. Доступні цілі: гучність, тон, фаза, ширина пульсація і відношення з підлеглим (під-) осциллятором. Відзначимо що деякі цілі визначені тільки для одного осциллятора. + +Кожна ціль модуляції має 4 регулятори, по одному на кожен модулятор. За замовчуванням регулятори встановлені на 0, тобто без модуляції. Включення регуляторів на 1 веде до того, що модулятор впливає на ціль модуляції на стільки на скільки це можливо. Включення його в -1 робить те ж, але зі зворотньою модуляцією. + + + + + + Volume + Гучність + + + + + + Panning + Баланс + + + + + + Coarse detune + Грубе підстроювання + + + + + + semitones + півтон(а,ів) + + + + + Finetune left + Точне настроювання лівого каналу + + + + + + + cents + відсотків + + + + + Finetune right + Точне настроювання правого каналу + + + + + + Stereo phase offset + Зміщення стерео-фази + + + + + + + + deg + град + + + + Pulse width + Довжина імпульсу + + + + Send sync on pulse rise + Відправляти синхронізацію на підйомі імпульсу + + + + Send sync on pulse fall + Відправити синхронізацію на падінні пульсу + + + + Hard sync oscillator 2 + Жорстка синхронізація осциллятора 2 + + + + Reverse sync oscillator 2 + Верерс синхронізація осциллятора 2 + + + + Sub-osc mix + Мікс суб-осциляторів + + + + Hard sync oscillator 3 + Жорстка синхронізація осциллятора 3 + + + + Reverse sync oscillator 3 + Верерс синхронізація осциллятора 3 + + + + + + + Attack + Вступ + + + + + Rate + Частота вибірки + + + + + Phase + Фаза + + + + + Pre-delay + Передзатримка + + + + + Hold + Утримання + + + + + Decay + Згасання + + + + + Sustain + Витримка + + + + + Release + Зменшення + + + + + Slope + Нахил + + + + Mix Osc2 with Osc3 + Змішати Осц2 з Осц3 + + + + Modulate amplitude of Osc3 with Osc2 + Модулювати амплітуду осциллятора 3 сигналом з осц2 + + + + Modulate frequency of Osc3 with Osc2 + Модулювати частоту осциллятора 3 сигналом з осц2 + + + + Modulate phase of Osc3 with Osc2 + Модулювати фазу Осц3 осциллятором2 + + + + The CRS knob changes the tuning of oscillator 1 in semitone steps. + Регулятор CRS змінює налаштування осциллятора 1 у розмірі півтону. + + + + The CRS knob changes the tuning of oscillator 2 in semitone steps. + Регулятор CRS змінює налаштування осциллятора 2 у розмірі півтону. + + + + The CRS knob changes the tuning of oscillator 3 in semitone steps. + Регулятор CRS змінює налаштування осциллятора 3 у розмірі півтону. + + + + + + + FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. + FTL і FTR змінюють підстроювання осциллятора для лівого і правого каналів відповідно. Вони можуть додати стерео розстроювання осциллятора, яке розширює стерео картину і створює ілюзію космосу. + + + + + + The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. + Регулятор SPO змінює фазову різницю між лівим і правим каналами. Висока різниця створює більш широку стерео картину. + + + + The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. + PW регулятор контролює ширину пульсацій, також відому як робочий цикл осциллятора 1. Осциллятор 1 це цифровий імпульсний хвильовий генератор, він не відтворює сигнал з обмеженою смугою, це означає, що його можна використовувати як чутний осциллятор, але це призведе до накладення сигналів (або згладжування) . Його можна використовувати й як не чутне джерело синхронізуючого сигналу, для використання в синхронізації осцилляторів 2 і 3. + + + + Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + Надсилати синхронізацію при підвищенні: при включенні, сигнал синхронізації надсилається кожен раз коли стан осциллятора 1 змінюється з низького на високий, тобто коли амплітуда змінюється від -1 до 1. +Тон осциллятора 1, фаза і ширина пульсацій може впливати на час синхронізації, але гучність не має ефекту. Сигнал синхронізації надсилається незалежно для лівого і правого каналів. + + + + Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + Надсилати синхронізацію при зниженні: при включенні, сигнал синхронізації надсилається кожен раз коли стан осциллятора 1 змінюється з виского на низьке, тобто коли амплітуда змінюється від 1 до -1. +Тон осциллятора 1, фаза і ширина пульсацій може впливати на час синхронізації, але гучність не має ефекту. Сигнал синхронізації надсилається незалежно для лівого і правого каналів. + + + + + Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. + Жорстка синхронізація: Кожен раз при отриманні осциллятором сигналу синхронізації від осциллятора 1, його фаза скидається до 0 + його межа фази, якою б вона не була. + + + + + Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. + Реверс синхронізація: Кожен раз при отриманні сигналу синхронізації від осциллятора 1, амплітуда осциллятора перевертається. + + + + Choose waveform for oscillator 2. + Вибрати форму хвилі для осциллятора 2. + + + + Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + Виберіть форму хвилі для першого додаткового осциллятора осциллятора 3. Осциллятор 3 може м'яко переходити між двома різними хвилями. + + + + Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + Виберіть форму хвилі для другого додаткового осциллятора осциллятора 3. Осциллятор 3 може м'яко переходити між двома різними хвилями. + + + + The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. + SUB змінює змішування двох дод осцилляторів осциллятора 3. Кожен дод. осц. може бути встановлений для створення різних хвиль і осциллятор 3 може м'яко переходити між ними. Усі вхідні модуляції для осциллятора 3 застосовуються на обидва дод.осц./хвилі одним і тим же чином. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +Mix mode means no modulation: the outputs of the oscillators are simply mixed together. + На додаток до виділених модуляторів Монстро дозволяє виходу осциллятора 2 модулювати осцллятор 3. + +Змішаний (Mix) режим означає без модуляції: виходи осцилляторів просто змішуються один з одним. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. + На додаток до виділених модуляторів Монстро дозволяє виходу осциллятора 2 модулювати осцллятор 3. + +AM режим значить Амплітуда Модуляції: Осциллятори 2 модулює амплітуду (гучність) осциллятора 3. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. + На додаток до виділених модуляторів Монстро дозволяє виходу осциллятора 2 модулювати осцллятор 3. + +FM (ЧМ) режим означає Частотна Модуляція: осциллятор 2 модулює частоту (pitch, тональність) осциллятора 3. Частота модуляції відбувається у фазі модуляції, яка дає більш стабільний загальний тон, ніж "чиста" частотна модуляція. + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. + На додаток до виділених модуляторів Монстро дозволяє виходу осциллятора 2 модулювати осцллятор 3. + +PM (ФМ) режим означає Фазова Модуляція: Осциллятор 2 модулює фазу осциллятора 3. Це відрізняється від частотної модуляції тим, що зміни фаз не сумуються. + + + + Select the waveform for LFO 1. +"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + Виберіть форму хвилі для LFO 1 (НизькоЧастотнийГенератор). +"Random" (Випадково) і "Random-smooth" (випадкове згладжування) - це спеціальні хвилі: вони створюють випадковий сигнал, де частота LFO контролює як часто змінюється стан генератора (LFO). +Згладжена версія переходить між цими станами з косинусоїдальною інтерполяцією. Ці випадкові режими можуть бути використані, щоб дати "життя" вашим налаштуванням - додати трішки аналогової непередбачуваності ... + + + + Select the waveform for LFO 2. +"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + Виберіть форму хвилі для LFO 2 (НизкоЧастотнийГенератор). +"Random" (Випадково) і "Random-smooth" (випадкове згладжування) - це спеціальні хвилі: вони створюють випадковий сигнал, де частота LFO контролює як часто змінюється стан генератора (LFO). +Згладжена версія переходить між цими станами з косинусоїдальною інтерполяцією. Ці випадкові режими можуть бути використані, щоб дати "життя" вашим налаштуванням - додати трішки аналогової непередбачуваності ... + + + + + Attack causes the LFO to come on gradually from the start of the note. + Атака відповідає за плавність поведінки LFO від початку ноти. + + + + + Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. + Rate (Частота) встановлює швидкість LFO, вимірювану в мілісекундах за цикл. Може синхронізуватися з темпом. + + + + + PHS controls the phase offset of the LFO. + PHS контролює зсув фази LFO (НЧГ). + + + + + PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. + PRE передзатримка, затримує старт обвідної від початку ноти. 0 означає без затримки. + + + + + ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. + ATT атака контролює як швидко обвідна нарощується на старті, вимірюється в мілісекундах. Значення 0 означає миттєво. + + + + + HOLD controls how long the envelope stays at peak after the attack phase. + HOLD (УТРИМУВАТИ) контролює як довго обвідна залишається на піку після фази атаки. + + + + + DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. + DEC (decay) згасання контролює як швидко обвідна спадає з пікового значення, вимірюється в мілісекундах, як довго буде йти з піку до нуля. Реальне загасання може бути коротшим, якщо використовується витримка. + + + + + SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. + SUS (sustain) витримка, контролює рівень обвідної. Загасання фази не піде нижче цього рівня поки нота утримується. + + + + + REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. + REL (release) відпускання контролює як довго нота відпускається, вимірюється в довготі падіння від піку до нуля. Реальне відпускання може бути коротшим, залежно від фази, в якій нота відпущена. + + + + + The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. + Регулятор нахилу контролює криву або форму обвідної. Значення 0 створює прямі підйоми і спади. Від'ємні величини створюють криві з уповільненим початком, швидким піком і знову уповільненим спадом. Позитивні значення створюють криві які починаються і закінчуються швидко, але довше залишаються на піках. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modulation amount + Глибина модуляції + + + + MultitapEchoControlDialog + + + Length + Довжина + + + + Step length: + Довжина кроку: + + + + Dry + Сухий + + + + Dry Gain: + Сухе підсилення: + + + + Stages + Етапи + + + + Lowpass stages: + НЧ етапи: + + + + Swap inputs + Обмін входами + + + + Swap left and right input channel for reflections + Дзеркальний обмін лівим і правим каналами + + + + NesInstrument + + + Channel 1 Coarse detune + Грубе підстроювання 1 каналу + + + + Channel 1 Volume + Гучність 1 каналу + + + + Channel 1 Envelope length + Довжина обвідної 1 каналу + + + + Channel 1 Duty cycle + Робочий цикл 1 каналу + + + + Channel 1 Sweep amount + Кількість розгортки 1 каналу + + + + Channel 1 Sweep rate + Швидкість розгортки 1 каналу + + + + Channel 2 Coarse detune + Грубе підстроювання 2 каналу + + + + Channel 2 Volume + Гучність 2 каналу + + + + Channel 2 Envelope length + Довжина обвідної 2 каналу + + + + Channel 2 Duty cycle + Робочий цикл 2 каналу + + + + Channel 2 Sweep amount + Кількість розгортки 2 каналу + + + + Channel 2 Sweep rate + Швидкість розгортки 2 каналу + + + + Channel 3 Coarse detune + Грубе підстроювання 3 каналу + + + + Channel 3 Volume + Гучність 3 каналу + + + + Channel 4 Volume + Гучність 4 каналу + + + + Channel 4 Envelope length + Довжина обвідної 4 каналу + + + + Channel 4 Noise frequency + Частота шуму 4 каналу + + + + Channel 4 Noise frequency sweep + Частота розгортки шуму 4 каналу + + + + Master volume + Основна гучність + + + + Vibrato + Вібрато + + + + NesInstrumentView + + + + + + Volume + Гучність + + + + + + Coarse detune + Грубе підстроювання + + + + + + Envelope length + Довжина обвідної + + + + Enable channel 1 + Увімкнути канал 1 + + + + Enable envelope 1 + Увімкнути обвідну 1 + + + + Enable envelope 1 loop + Увімкнти повтор обвідної 1 + + + + Enable sweep 1 + Увімкнути розгортку 1 + + + + + Sweep amount + Кількість розгортки + + + + + Sweep rate + Темп розгортки + + + + + 12.5% Duty cycle + 12.5% Робочого циклу + + + + + 25% Duty cycle + 25% Робочого циклу + + + + + 50% Duty cycle + 50% Робочого циклу + + + + + 75% Duty cycle + 75% Робочого циклу + + + + Enable channel 2 + Увімкнути канал 2 + + + + Enable envelope 2 + Увімкнути обвідну 2 + + + + Enable envelope 2 loop + Увімкнти повтор обвідної 2 + + + + Enable sweep 2 + Увімкнути розгортку 2 + + + + Enable channel 3 + Увімкнути канал 3 + + + + Noise Frequency + Частота шуму + + + + Frequency sweep + Частота темпу + + + + Enable channel 4 + Увімкнути канал 4 + + + + Enable envelope 4 + Увімкнути обвідну 4 + + + + Enable envelope 4 loop + Увімкнти повтор обвідної 4 + + + + Quantize noise frequency when using note frequency + Квантування частоту шуму при використанні частоти ноти + + + + Use note frequency for noise + Використовувати частоту ноти для шуму + + + + Noise mode + Форма шуму + + + + Master Volume + Основна гучність + + + + Vibrato + Вібрато + + + + OscillatorObject + + + Osc %1 waveform + Форма сигналу осциллятора %1 + + + + Osc %1 harmonic + Осц %1 гармонійний + + + + + Osc %1 volume + Гучність осциллятора %1 + + + + + Osc %1 panning + Стереобаланс для осциллятора %1 + + + + + Osc %1 fine detuning left + Точне підстроювання лівого каналу осциллятора %1 + + + + Osc %1 coarse detuning + Підстроювання осциллятора %1 грубе + + + + Osc %1 fine detuning right + Підстроювання правого каналу осциллятора %1 тонка + + + + Osc %1 phase-offset + Зміщення фази осциллятора %1 + + + + Osc %1 stereo phase-detuning + Підстроювання стерео-фази осциллятора %1 + + + + Osc %1 wave shape + Гладкість сигналу осциллятора %1 + + + + Modulation type %1 + Тип модуляції %1 + + + + PatchesDialog + + + Qsynth: Channel Preset + Q-Синтезатор: Канал передустановлено + + + + Bank selector + Селектор банку + + + + Bank + Банк + + + + Program selector + Селектор програм + + + + Patch + Патч + + + + Name + І'мя + + + + OK + ОК + + + + Cancel + Скасувати + + + + PatmanView + + + Open other patch + Відкрити інший патч + + + + Click here to open another patch-file. Loop and Tune settings are not reset. + Натисніть щоб відкрити інший патч-файл. Циклічність і налаштування при цьому збережуться. + + + + Loop + Повтор + + + + Loop mode + Режим повтору + + + + Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. + Тут вмикається/вимикається режим повтору, при увімкнені PatMan буде використовувати інформацію про повтор з файлу. + + + + Tune + Підлаштувати + + + + Tune mode + Тип підстроювання + + + + Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. + Тут вмикається/вимикається режим підстроювання. Якщо його увімкнено, то PatMan змінить запис так, щоб він збігався по частоті з нотою. + + + + No file selected + Файл не вибрано + + + + Open patch file + Відкрити патч-файл + + + + Patch-Files (*.pat) + Патч-файли (*.pat) + + + + PatternView + + + use mouse wheel to set velocity of a step + використовуйте колесо миші для встановлення кроку гучності + + + + double-click to open in Piano Roll + Відкрити в редакторі нот подвійним клацанням миші + + + + Open in piano-roll + Відкрити в редакторі нот + + + + Clear all notes + Очистити всі ноти + + + + Reset name + Скинути назву + + + + Change name + Перейменувати + + + + Add steps + Додати такти + + + + Remove steps + Видалити такти + + + + Clone Steps + Клонувати такти + + + + PeakController + + + Peak Controller + Контролер вершин + + + + Peak Controller Bug + Контролер вершин з багом + + + + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. + Через помилку в старій версії LMMS контролери вершин не можуть правильно підключатися. Будь-ласка переконайтеся, що контролери вершин правильно приєднані і перезбережіть цей файл, вибачте, за заподіяні незручності. + + + + PeakControllerDialog + + + PEAK + ПІК + + + + LFO Controller + Контролер LFO + + + + PeakControllerEffectControlDialog + + + BASE + БАЗА + + + + Base amount: + Базове значення: + + + + AMNT + ГЛИБ + + + + Modulation amount: + Глибина модуляції: + + + + MULT + МНОЖ + + + + Amount Multiplicator: + Величина множника: + + + + ATCK + ВСТУП + + + + Attack: + Вступ: + + + + DCAY + ЗГАС + + + + Release: + Зменшення: + + + + TRSH + TRSH + + + + Treshold: + Поріг: + + + + PeakControllerEffectControls + + + Base value + Опорне значення + + + + Modulation amount + Глибина модуляції + + + + Attack + Вступ + + + + Release + Зменшення + + + + Treshold + Поріг + + + + Mute output + Заглушити вивід + + + + Abs Value + Абс Значення + + + + Amount Multiplicator + Величина множника + + + + PianoRoll + + + Note Velocity + Гучність нот + + + + Note Panning + Стереофонія нот + + + + Mark/unmark current semitone + Відмітити/Зняти відмітку з поточного півтону + + + + Mark/unmark all corresponding octave semitones + Відмітити/Зняти всі відповідні півтони октави + + + + Mark current scale + Відмітити поточний підйом + + + + Mark current chord + Відмітити поточний акорд + + + + Unmark all + Зняти виділення + + + + Select all notes on this key + Вибрати всі ноти на цій тональності + + + + Note lock + Фіксація нот + + + + Last note + По останій ноті + + + + No scale + Без підйому + + + + No chord + Прибрати акорди + + + + Velocity: %1% + Гучність %1% + + + + Panning: %1% left + Баланс %1% лівий + + + + Panning: %1% right + Баланс %1% правий + + + + Panning: center + Баланс: по середині + + + + Please open a pattern by double-clicking on it! + Відкрийте шаблон за допомогою подвійного клацання мишею! + + + + + Please enter a new value between %1 and %2: + Введіть нове значення від %1 до %2: + + + + PianoRollWindow + + + Play/pause current pattern (Space) + Гра/Пауза поточної мелодії (Пробіл) + + + + Record notes from MIDI-device/channel-piano + Записати ноти з цифрового музичного інструмента (MIDI) + + + + Record notes from MIDI-device/channel-piano while playing song or BB track + Записати ноти з цифрового музичного інструменту (MIDI) під час відтворення пісні або доріжки Ритм-Басу + + + + Stop playing of current pattern (Space) + Зупинити програвання поточної мелодії (Пробіл) + + + + Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. + Натисніть тут щоб програти поточний шаблон. Це може стати в нагоді при його редагуванні. Після закінчення шаблону відтворення почнеться спочатку. + + + + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. + Натисніть цю кнопку, якщо ви хочете записати ноти з пристрою MIDI або віртуального синтезатора відповідного каналу. Пізніше ви зможете відредагувати записаний шаблон. + + + + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. + Натисніть цю кнопку, якщо ви хочете записати ноти з пристрою MIDI або віртуального синтезатора відповідного каналу. Під час запису всі ноти записуються в цей шаблон, і ви будете чути композицію або РБ доріжку на задньому плані. + + + + Click here to stop playback of current pattern. + Натисніть тут, якщо ви хочете зупинити відтворення поточного шаблону. + + + + Edit actions + Зміна + + + + Draw mode (Shift+D) + Режим малювання (Shift + D) + + + + Erase mode (Shift+E) + Режим стирання (Shift+E) + + + + Select mode (Shift+S) + Режим вибору нот (Shift+S) + + + + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + Режим малювання нот, в ньому ви можете додавати/переміщати і змінювати тривалість одиночних нот. Це режим за замовчуванням і використовується більшу частину часу. +Для включення цього режиму можна скористатися комбінацією клавіш Shift+D, утримуйте %1 для тимчасового перемикання в режим вибору. + + + + Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. + Режим стирання. У цьому режимі ви можете стирати ноти. Для увімкнення цього режиму можна скористатися комбінацією клавіш Shift+E. + + + + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Режим виділення. У цьому режимі можна виділяти ноти, також можна утримувати %1 в режимі малювання, щоб на час увійти в режим виділення. + + + + Pitch Bend mode (Shift+T) + Режим Pitch Bend (Shift+T) + + + + Click here and Pitch Bend mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + Натисніть тут для активації Pitch Blend режиму. Ви зможете клікнути на ноту, щоб почати автоматичний детюн. Можна використовувати це для "ковзання" від однієї ноти до іншої. Можна включити цей режим за допомогою Shift + T. + + + + Quantize + Квантовать + + + + Copy paste controls + Управління копіюванням та вставкою + + + + Cut selected notes (%1+X) + Перемістити виділені ноти до буферу (%1+X) + + + + Copy selected notes (%1+C) + Копіювати виділені ноти до буферу (%1+X) + + + + Paste notes from clipboard (%1+V) + Вставити ноти з буферу (%1+V) + + + + Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При натиснені цієї кнопки виділені ноти будуть вирізані до буферу. Пізніше ви зможете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". + + + + Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + При натиснені цієї кнопки виділені ноти буде скопійовано до буферу. Пізніше ви зможете вставити їх в будь-яке місце будь-якого шаблону за допомогою кнопки "Вставити". + + + + Click here and the notes from the clipboard will be pasted at the first visible measure. + При натиснені цієї кнопки ноти з буферу будуть вставлені в перший видимий такт. + + + + Timeline controls + Управління хронологією + + + + Zoom and note controls + Управління масштабом і нотами + + + + This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. + Цим контролюється масштаб осі. Це може бути корисно для спеціальних завдань. Для звичайного редагування, масштаб слід встановлювати за найменшою нотою. + + + + The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. + "Q" позначає квантування і контролює розмір нотної сітки і контрольні точки тяжіння. З меншою величиною квантування, можна малювати короткі ноти в редаторі нот і більш точно контролювати точки в редакторі Автоматизації. + + + + This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited + Дозволяє вибрати довжину нової ноти. "Остання Нота" означає, що LMMS буде використовувати довжину ноти, зміненої в останній раз + + + + The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! + Функція безпосередньо пов'язана з контекстним меню на віртуальній клавіатурі зліва в нотному редакторі. Після того, як обраний масштаб у випадаючому меню, можна натиснути правою кнопкою у віртуальній клавіатурі і вибрати "Mark Current Scale" (Відзначити поточний масштаб). LMMS підсвітить всі ноти які лежать в обраному масштабі для обраної клавіші! + + + + Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + Дозволяє вибрати акорд, який LMMS потім зможе намалювати або підсвітити. У цьому меню можна знайти найбільш популярні акорди. Після того, як ви вибрали акорд, натисніть в будь-якому місці, щоб поставити його, а правим кліком по віртуальній клавіатурі відкривається контекстне меню і підсвічування акорду. Для повернення в режим однієї ноти потрібно вибрати "Без акорду" в цьому випадаючому меню. + + + + + Piano-Roll - %1 + Нотний редактор - %1 + + + + + Piano-Roll - no pattern + Нотний редактор - без шаблону + + + + PianoView + + + Base note + Опорна нота + + + + Plugin + + + Plugin not found + Модуль не знайдено + + + + The plugin "%1" wasn't found or could not be loaded! +Reason: "%2" + Модуль «%1» відсутній чи не може бути завантажений! +Причина: «%2» + + + + Error while loading plugin + Помилка завантаження модуля + + + + Failed to load plugin "%1"! + Не вдалося завантажити модуль «%1»! + + + + PluginBrowser + + + Instrument Plugins + Модулі інструментів + + + + Instrument browser + Огляд інструментів + + + + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. + Ви можете переносити потрібні вам інструменти з цієї панелі в музичний, ритм-бас редактор або в існуючу доріжку інструменту. + + + + PluginFactory + + + Plugin not found. + Модуль не знайдено. + + + + LMMS plugin %1 does not have a plugin descriptor named %2! + LMMS плагін %1 не має опису плагіна з ім'ям %2! + + + + ProjectNotes + + + Project Notes + Примітки проекту + + + + Enter project notes here + Напишіть примітки до проекту тут + + + + Edit Actions + Зміна + + + + &Undo + &U Скасувати + + + + %1+Z + %1+Z + + + + &Redo + &R Повторити + + + + %1+Y + %1+Y + + + + &Copy + &C Копіювати + + + + %1+C + %1+C + + + + Cu&t + &t Вирізати + + + + %1+X + %1+X + + + + &Paste + &P Вставити + + + + %1+V + %1+V + + + + Format Actions + Форматування + + + + &Bold + Напів&жирний + + + + %1+B + %1+B + + + + &Italic + &Курсив + + + + %1+I + %1+I + + + + &Underline + &Підкреслити + + + + %1+U + %1+U + + + + &Left + По &лівому краю + + + + %1+L + %1+L + + + + C&enter + По &центрі + + + + %1+E + %1+E + + + + &Right + По &правому краю + + + + %1+R + %1+R + + + + &Justify + По &ширині + + + + %1+J + %1+J + + + + &Color... + &C Колір... + + + + ProjectRenderer + + + WAV-File (*.wav) + Файл WAV (*.wav) + + + + Compressed OGG-File (*.ogg) + Стиснутий файл OGG (*.ogg) + + + FLAC-File (*.flac) + + + + + Compressed MP3-File (*.mp3) + Стиснутий MP3-файл (* .mp3) + + + + QWidget + + + + + Name: + І'мя: + + + + + Maker: + Розробник: + + + + + Copyright: + Авторське право: + + + + + Requires Real Time: + Потрібна обробка в реальному часі: + + + + + + + + + Yes + Так + + + + + + + + + No + Ні + + + + + Real Time Capable: + Робота в реальному часі: + + + + + In Place Broken: + Замість зламаного: + + + + + Channels In: + Канали в: + + + + + Channels Out: + Канали з: + + + + File: %1 + Файл: %1 + + + + File: + Файл: + + + + RenameDialog + + + Rename... + Перейменувати ... + + + + ReverbSCControlDialog + + + Input + Ввід + + + + Input Gain: + Вхідне підсилення: + + + + Size + Розмір + + + + Size: + Розмір: + + + + Color + Колір + + + + Color: + Колір: + + + + Output + Вивід + + + + Output Gain: + Вихідне підсилення: + + + + ReverbSCControls + + + Input Gain + Вхідне підсилення + + + + Size + Розмір + + + + Color + Колір + + + + Output Gain + Вихідне підсилення + + + + SampleBuffer + + + Fail to open file + Не вдається відкрити файл + + + + Audio files are limited to %1 MB in size and %2 minutes of playing time + Аудіофайли обмежено розміром в %1 МБ і %2 хвилин(и) програвання + + + + Open audio file + Відкрити звуковий файл + + + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + Всі Аудіо-файли (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + + + + Wave-Files (*.wav) + Файли Wave (*.wav) + + + + OGG-Files (*.ogg) + Файли OGG (*.ogg) + + + + DrumSynth-Files (*.ds) + Файли DrumSynth (*.ds) + + + + FLAC-Files (*.flac) + Файли FLAC (*.flac) + + + + SPEEX-Files (*.spx) + Файли SPEEX (*.spx) + + + + VOC-Files (*.voc) + Файли VOC (*.voc) + + + + AIFF-Files (*.aif *.aiff) + Файли AIFF (*.aif *.aiff) + + + + AU-Files (*.au) + Файли AU (*.au) + + + + RAW-Files (*.raw) + Файли RAW (*.raw) + + + + SampleTCOView + + + double-click to select sample + Виберіть запис подвійним натисненням миші + + + + Delete (middle mousebutton) + Видалити (середня кнопка мишки) + + + + Cut + Вирізати + + + + Copy + Копіювати + + + + Paste + Вставити + + + + Mute/unmute (<%1> + middle click) + Заглушити/включити (<%1> + середня кнопка миші) + + + + SampleTrack + + + Volume + Гучність + + + + Panning + Баланс + + + + + Sample track + Доріжка запису + + + + SampleTrackView + + + Track volume + Гучність доріжки + + + + Channel volume: + Гучність каналу: + + + + VOL + ГУЧН + + + + Panning + Баланс + + + + Panning: + Баланс: + + + + PAN + БАЛ + + + + SetupDialog + + + Setup LMMS + Налаштування LMMS + + + + + General settings + Загальні налаштування + + + + BUFFER SIZE + РОЗМІР БУФЕРУ + + + + + Reset to default-value + Відновити значення за замовчуванням + + + + MISC + РІЗНЕ + + + + Enable tooltips + Включити підказки + + + + Show restart warning after changing settings + Показувати попередження про перезапуск при зміні налаштувань + + + + Display volume as dBFS + Відображати гучність в децибелах + + + + Compress project files per default + За замовчуванням стискати файли проектів + + + + One instrument track window mode + Режим вікна однієї інструментальної доріжки + + + + HQ-mode for output audio-device + Режим високої якості для виведення звуку + + + + Compact track buttons + Стиснути кнопки доріжки + + + + Sync VST plugins to host playback + Синхронізувати VST плагіни з хостом відтворення + + + + Enable note labels in piano roll + Включити позначення нот у музичному редакторі + + + + Enable waveform display by default + Включити відображення форми хвилі за замовчуванням + + + + Keep effects running even without input + Продовжувати роботу ефектів навіть без вхідного сигналу + + + + Create backup file when saving a project + Створю запасний файл при збереженні проекту + + + + Reopen last project on start + Відкривати останній проект при запуску + + + + Use built-in NaN handler + Використовувати вбудований обробник NaN + + + + PLUGIN EMBEDDING + ВСТАНОВИТИ УПРАВЛІННЯ + + + + No embedding + Не встановлено + + + + Embed using Qt API + Встановлення використовуючи Qt API + + + + Embed using native Win32 API + Встановлення використовуючи рідний Win32 API + + + + Embed using XEmbed protocol + Встановлення використовуючи протокол XEmbed + + + + LANGUAGE + МОВА + + + + + Paths + Шляхи + + + + Directories + Каталоги + + + + LMMS working directory + Робочий каталог LMMS + + + + Themes directory + Каталог тем + + + + Background artwork + Фонове зображення + + + + VST-plugin directory + Каталог модулів VST + + + + GIG directory + Каталог GIG + + + + SF2 directory + Каталог SF2 + + + + LADSPA plugin directories + Каталог модулів LADSPA + + + + STK rawwave directory + Каталог STK rawwave + + + + Default Soundfont File + Основний Soundfont файл + + + + + Performance settings + Налаштування продуктивності + + + + Auto save + Авто-збереження + + + + Enable auto-save + Увімкнути автоматичне збереження + + + + Allow auto-save while playing + Дозволити автоматичне збереження під час відтворення + + + + UI effects vs. performance + Візуальні ефекти / продуктивність + + + + Smooth scroll in Song Editor + Плавне прокручування в музичному редакторі + + + + Show playback cursor in AudioFileProcessor + Показувати покажчик відтворення в процесорі аудіо файлів + + + + + Audio settings + Параметри звуку + + + + AUDIO INTERFACE + ЗВУКОВА СИСТЕМА + + + + + MIDI settings + Параметри MIDI + + + + MIDI INTERFACE + ІНТЕРФЕЙС MIDI + + + + OK + ОК + + + + Cancel + Скасувати + + + + Restart LMMS + Перезапустіть LMMS + + + + Please note that most changes won't take effect until you restart LMMS! + Врахуйте, що більшість налаштувань не вступлять в силу до перезапуску програми! + + + + Frames: %1 +Latency: %2 ms + Фрагментів: %1 +Затримка: %2 мс + + + + Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. + Тут ви можете налаштувати розмір внутрішнього звукового буфера LMMS. Менші значення дають менший час відгуку програми, але підвищують споживання ресурсів - це особливо помітно на старих машинах і системах, ядро ​​яких не підтримує пріоритету реального часу. Якщо спостерігається переривчастий звук, спробуйте збільшити розмір буферу. + + + + Choose LMMS working directory + Вибір робочого каталогу LMMS + + + + Choose your GIG directory + Виберіть каталог GIG + + + + Choose your SF2 directory + Виберіть каталог SF2 + + + + Choose your VST-plugin directory + Вибір свого каталогу для модулів VST + + + + Choose artwork-theme directory + Вибір каталогу з темою оформлення для LMMS + + + + Choose LADSPA plugin directory + Вибір каталогу з модулями LADSPA + + + + Choose STK rawwave directory + Вибір каталогу STK rawwave + + + + Choose default SoundFont + Вибрати головний SoundFont + + + + Choose background artwork + Вибрати фонове зображення + + + + minutes + хвилин + + + + minute + хвилина + + + + Disabled + Вимкнено + + + + Auto-save interval: %1 + Інтервал автоматичного збереження: %1 + + + + Set the time between automatic backup to %1. +Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. + Встановіть проміжок часу автоматичного резервного копіювання в %1. +Не забудьте також зберегти проект вручну. Ви можете вимкнути автозбереження, інколи деяким старим системи тяжко в таком режимі. + + + + Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. + Будь ласка, виберіть звукову систему. Залежно від конфігурації під час компілювання програми, ви можете використовувати ALSA, JACK, OSS та інші. У нижній частині вікна налаштування можна задати специфічні параметри обраної системи. + + + + Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. + Будь ласка, виберіть інтерфейс MIDI. Залежно від конфігурації під час компілювання програми, ви можете використовувати ALSA, OSS та інші. У нижній частині вікна налаштування можна задати специфічні параметри обраного інтерфейсу. + + + + Song + + + Tempo + Темп + + + + Master volume + Основна гучність + + + + Master pitch + Основна тональність + + + + LMMS Error report + Повідомлення про помилку в LMMS + + + + Project saved + Проект збережено + + + + The project %1 is now saved. + Проект %1 збережено. + + + + Project NOT saved. + Проект НЕ ЗБЕРЕЖЕНО. + + + + The project %1 was not saved! + Проект %1 не збережено! + + + + Import file + Імпорт файлу + + + + MIDI sequences + MiDi послідовність + + + + Hydrogen projects + Hydrogen проекти + + + + All file types + Всі типи файлів + + + + + Empty project + Проект порожній + + + + + This project is empty so exporting makes no sense. Please put some items into Song Editor first! + Проект нічого не містить, так що й експортувати нічого. Спочатку додайте хоча б одну доріжку за допомогою музичного редактора! + + + + Select directory for writing exported tracks... + Виберіть теку для запису експортованих доріжок ... + + + + + untitled + Без назви + + + + + Select file for project-export... + Вибір файлу для експорту проекту ... + + + + Save project + Зберегти проект + + + + MIDI File (*.mid) + MIDI-файл (* mid) + + + + The following errors occured while loading: + Наступні помилки виникли при завантаженні: + + + + SongEditor + + + Could not open file + Не можу відкрити файл + + + + Could not open file %1. You probably have no permissions to read this file. + Please make sure to have at least read permissions to the file and try again. + Неможливо відкрити файл %1, ймовірно, немає дозволу на його читання. +Будь-ласка переконайтеся, що є принаймні права на читання цього файлу і спробуйте ще раз. + + + + Could not write file + Не можу записати файл + + + + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. + Неможливо відкрити %1 для запису, можливо, немає дозволу на запис в цей файл, будь-ласка упевніться, що є доступ до цього файлу і спробуйте знову. + + + + Error in file + Помилка у файлі + + + + The file %1 seems to contain errors and therefore can't be loaded. + Файл %1 можливо містить помилки через які не може завантажитися. + + + + Version difference + Різниця версій + + + + This %1 was created with LMMS %2. + Цей %1 було створено в LMMS версії %2 + + + + template + шаблон + + + + project + проект + + + + Tempo + Темп + + + + TEMPO/BPM + ТЕМП/BPM + + + + tempo of song + Темп музики + + + + The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). + Це значення задає темп музики в ударах в хвилину (англ. аббр. BPM). На кожен такт приходить чотири удари, так що темп в ударах в хвилину фактично вказує, скільки чвертей такту програється за хвилину (або, що те ж, кількість тактів, що програються за чотири хвилини). + + + + High quality mode + Висока якість + + + + + Master volume + Основна гучність + + + + master volume + основна гучність + + + + + Master pitch + Основна тональність + + + + master pitch + основна тональність + + + + Value: %1% + Значення: %1% + + + + Value: %1 semitones + Значення: %1 півтон(у/ів) + + + + SongEditorWindow + + + Song-Editor + Музичний редактор + + + + Play song (Space) + Почати відтворення (Пробіл) + + + + Record samples from Audio-device + Записати семпл зі звукового пристрою + + + + Record samples from Audio-device while playing song or BB track + Записати семпл з аудіо-пристрої під час відтворення в музичному чи ритм/бас редакторі + + + + Stop song (Space) + Зупинити відтворення (Пробіл) + + + + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. + Натисніть, щоб прослухати створену мелодію. Відтворення почнеться з позиції курсора (зелений трикутник); ви можете рухати його під час програвання. + + + + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. + Натисніть сюди, якщо хочете зупинити відтворення мелодії. Курсор при цьому буде встановлений на початок композиції. + + + + Track actions + Стежити + + + + Add beat/bassline + Додати ритм/бас + + + + Add sample-track + Додати доріжку запису + + + + Add automation-track + Додати доріжку автоматизації + + + + Edit actions + Зміна + + + + Draw mode + Режим малювання + + + + Edit mode (select and move) + Правка (виділення/переміщення) + + + + Timeline controls + Управління хронологією + + + + Zoom controls + Управління масштабом + + + + SpectrumAnalyzerControlDialog + + + Linear spectrum + Лінійний спектр + + + + Linear Y axis + Лінійна вісь ординат + + + + SpectrumAnalyzerControls + + + Linear spectrum + Лінійний спектр + + + + Linear Y axis + Лінійна вісь ординат + + + + Channel mode + Режим каналу + + + + SubWindow + + + Close + Закрити + + + + Maximize + Розгорнути + + + + Restore + Відновити + + + + TabWidget + + + + Settings for %1 + Налаштування для %1 + + + + TempoSyncKnob + + + + Tempo Sync + Синхронізація темпу + + + + No Sync + Синхронізації немає + + + + Eight beats + Вісім ударів (дві ноти) + + + + Whole note + Ціла нота + + + + Half note + Півнота + + + + Quarter note + Чверть ноти + + + + 8th note + Восьма ноти + + + + 16th note + 1/16 ноти + + + + 32nd note + 1/32 ноти + + + + Custom... + Своя... + + + + Custom + Своя + + + + Synced to Eight Beats + Синхро по 8 ударам + + + + Synced to Whole Note + Синхро по цілій ноті + + + + Synced to Half Note + Синхро по половині ноти + + + + Synced to Quarter Note + Синхро по чверті ноти + + + + Synced to 8th Note + Синхро по 1/8 ноти + + + + Synced to 16th Note + Синхро по 1/16 ноти + + + + Synced to 32nd Note + Синхро по 1/32 ноти + + + + TimeDisplayWidget + + + click to change time units + натисніть для зміни одиниць часу + + + + MIN + ХВ + + + + SEC + С + + + + MSEC + МС + + + + BAR + БАР + + + + BEAT + БІТ + + + + TICK + ТІК + + + + TimeLineWidget + + + Enable/disable auto-scrolling + Увімк/вимк автопрокрутку + + + + Enable/disable loop-points + Увімк/вимк точки петлі + + + + After stopping go back to begin + Після зупинки переходити до початку + + + + After stopping go back to position at which playing was started + Після зупинки переходити до місця, з якого почалося відтворення + + + + After stopping keep position + Залишатися на місці зупинки + + + + + Hint + Підказка + + + + Press <%1> to disable magnetic loop points. + Натисніть <%1>, щоб прибрати прилипання точок циклу. + + + + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + Зажміть <Shift> щоб змістити початок точок циклу; Натисніть <%1>, щоб прибрати прилипання точок циклу. + + + + Track + + + Mute + Тиша + + + + Solo + Соло + + + + TrackContainer + + + Couldn't import file + Не можу імпортувати файл + + + + Couldn't find a filter for importing file %1. +You should convert this file into a format supported by LMMS using another software. + Не можу знайти фільтр для імпорту файла %1. +Для підключення цього файлу перетворіть його в формат, підтримуваний LMMS. + + + + Couldn't open file + Не можу відкрити файл + + + + Couldn't open file %1 for reading. +Please make sure you have read-permission to the file and the directory containing the file and try again! + Не можу відкрити файл %1 для запису. +Перевірте, чи володієте ви правами на запис в обраний файл і каталог що його містить і спробуйте знову! + + + + Loading project... + Завантаження проекту ... + + + + + Cancel + Скасувати + + + + + Please wait... + Зачекайте будь-ласка ... + + + + Loading cancelled + Завантаження скасовано + + + + Project loading was cancelled. + Завантаження проекту скасовано. + + + + Loading Track %1 (%2/Total %3) + Завантаження треку %1 (%2/з %3) + + + + Importing MIDI-file... + Імпортую файл MIDI... + + + + TrackContentObject + + + Mute + Тиша + + + + TrackContentObjectView + + + Current position + Позиція + + + + + Hint + Підказка + + + + Press <%1> and drag to make a copy. + Натисніть <%1> і перетягніть, щоб створити копію. + + + + Current length + Тривалість + + + + Press <%1> for free resizing. + Для вільної зміни розміру натисніть <%1>. + + + + + %1:%2 (%3:%4 to %5:%6) + %1:%2 (від %3:%4 до %5:%6) + + + + Delete (middle mousebutton) + Видалити (середня кнопка мишки) + + + + Cut + Вирізати + + + + Copy + Копіювати + + + + Paste + Вставити + + + + Mute/unmute (<%1> + middle click) + Заглушити/включити (<%1> + середня кнопка миші) + + + + TrackOperationsWidget + + + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Затисніть <%1> і натискайте мишку під час руху, щоб почати нову перезбірку. + + + + Actions for this track + Дії для цієї доріжки + + + + Mute + Тиша + + + + + Solo + Соло + + + + Mute this track + Відключити доріжку + + + + Clone this track + Клонувати доріжку + + + + Remove this track + Видалити доріжку + + + + Clear this track + Очистити цю доріжку + + + + FX %1: %2 + ЕФ %1: %2 + + + + Assign to new FX Channel + Призначити до нового каналу ефекту + + + + Turn all recording on + Включити все на запис + + + + Turn all recording off + Вимкнути всі записи + + + + TripleOscillatorView + + + Use phase modulation for modulating oscillator 1 with oscillator 2 + Модулювати фазу осциллятора 2 сигналом з 1 + + + + Use amplitude modulation for modulating oscillator 1 with oscillator 2 + Модулювати амплітуду осциллятора 2 сигналом з 1 + + + + Mix output of oscillator 1 & 2 + Змішати виходи 1 і 2 осцилляторів + + + + Synchronize oscillator 1 with oscillator 2 + Синхронізувати 1 осциллятор по 2 + + + + Use frequency modulation for modulating oscillator 1 with oscillator 2 + Модулювати частоту осциллятора 2 сигналом з 1 + + + + Use phase modulation for modulating oscillator 2 with oscillator 3 + Модулювати фазу осциллятора 3 сигналом з 2 + + + + Use amplitude modulation for modulating oscillator 2 with oscillator 3 + Модулювати амплітуду осциллятора 3 сигналом з 2 + + + + Mix output of oscillator 2 & 3 + Поєднати виходи осцилляторів 2 і 3 + + + + Synchronize oscillator 2 with oscillator 3 + Синхронізувати осциллятор 2 і 3 + + + + Use frequency modulation for modulating oscillator 2 with oscillator 3 + Модулювати частоту осциллятора 3 сигналом з 2 + + + + Osc %1 volume: + Гучність осциллятора %1: + + + + With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. + Ця ручка встановлює гучність осциллятора %1. Якщо 0, то осциллятор вимикається, інакше буде чутно настільки голосно, настільки тут встановлено. + + + + Osc %1 panning: + Баланс для осциллятора %1: + + + + With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. + Регулятор стереобалансу осциллятора %1. Величина -100 позначає, що 100% сигналу йде в лівий канал, а 100 - в правий. + + + + Osc %1 coarse detuning: + Грубе підстроювання осциллятора %1: + + + + semitones + півтон(а,ів) + + + + With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. + Ця ручка встановлює грубе підстроювання осцилятора %1. Ви можете пістроїти осцилятор на 24 півтони (2 октави) вгору і вниз. Це корисно для створення звуків з акорду. + + + + Osc %1 fine detuning left: + Точне підстроювання лівого каналу осциллятора %1: + + + + + cents + Відсотки + + + + With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + Ця ручка встановлює точне підстроювання для лівого каналу осциллятора %1. Підстроювання задається в діапазоні від -100 сотих до +100 сотих. Це корисно для створення "насичених" звуків. + + + + Osc %1 fine detuning right: + Точна підстройка правого канала осциллятора %1: + + + + With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + Ця ручка встановлює точне підстроювання для правого каналу осциллятора %1. Підстроювання задається в діапазоні від -100 сотих до +100 сотих. Це корисно для створення "насичених" звуків. + + + + Osc %1 phase-offset: + Зміщення фази осциллятора %1: + + + + + degrees + градуси + + + + With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + Ця ручка встановлює початкову фазу осциллятора %1, т. б. точку, з якої осциллятор починає виробляти сигнал. Наприклад, якщо ви задали синусоїдальну форму сигналу і початкову фазу 180º, хвиля спочатку піде вниз, а не вгору. Те ж саме для сигналу прямокутної форми. + + + + Osc %1 stereo phase-detuning: + Підстроювання стерео фази осциллятора %1: + + + + With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. + Ця ручка встановлює фазове підстроювання осциллятора %1 між каналами, тобто різницю фаз між лівим і правим каналами. Це зручно для створення розширення стереоефектів. + + + + Use a sine-wave for current oscillator. + Генерувати гармонійний (синусоїдальний) сигнал. + + + + Use a triangle-wave for current oscillator. + Генерувати трикутний сигнал. + + + + Use a saw-wave for current oscillator. + Генерувати зигзагоподібний сигнал. + + + + Use a square-wave for current oscillator. + Генерувати квадрат. + + + + Use a moog-like saw-wave for current oscillator. + Використовувати муг-зигзаг для цього осциллятора. + + + + Use an exponential wave for current oscillator. + Використовувати експонентний сигнал для цього осциллятора. + + + + Use white-noise for current oscillator. + Генерувати білий шум. + + + + Use a user-defined waveform for current oscillator. + Задати форму сигналу. + + + + VersionedSaveDialog + + + Increment version number + Збільшуючийся номер версії + + + + Decrement version number + Зменшуючийся номер версії + + + + already exists. Do you want to replace it? + вже існує. Замінити його? + + + + VestigeInstrumentView + + + Open other VST-plugin + Відкрити інший VST плагін + + + + Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. + Відкрити інший модуль VST. Після натискання на кнопку з'явиться стандартний діалог вибору файлу, де ви зможете вибрати потрібний модуль. + + + + Control VST-plugin from LMMS host + Управління VST плагіном через LMMS хост + + + + Click here, if you want to control VST-plugin from host. + Натисніть тут, для контролю VST плагіном через хост. + + + + Open VST-plugin preset + Відкрити передустановку VST плагіна + + + + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + Відкрити іншу .fxp . fxb передустановку VST. + + + + Previous (-) + Попередній <-> + + + + + Click here, if you want to switch to another VST-plugin preset program. + Перемикання на іншу передустановку програми VST плагіна. + + + + Save preset + Зберегти передустановку + + + + Click here, if you want to save current VST-plugin preset program. + Зберегти поточну передустановку програми VST плагіна. + + + + Next (+) + Наступний <+> + + + + Click here to select presets that are currently loaded in VST. + Вибір із уже завантажених в VST предустановок. + + + + Show/hide GUI + Показати / приховати інтерфейс + + + + Click here to show or hide the graphical user interface (GUI) of your VST-plugin. + Приховує / показує графічний користувальницький інтерфейс (GUI) обраного модуля VST. + + + + Turn off all notes + Вимкнути всі ноти + + + + Open VST-plugin + Відкрити модуль VST + + + + DLL-files (*.dll) + Бібліотеки DLL (*.dll) + + + + EXE-files (*.exe) + Програми EXE (*.exe) + + + + No VST-plugin loaded + Модуль VST не завантажений + + + + Preset + Передустановка + + + + by + від + + + + - VST plugin control + - Управління VST плагіном + + + + VisualizationWidget + + + click to enable/disable visualization of master-output + Натисніть, щоб увімкнути/вимкнути візуалізацію головного виводу + + + + Click to enable + Натисніть для включення + + + + VstEffectControlDialog + + + Show/hide + Показати/Сховати + + + + Control VST-plugin from LMMS host + Управління VST плагіном через LMMS хост + + + + Click here, if you want to control VST-plugin from host. + Натисніть тут, для контролю VST плагіном через хост. + + + + Open VST-plugin preset + Відкрити передустановку VST плагіна + + + + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + Відкрити іншу .fxp . fxb передустановку VST. + + + + Previous (-) + Попередній <-> + + + + + Click here, if you want to switch to another VST-plugin preset program. + Перемикання на іншу передустановку програми VST плагіна. + + + + Next (+) + Наступний <+> + + + + Click here to select presets that are currently loaded in VST. + Вибір із уже завантажених в VST предустановок. + + + + Save preset + Зберегти налаштування + + + + Click here, if you want to save current VST-plugin preset program. + Зберегти поточну передустановку програми VST плагіна. + + + + + Effect by: + Ефекти по: + + + + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + + + + VstPlugin + + + + The VST plugin %1 could not be loaded. + VST плагін %1 не може бути завантажено. + + + + Open Preset + Відкрити предустановку + + + + + Vst Plugin Preset (*.fxp *.fxb) + Передустановка VST плагіна (*.fxp, *.fxb) + + + + : default + : основні + + + + " + " + + + + ' + ' + + + + Save Preset + Зберегти предустановку + + + + .fxp + .fxp + + + + .FXP + .FXP + + + + .FXB + .FXB + + + + .fxb + .fxb + + + + Loading plugin + Завантаження модуля + + + + Please wait while loading VST plugin... + Будь ласка, зачекайте доки завантажується VST плагін ... + + + + WatsynInstrument + + + Volume A1 + Гучність A1 + + + + Volume A2 + Гучність A2 + + + + Volume B1 + Гучність B1 + + + + Volume B2 + Гучність B2 + + + + Panning A1 + Баланс A1 + + + + Panning A2 + Баланс A2 + + + + Panning B1 + Баланс B1 + + + + Panning B2 + Баланс B2 + + + + Freq. multiplier A1 + Множник частоти A1 + + + + Freq. multiplier A2 + Множник частоти A2 + + + + Freq. multiplier B1 + Множник частоти B1 + + + + Freq. multiplier B2 + Множник частоти B2 + + + + Left detune A1 + Ліве підстроювання A1 + + + + Left detune A2 + Ліве підстроювання A2 + + + + Left detune B1 + Ліве підстроювання B1 + + + + Left detune B2 + Ліве підстроювання B2 + + + + Right detune A1 + Праве підстроювання A1 + + + + Right detune A2 + Праве підстроювання A2 + + + + Right detune B1 + Праве підстроювання B1 + + + + Right detune B2 + Праве підстроювання B2 + + + + A-B Mix + A-B Мікс + + + + A-B Mix envelope amount + A-B Мікс кіл. обвідної + + + + A-B Mix envelope attack + A-B Мікс атаки обвідної + + + + A-B Mix envelope hold + A-B Мікс утримання обвідної + + + + A-B Mix envelope decay + A-B Мікс згасання обвідної + + + + A1-B2 Crosstalk + Перехресні перешкоди A1-B2 + + + + A2-A1 modulation + Модуляція A2-A1 + + + + B2-B1 modulation + Модуляція B2-B1 + + + + Selected graph + Обраний графік + + + + WatsynView + + + + + + Volume + Гучність + + + + + + + Panning + Баланс + + + + + + + Freq. multiplier + Множник частоти + + + + + + + Left detune + Ліве підстроювання + + + + + + + + + + + cents + відсотків + + + + + + + Right detune + Праве підстроювання + + + + A-B Mix + A-B Мікс + + + + Mix envelope amount + Мікс кількості обвідної + + + + Mix envelope attack + A-B Мікс вступу обвідної + + + + Mix envelope hold + A-B Мікс утримання обвідної + + + + Mix envelope decay + A-B Мікс згасання обвідної + + + + Crosstalk + Перехід + + + + Select oscillator A1 + Виберіть генератор A1 + + + + Select oscillator A2 + Виберіть генератор A2 + + + + Select oscillator B1 + Виберіть генератор B1 + + + + Select oscillator B2 + Виберіть генератор B2 + + + + Mix output of A2 to A1 + Змішати виходи A2 до A1 + + + + Modulate amplitude of A1 with output of A2 + Модулювати амплітуду А1 виходом з А2 + + + + Ring-modulate A1 and A2 + Кільцева модуляція А1 і А2 + + + + Modulate phase of A1 with output of A2 + Модулювати фазу А1 виходом з А2 + + + + Mix output of B2 to B1 + Змішати виходи В2 до В1 + + + + Modulate amplitude of B1 with output of B2 + Модулювати амплітуду В1 виходом з В2 + + + + Ring-modulate B1 and B2 + Кільцева модуляція В1 і В2 + + + + Modulate phase of B1 with output of B2 + Модулювати фазу В1 виходом з В2 + + + + + + + Draw your own waveform here by dragging your mouse on this graph. + Тут ви можете малювати власний сигнал. + + + + Load waveform + Завантаження форми звуку + + + + Click to load a waveform from a sample file + Натисніть для завантаження форми звуку з файлу із зразком + + + + Phase left + Фаза зліва + + + + Click to shift phase by -15 degrees + Натисніть, щоб змістити фазу на -15 градусів + + + + Phase right + Фаза праворуч + + + + Click to shift phase by +15 degrees + Натисніть, щоб змістити фазу на +15 градусів + + + + Normalize + Нормалізувати + + + + Click to normalize + Натисніть для нормалізації + + + + Invert + Інвертувати + + + + Click to invert + Натисніть щоб інвертувати + + + + Smooth + Згладити + + + + Click to smooth + Натисніть щоб згладити + + + + Sine wave + Синусоїда + + + + Click for sine wave + Згенерувати гармонійний (синусоїдальний) сигнал + + + + + Triangle wave + Трикутна хвиля + + + + Click for triangle wave + Згенерувати трикутний сигнал + + + + Click for saw wave + Згенерувати зигзагоподібний сигнал + + + + Square wave + Квадратна хвиля + + + + Click for square wave + Згенерувати квадратний сигнал + + + + ZynAddSubFxInstrument + + + Portamento + Портаменто + + + + Filter Frequency + Фільтр Частот + + + + Filter Resonance + Фільтр резонансу + + + + Bandwidth + Ширина смуги + + + + FM Gain + Підсил FM + + + + Resonance Center Frequency + Частоти центру резонансу + + + + Resonance Bandwidth + Ширина смуги резонансу + + + + Forward MIDI Control Change Events + Переслати зміну подій MIDI управління + + + + ZynAddSubFxView + + + Portamento: + Портаменто: + + + + PORT + PORT + + + + Filter Frequency: + Фільтр частот: + + + + FREQ + FREQ + + + + Filter Resonance: + Фільтр резонансу: + + + + RES + RES + + + + Bandwidth: + Смуга пропускання: + + + + BW + BW + + + + FM Gain: + Підсилення частоти модуляції (FM): + + + + FM GAIN + FM GAIN + + + + Resonance center frequency: + Частота центру резонансу: + + + + RES CF + RES CF + + + + Resonance bandwidth: + Ширина смуги резонансу: + + + + RES BW + RES BW + + + + Forward MIDI Control Changes + Переслати зміну подій MiDi управління + + + + Show GUI + Показати інтерфейс + + + + Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + Натисніть сюди щоб сховати чи показати графічний інтерфейс ZynAddSubFX. + + + + audioFileProcessor + + + Amplify + Підсилення + + + + Start of sample + Початок запису + + + + End of sample + Кінець запису + + + + Loopback point + Точка повернення з повтору + + + + Reverse sample + Перевернути запис + + + + Loop mode + Режим повтору + + + + Stutter + Заїкання + + + + Interpolation mode + Режим Інтерполяції + + + + None + Нічого + + + + Linear + Лінійний + + + + Sinc + Синхронізований + + + + Sample not found: %1 + Запис не знайдено: %1 + + + + bitInvader + + + Samplelength + Тривалість + + + + bitInvaderView + + + Sample Length + Тривалість запису + + + + Draw your own waveform here by dragging your mouse on this graph. + Тут ви можете малювати власний сигнал. + + + + Sine wave + Синусоїда + + + + Click for a sine-wave. + Генерувати гармонійний (синусоїдальний) сигнал. + + + + Triangle wave + Трикутник + + + + Click here for a triangle-wave. + Згенерувати трикутний сигнал. + + + + Saw wave + Зигзаг + + + + Click here for a saw-wave. + Згенерувати зигзаг. + + + + Square wave + Квадрат + + + + Click here for a square-wave. + Згенерувати квадратний сигнал. + + + + White noise wave + Білий шум + + + + Click here for white-noise. + Згенерувати білий шум. + + + + User defined wave + Користувацька + + + + Click here for a user-defined shape. + Задати форму сигналу вручну. + + + + Smooth + Згладити + + + + Click here to smooth waveform. + Клацніть щоб згладити форму сигналу. + + + + Interpolation + Інтерполяція + + + + Normalize + Нормалізувати + + + + dynProcControlDialog + + + INPUT + ВХІД + + + + Input gain: + Вхідне підсилення: + + + + OUTPUT + ВИХІД + + + + Output gain: + Вихідне підсилення: + + + + ATTACK + ВСТУП + + + + Peak attack time: + Час пікової атаки: + + + + RELEASE + ЗМЕНШЕННЯ + + + + Peak release time: + Час відпуску піку: + + + + Reset waveform + Скидання сигналу + + + + Click here to reset the wavegraph back to default + Натисніть тут, щоб скинути граф хвилі назад за замовчуванням + + + + Smooth waveform + Згладжений сигнал + + + + Click here to apply smoothing to wavegraph + Натисніть тут, щоб застосувати згладжування графа хвилі + + + + Increase wavegraph amplitude by 1dB + Збільште амплітуди графа хвилі на 1дБ + + + + Click here to increase wavegraph amplitude by 1dB + Натисніть тут, щоб збільшити амплітуду графа хвилі на 1дБ + + + + Decrease wavegraph amplitude by 1dB + Зменшення амплітуди графа хвилі на 1дБ + + + + Click here to decrease wavegraph amplitude by 1dB + Натисніть тут, щоб зменшити амплітуду графа хвилі на 1дБ + + + + Stereomode Maximum + Максимальний стереорежим + + + + Process based on the maximum of both stereo channels + Процес заснований на максимумі від обох каналів + + + + Stereomode Average + Середній стереорежим + + + + Process based on the average of both stereo channels + Процес заснований на середньому обох каналів + + + + Stereomode Unlinked + Розімкнений стереорежим + + + + Process each stereo channel independently + Обробляє кожен стерео канал незалежно + + + + dynProcControls + + + Input gain + Вхідне підсилення + + + + Output gain + Вихідне підсилення + + + + Attack time + Час вступу + + + + Release time + Час зменшення + + + + Stereo mode + Стерео режим + + + + expressiveView + + Select oscillator W1 + + + + Select oscillator W2 + + + + Select oscillator W3 + + + + Select OUTPUT 1 + + + + Select OUTPUT 2 + + + + Open help window + + + + Sine wave + Синусоїда + + + Click for a sine-wave. + Генерувати гармонійний (синусоїдальний) сигнал. + + + Moog-Saw wave + + + + Click for a Moog-Saw-wave. + + + + Exponential wave + Експоненціальна хвиля + + + Click for an exponential wave. + + + + Saw wave + Зигзаг + + + Click here for a saw-wave. + Згенерувати зигзаг. + + + User defined wave + Користувацька + + + Click here for a user-defined shape. + Задати форму сигналу вручну. + + + Triangle wave + Трикутник + + + Click here for a triangle-wave. + Згенерувати трикутний сигнал. + + + Square wave + Квадратна хвиля + + + Click here for a square-wave. + Згенерувати квадратний сигнал. + + + White noise wave + Білий шум + + + Click here for white-noise. + Згенерувати білий шум. + + + WaveInterpolate + + + + ExpressionValid + + + + General purpose 1: + + + + General purpose 2: + + + + General purpose 3: + + + + O1 panning: + + + + O2 panning: + + + + Release transition: + + + + Smoothness + + + + + fxLineLcdSpinBox + + + Assign to: + Призначити до: + + + + New FX Channel + Новий ефект каналу + + + + graphModel + + + Graph + Графік + + + + kickerInstrument + + + Start frequency + Початкова частота + + + + End frequency + Кінцева частота + + + + Length + Довжина + + + + Distortion Start + Початкове спотворення + + + + Distortion End + Кінцеве спотворення + + + + Gain + Підсилення + + + + Envelope Slope + Нахил обвідної + + + + Noise + Шум + + + + Click + Натисніть + + + + Frequency Slope + Частота нахилу + + + + Start from note + Почати з замітки + + + + End to note + Закінчити заміткою + + + + kickerInstrumentView + + + Start frequency: + Початкова частота: + + + + End frequency: + Кінцева частота: + + + + Frequency Slope: + Частота нахилу: + + + + Gain: + Підсилення: + + + + Envelope Length: + Довжина обвідної: + + + + Envelope Slope: + Нахил обвідної: + + + + Click: + Натиснення: + + + + Noise: + Шум: + + + + Distortion Start: + Початкове спотворення: + + + + Distortion End: + Кінцеве спотворення: + + + + ladspaBrowserView + + + + Available Effects + Доступні ефекти + + + + + Unavailable Effects + Недоступні ефекти + + + + + Instruments + Інструменти + + + + + Analysis Tools + Аналізатори + + + + + Don't know + Невідомі + + + + This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. + +Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. + +Unavailable Effects are those that were identified as effects, but either didn't have the same number of input and output channels or weren't real time capable. + +Instruments are plugins for which only output channels were identified. + +Analysis Tools are plugins for which only input channels were identified. + +Don't Knows are plugins for which no input or output channels were identified. + +Double clicking any of the plugins will bring up information on the ports. + У цьому вікні показана інформація про всі модулі LADSPA, які виявила LMMS. Вони розділені на п'ять категорій, залежно від назв і типів портів. + +Доступні ефекти - це ті, які можуть бути використані в LMMS. Щоб ефект LADSPA міг бути використаний, він повинен, по-перше, бути власне ефектом, т. б. мати як вхідні так і вихідні канали. LMMS в якості вхідного каналу сприймає аудіопорти, що містять у назві "in", а вихідні вгадує по підстрочці "out". Для використання в LMMS число вхідних каналів має збігатися з числом вихідних, і ефект повинен мати можливість використання в реальному часі. + +Недоступні ефекти - це модулі LADSPA, розпізнані як ефекти, однак або з незбіжною кількістю вхідних/вихідних каналів, або не призначені для використання в реальному часі. + +Інструменти - це модулі, у яких є тільки вихідні канали. + +Аналізатори - це модулі, що володіють лише вхідними каналами. + +Невідомі - модулі, у яких не було виявлено ні вхідних, ні вихідних каналів. + +Подвійне клацання лівою кнопкою миші по модулю дасть інформацію по його портах. + + + + Type: + Тип: + + + + ladspaDescription + + + Plugins + Модулі + + + + Description + Опис + + + + ladspaPortDialog + + + Ports + Порти + + + + Name + І'мя + + + + Rate + Частота вибірки + + + + Direction + Напрямок + + + + Type + Тип + + + + Min < Default < Max + Менше < Стандарт <Більше + + + + Logarithmic + Логарифмічний + + + + SR Dependent + Залежність від SR + + + + Audio + Аудіо + + + + Control + Управління + + + + Input + Ввід + + + + Output + Вивід + + + + Toggled + Увімкнено + + + + Integer + Ціле + + + + Float + Дробове + + + + + Yes + Так + + + + lb302Synth + + + VCF Cutoff Frequency + Частота зрізу VCF + + + + VCF Resonance + Посилення VCF + + + + VCF Envelope Mod + Модуляція обвідної VCF + + + + VCF Envelope Decay + Спад обвідної VCF + + + + Distortion + Спотворення + + + + Waveform + Форма хвилі + + + + Slide Decay + Зміщення згасання + + + + Slide + Зміщення + + + + Accent + Акцент + + + + Dead + Глухо + + + + 24dB/oct Filter + 24дБ/окт фільтр + + + + lb302SynthView + + Cutoff Freq: Частота зрізу: - Resonance: - Резонанс: + + Resonance: + Резонанс: + + + + Env Mod: + Мод Обвідної: + + + + Decay: + Згасання: + + + + 303-es-que, 24dB/octave, 3 pole filter + 303-ій, 24дБ/октаву, 3-польний фільтр + + + + Slide Decay: + Зміщення згасання: + + + + DIST: + СПОТ: + + + + Saw wave + Зигзаг + + + + Click here for a saw-wave. + Згенерувати зигзаг. + + + + Triangle wave + Трикутна хвиля + + + + Click here for a triangle-wave. + Згенерувати трикутний сигнал. + + + + Square wave + Квадрат + + + + Click here for a square-wave. + Згенерувати квадратний сигнал. + + + + Rounded square wave + Хвиля округленого квадрату + + + + Click here for a square-wave with a rounded end. + Створити квадратну хвилю закруглену в кінці. + + + + Moog wave + Муг хвиля + + + + Click here for a moog-like wave. + Згенерувати хвилю схожу на муг. + + + + Sine wave + Синусоїда + + + + Click for a sine-wave. + Генерувати гармонійний (синусоїдальний) сигнал. + + + + + White noise wave + Білий шум + + + + Click here for an exponential wave. + Генерувати експонентний сигнал. + + + + Click here for white-noise. + Згенерувати білий шум. + + + + Bandlimited saw wave + Зигзаг хвиля з обмеженою смугою + + + + Click here for bandlimited saw wave. + Натисніть тут для пилкоподібної хвилі з обмеженою смугою. + + + + Bandlimited square wave + Квадратна хвиля з обмеженою смугою + + + + Click here for bandlimited square wave. + Натисніть тут для квадратної хвилі з обмеженою смугою. + + + + Bandlimited triangle wave + Трикутна хвиля з обмеженою смугою + + + + Click here for bandlimited triangle wave. + Натисніть тут для трикутної хвилі з обмеженою смугою. + + + + Bandlimited moog saw wave + Муг-зигзаг хвиля з обмеженою смугою + + + + Click here for bandlimited moog saw wave. + Натисніть тут для муг-зигзаг хвилі з обмеженою смугою. + + + + malletsInstrument + + + Hardness + Жорсткість + + + + Position + Положення + + + + Vibrato Gain + Посилення вібрато + + + + Vibrato Freq + Частота вібрато + + + + Stick Mix + Зведення рученят + + + + Modulator + Модулятор + + + + Crossfade + Перехід + + + + LFO Speed + Швидкість LFO + + + + LFO Depth + Глибина LFO + + + + ADSR + ADSR + + + + Pressure + Тиск + + + + Motion + Рух + + + + Speed + Швидкість + + + + Bowed + Нахил + + + + Spread + Розкид + + + + Marimba + Марімба + + + + Vibraphone + Віброфон + + + + Agogo + Дискотека + + + + Wood1 + Дерево1 + + + + Reso + Ресо + + + + Wood2 + Дерево2 + + + + Beats + Удари + + + + Two Fixed + Два фіксованих + + + + Clump + Важка хода + + + + Tubular Bells + Трубні дзвони + + + + Uniform Bar + Рівномірні смуги + + + + Tuned Bar + Підстроєні смуги + + + + Glass + Скло + + + + Tibetan Bowl + Тибетські кулі + + + + malletsInstrumentView + + + Instrument + Інструмент + + + + Spread + Розкид - Env Mod: - Мод Обвідної: + + Spread: + Розкид: - Decay: - Згасання: + + Missing files + Відсутні файли - 303-es-que, 24dB/octave, 3 pole filter - 303-ій, 24дБ/октаву, 3-польний фільтр + + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! + Схоже, що встановлені не всі пакети Stk. Вам слід це перевірити! - Slide Decay: - Зміщення згасання: + + Hardness + Жорсткість - DIST: - СПОТ: + + Hardness: + Жорсткість: - Saw wave - Зигзаг + + Position + Положення - Click here for a saw-wave. - Згенерувати зигзаг. + + Position: + Положення: - Triangle wave - Трикутна хвиля + + Vib Gain + Підс. вібрато - Click here for a triangle-wave. - Згенерувати трикутний сигнал. + + Vib Gain: + Підс. вібрато: - Square wave - Квадрат + + Vib Freq + Част. віб - Click here for a square-wave. - Згенерувати квадратний сигнал. + + Vib Freq: + Вібрато: - Rounded square wave - Хвиля округленого квадрату + + Stick Mix + Зведення рученят - Click here for a square-wave with a rounded end. - Створити квадратну хвилю закруглену в кінці. + + Stick Mix: + Зведення рученят: - Moog wave - Муг хвиля + + Modulator + Модулятор - Click here for a moog-like wave. - Згенерувати хвилю схожу на муг. + + Modulator: + Модулятор: - Sine wave - Синусоїда + + Crossfade + Перехід - Click for a sine-wave. - Генерувати гармонійний (синусоїдальний) сигнал. + + Crossfade: + Перехід: - White noise wave - Білий шум + + LFO Speed + Швидкість LFO - Click here for an exponential wave. - Генерувати експонентний сигнал. + + LFO Speed: + Швидкість LFO: - Click here for white-noise. - Згенерувати білий шум. + + LFO Depth + Глибина LFO - Bandlimited saw wave - Зигзаг хвиля з обмеженою смугою + + LFO Depth: + Глибина LFO: - Click here for bandlimited saw wave. - Натисніть тут для пилкоподібної хвилі з обмеженою смугою. + + ADSR + ADSR - Bandlimited square wave - Квадратна хвиля з обмеженою смугою + + ADSR: + ADSR: - Click here for bandlimited square wave. - Натисніть тут для квадратної хвилі з обмеженою смугою. + + Pressure + Тиск - Bandlimited triangle wave - Трикутна хвиля з обмеженою смугою + + Pressure: + Тиск: - Click here for bandlimited triangle wave. - Натисніть тут для трикутної хвилі з обмеженою смугою. + + Speed + Швидкість - Bandlimited moog saw wave - Муг-зигзаг хвиля з обмеженою смугою + + Speed: + Швидкість: + + + manageVSTEffectView - Click here for bandlimited moog saw wave. - Натисніть тут для муг-зигзаг хвилі з обмеженою смугою. + + - VST parameter control + Управление VST параметрами + + + + VST Sync + VST синхронізація + + + + Click here if you want to synchronize all parameters with VST plugin. + Натисніть тут для синхронізації всіх параметрів VST плагіна. + + + + + Automated + Автоматизовано + + + + Click here if you want to display automated parameters only. + Натисніть тут, якщо хочете бачити тільки автоматизовані параметри. + + + + Close + Закрити + + + + Close VST effect knob-controller window. + Закрити вікно управління регуляторами VST плагіна. - malletsInstrument + manageVestigeInstrumentView - Hardness - Жорсткість + + + - VST plugin control + Управління VST плагіном - Position - Положення + + VST Sync + VST синхронізація - Modulator - Модулятор + + Click here if you want to synchronize all parameters with VST plugin. + Натисніть тут для синхронізації всіх параметрів VST плагіна. - Crossfade - Перехід + + + Automated + Автоматизовано - ADSR - ADSR + + Click here if you want to display automated parameters only. + Натисніть тут, якщо хочете бачити тільки автоматизовані параметри. - Pressure - Тиск + + Close + Закрити - Motion - Рух + + Close VST plugin knob-controller window. + Закрити вікно управління регуляторами VST плагіна. + + + + opl2instrument + + + Patch + Патч + + + + Op 1 Attack + ОП 1 Вступ + + + + Op 1 Decay + ОП 1 Спад + + + + Op 1 Sustain + ОП 1 Видержка + + + + Op 1 Release + ОП 1 Зменшення + + + + Op 1 Level + ОП 1 Рівень + + + + Op 1 Level Scaling + ОП 1 Рівень збільшення + + + + Op 1 Frequency Multiple + ОП 1 Множник частот + + + + Op 1 Feedback + ОП 1 Повернення + + + + Op 1 Key Scaling Rate + ОП 1 Ключова ставка множника + + + + Op 1 Percussive Envelope + ОП 1 Ударна обвідна + + + + Op 1 Tremolo + ОП 1 Тремоло + + + + Op 1 Vibrato + Оп 1 Вібрато + + + + Op 1 Waveform + ОП 1 Хвиля + + + + Op 2 Attack + ОП 2 Вступ + + + + Op 2 Decay + ОП 2 Спад + + + + Op 2 Sustain + ОП 2 Видержка + + + + Op 2 Release + ОП 2 Зменшення + + + + Op 2 Level + ОП 2 Рівень + + + + Op 2 Level Scaling + ОП 2 Рівень збільшення + + + + Op 2 Frequency Multiple + ОП 2 Множник частот + + + + Op 2 Key Scaling Rate + ОП 2 Ключова ставка множника + + + + Op 2 Percussive Envelope + ОП 2 Ударна обвідна + + + + Op 2 Tremolo + ОП 2 Тремоло + + + + Op 2 Vibrato + Оп 2 Вібрато + + + + Op 2 Waveform + ОП 2 Хвиля + + + + FM + FM + + + + Vibrato Depth + Глибина вібрато + + + + Tremolo Depth + Глибина тремоло + + + + opl2instrumentView + + + + Attack + Вступ + + + + + Decay + Згасання + + + + + Release + Зменшення + + + + + Frequency multiplier + Множник частоти + + + + organicInstrument + + + Distortion + Спотворення + + + + Volume + Гучність + + + + organicInstrumentView + + + Distortion: + Спотворення: + + + + The distortion knob adds distortion to the output of the instrument. + Спотворення додає спотворення до виходу інструменту. + + + + Volume: + Гучність: + + + + The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. + Регулятор гучності виведення інструменту, підсумовується з регулятором гучності вікна інструменту. + + + + Randomise + Випадково + + + + The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. + Кнопка рандомізації випадково встановлює всі регулятори, крім гармонік, основної гучності і регулятора спотворень. + + + + + Osc %1 waveform: + Форма сигналу осциллятора %1: - Speed - Швидкість + + Osc %1 volume: + Гучність осциллятора %1: - Bowed - Нахил + + Osc %1 panning: + Баланс для осциллятора %1: - Spread - Розкид + + Osc %1 stereo detuning + Осц %1 стерео расстройка - Marimba - Марімба + + cents + соті - Vibraphone - Віброфон + + Osc %1 harmonic: + Осц %1 гармоніка: + + + FreeBoyInstrument - Agogo - Дискотека + + Sweep time + Час поширення - Reso - Ресо + + Sweep direction + Напрям поширення - Beats - Удари + + Sweep RtShift amount + Кіл-ть розгортки зсуву вправо - Clump - Важка хода + + + Wave Pattern Duty + Робоча форма хвилі - Glass - Скло + + Channel 1 volume + Гучність першого каналу - Vibrato gain - + + + + Volume sweep direction + Обсяг напрямку поширення - Vibrato frequency - + + + + Length of each step in sweep + Довжина кожного кроку в розгортці - Stick mix - + + Channel 2 volume + Гучність другого каналу - LFO speed - Швидкість LFO + + Channel 3 volume + Гучність третього каналу - LFO depth - + + Channel 4 volume + Гучність четвертого каналу - Wood 1 - + + Shift Register width + Зміщення ширини регістра - Wood 2 - + + Right Output level + Вихідний рівень праворуч - Two fixed - + + Left Output level + Вихідний рівень зліва - Tubular bells - + + Channel 1 to SO2 (Left) + Від першого каналу до SO2 (лівий канал) - Uniform bar - + + Channel 2 to SO2 (Left) + Від другого каналу до SO2 (лівий канал) - Tuned bar - + + Channel 3 to SO2 (Left) + Від третього каналу до SO2 (лівий канал) - Tibetan bowl - + + Channel 4 to SO2 (Left) + Від четвертого каналу до SO2 (лівий канал) - - - malletsInstrumentView - Instrument - Інструмент + + Channel 1 to SO1 (Right) + Від першого каналу до SO1 (правий канал) - Spread - Розкид + + Channel 2 to SO1 (Right) + Від другого каналу до SO1 (правий канал) - Spread: - Розкид: + + Channel 3 to SO1 (Right) + Від третього каналу до SO1 (правий канал) - Hardness - Жорсткість + + Channel 4 to SO1 (Right) + Від четвертого каналу до SO1 (правий канал) - Hardness: - Жорсткість: + + Treble + Дискант - Position - Положення + + Bass + Бас + + + FreeBoyInstrumentView - Position: - Положення: + + Sweep Time: + Час розгортки: - Modulator - Модулятор + + Sweep Time + Час розгортки - Modulator: - Модулятор: + + The amount of increase or decrease in frequency + Кіл-ть збільшення або зменшення в частоті - Crossfade - Перехід + + Sweep RtShift amount: + Кіл-ть розгортки зміщення вправо: - Crossfade: - Перехід: + + Sweep RtShift amount + Кіл-ть розгортки зсуву вправо - ADSR - ADSR + + The rate at which increase or decrease in frequency occurs + Темп прояви збільшення або зниження в частоті - ADSR: - ADSR: + + + Wave pattern duty: + Робоча форма хвилі: - Pressure - Тиск + + Wave Pattern Duty + Робоча форма хвилі - Pressure: - Тиск: + + + The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. + Робочий цикл це коефіцієнт тривалості (часу) включеного сигналу відносно всього періоду сигналу. - Speed - Швидкість + + + Square Channel 1 Volume: + Гучність квадратного каналу 1: - Speed: - Швидкість: + + Square Channel 1 Volume + Гучність квадратного каналу 1 - Missing files - Відсутні файли + + + + Length of each step in sweep: + Довжина кожного кроку в розгортці: - Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! - Схоже, що встановлені не всі пакети Stk. Вам слід це перевірити! + + + + Length of each step in sweep + Довжина кожного кроку в розгортці - Vibrato gain - + + + + The delay between step change + Затримка між змінами кроку - Vibrato gain: - + + Wave pattern duty + Робоча форма хвилі - Vibrato frequency - + + Square Channel 2 Volume: + Гучність квадратного каналу 2: - Vibrato frequency: - + + + Square Channel 2 Volume + Гучність квадратного каналу 2 - Stick mix - + + Wave Channel Volume: + Гучність хвильового каналу: - Stick mix: - + + + Wave Channel Volume + Гучність хвильового каналу - LFO speed - Швидкість LFO + + Noise Channel Volume: + Гучність каналу шуму: - LFO speed: - Швидкість LFO: + + + Noise Channel Volume + Гучність каналу шуму - LFO depth - + + SO1 Volume (Right): + Гучність SO1 (Правий): - LFO depth: - + + SO1 Volume (Right) + Гучність SO1 (Правий) - - - manageVSTEffectView - - VST parameter control - Управление VST параметрами + + SO2 Volume (Left): + Гучність SO2 (Лівий): - Automated - Автоматизовано + + SO2 Volume (Left) + Гучність SO2 (Лівий) - Close - Закрити + + Treble: + Дискант: - VST sync - + + Treble + Дискант - - - manageVestigeInstrumentView - - VST plugin control - Управління VST плагіном + + Bass: + Бас: - VST Sync - VST синхронізація + + Bass + Бас - Automated - Автоматизовано + + Sweep Direction + Напрямок розгортки - Close - Закрити + + + + + + Volume Sweep Direction + Гучність напрямки розгортки - - - organicInstrument - Distortion - Спотворення + + Shift Register Width + Зміщення ширини регістра - Volume - Гучність + + Channel1 to SO1 (Right) + Канал1 в SO1 (Правий) - - - organicInstrumentView - Distortion: - Спотворення: + + Channel2 to SO1 (Right) + Канал2 в SO1 (Правий) - Volume: - Гучність: + + Channel3 to SO1 (Right) + Канал3 в SO1 (Правий) - Randomise - Випадково + + Channel4 to SO1 (Right) + Канал4 в SO1 (Правий) - Osc %1 waveform: - Форма сигналу осциллятора %1: + + Channel1 to SO2 (Left) + Канал1 в SO2 (Лівий) - Osc %1 volume: - Гучність осциллятора %1: + + Channel2 to SO2 (Left) + Канал2 в SO2 (Лівий) - Osc %1 panning: - Баланс для осциллятора %1: + + Channel3 to SO2 (Left) + Канал3 в SO2 (Лівий) - cents - соті + + Channel4 to SO2 (Left) + Канал4 в SO2 (Лівий) - Osc %1 stereo detuning - Осц %1 стерео расстройка + + Wave Pattern + Малюнок хвилі - Osc %1 harmonic: - Осц %1 гармоніка: + + Draw the wave here + Малювати хвилю тут patchesDialog + Qsynth: Channel Preset Q-Синтезатор: Канал передустановлено + Bank selector Селектор банку + Bank Банк + Program selector Селектор програм + Patch Патч + Name І'мя + OK ОК + Cancel Скасувати @@ -4310,449 +11880,634 @@ pluginBrowser - Incomplete monophonic imitation tb303 - Незавершена монофонічна імітація tb303 + + no description + опис відсутній - Plugin for freely manipulating stereo output - Модуль для довільного управління стереовиходом + + A native amplifier plugin + Рідний плагін підсилення - Plugin for controlling knobs with sound peaks - Модуль для встановлення значень регуляторів на піках гучності + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + Простий семплер з різними налаштуваннями для використання записів (наприклад, ударні) в інструментальному трекі - Plugin for enhancing stereo separation of a stereo input file - Модуль, що підсилює різницю між каналами стереозапису + + Boost your bass the fast and simple way + Накачай свій бас швидко і просто - List installed LADSPA plugins - Показати встановлені модулі LADSPA + + Customizable wavetable synthesizer + Налаштовуваний синтезатор звукозаписів (wavetable) - GUS-compatible patch instrument - Патч-інструмент, сумісний з GUS + + An oversampling bitcrusher + Перевибірка малого дробдення - Additive Synthesizer for organ-like sounds - Синтезатор звуків нашталт органу + + Carla Patchbay Instrument + Carla Комутаційний інструмент - Tuneful things to bang on - Мелодійні ударні + + Carla Rack Instrument + Carla підставочний інструмент - VST-host for using VST(i)-plugins within LMMS - VST - хост для підтримки модулів VST(i) в LMMS + + A 4-band Crossover Equalizer + 4-смуговий еквалайзер Кросовер - Vibrating string modeler - Емуляція вібруючих струн + + A native delay plugin + Рідний плагін затримки - plugin for using arbitrary LADSPA-effects inside LMMS. - Модуль, що дозволяє використовувати в LMMS будь які ефекти LADSPA. + + A Dual filter plugin + Плагін подвійного фільтру - Filter for importing MIDI-files into LMMS - Фільтр для включення файлу MIDI в проект ЛММС + + plugin for processing dynamics in a flexible way + плагін для обробки динаміки гнучким методом - Emulation of the MOS6581 and MOS8580 SID. -This chip was used in the Commodore 64 computer. - Емуляція MOS6581 і MOS8580. -Використовувалося на комп'ютері Commodore 64. + + A native eq plugin + Рідний eq плагін - Player for SoundFont files - Програвач файлів SoundFont + + A native flanger plugin + Рідний фланжер плагін - Emulation of GameBoy (TM) APU - Емуляція GameBoy (ТМ) + + Player for GIG files + Програвач GIG файлів - Customizable wavetable synthesizer - Налаштовуваний синтезатор звукозаписів (wavetable) + + Filter for importing Hydrogen files into LMMS + Фільтр для імпорту Hydrogen файлів в LMMS - Embedded ZynAddSubFX - Вбудований ZynAddSubFX + + Versatile drum synthesizer + Універсальний барабанний синтезатор + + + + List installed LADSPA plugins + Показати встановлені модулі LADSPA + + + + plugin for using arbitrary LADSPA-effects inside LMMS. + Модуль, що дозволяє використовувати в LMMS будь які ефекти LADSPA. - 2-operator FM Synth - 2-режимний синт модуляції частот (FM synth) + + Incomplete monophonic imitation tb303 + Незавершена монофонічна імітація tb303 - Filter for importing Hydrogen files into LMMS - Фільтр для імпорту Hydrogen файлів в LMMS + + Filter for exporting MIDI-files from LMMS + Фільтри для експорту MIDI-файлів з LMMS - LMMS port of sfxr - LMMS порт SFXR + + Filter for importing MIDI-files into LMMS + Фільтр для включення файлу MIDI в проект ЛММС + Monstrous 3-oscillator synth with modulation matrix Монстро 3-осцилляторний синт з матрицею модуляції - Three powerful oscillators you can modulate in several ways - Три потужних генераторів можна модулювати декількома способами + + A multitap echo delay plugin + Плагін багаторазової послідовної затримки відлуння - A native amplifier plugin - Рідний плагін підсилення + + A NES-like synthesizer + NES-подібний синтезатор - Carla Rack Instrument - Carla підставочний інструмент + + 2-operator FM Synth + 2-режимний синт модуляції частот (FM synth) - 4-oscillator modulatable wavetable synth - 4-генераторний модулюючий синтезатор звукозаписів + + Additive Synthesizer for organ-like sounds + Синтезатор звуків нашталт органу - plugin for waveshaping - плагін формування сигналу + + Emulation of GameBoy (TM) APU + Емуляція GameBoy (ТМ) - Boost your bass the fast and simple way - Накачай свій бас швидко і просто + + GUS-compatible patch instrument + Патч-інструмент, сумісний з GUS - Versatile drum synthesizer - Універсальний барабанний синтезатор + + Plugin for controlling knobs with sound peaks + Модуль для встановлення значень регуляторів на піках гучності - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - Простий семплер з різними налаштуваннями для використання записів (наприклад, ударні) в інструментальному трекі + + Reverb algorithm by Sean Costello + Алгоритм реверберації Шона Костелло - plugin for processing dynamics in a flexible way - плагін для обробки динаміки гнучким методом + + Player for SoundFont files + Програвач файлів SoundFont - Carla Patchbay Instrument - Carla Комутаційний інструмент + + LMMS port of sfxr + LMMS порт SFXR - plugin for using arbitrary VST effects inside LMMS. - плагін для використання довільних VST ефектів всередині LMMS. + + Emulation of the MOS6581 and MOS8580 SID. +This chip was used in the Commodore 64 computer. + Емуляція MOS6581 і MOS8580. +Використовувалося на комп'ютері Commodore 64. + Graphical spectrum analyzer plugin Плагін графічного аналізу спектру - A NES-like synthesizer - NES-подібний синтезатор - - - A native delay plugin - Рідний плагін затримки + + Plugin for enhancing stereo separation of a stereo input file + Модуль, що підсилює різницю між каналами стереозапису - Player for GIG files - Програвач GIG файлів + + Plugin for freely manipulating stereo output + Модуль для довільного управління стереовиходом - A multitap echo delay plugin - Плагін багаторазової послідовної затримки відлуння + + Tuneful things to bang on + Мелодійні ударні - A native flanger plugin - Рідний фланжер плагін + + Three powerful oscillators you can modulate in several ways + Три потужних генераторів можна модулювати декількома способами - An oversampling bitcrusher - Перевибірка малого дробдення + + VST-host for using VST(i)-plugins within LMMS + VST - хост для підтримки модулів VST(i) в LMMS - A native eq plugin - Рідний eq плагін + + Vibrating string modeler + Емуляція вібруючих струн - A 4-band Crossover Equalizer - 4-смуговий еквалайзер Кросовер + + plugin for using arbitrary VST effects inside LMMS. + плагін для використання довільних VST ефектів всередині LMMS. - A Dual filter plugin - Плагін подвійного фільтру + + 4-oscillator modulatable wavetable synth + 4-генераторний модулюючий синтезатор звукозаписів - Filter for exporting MIDI-files from LMMS - Фільтри для експорту MIDI-файлів з LMMS + + plugin for waveshaping + плагін формування сигналу - Reverb algorithm by Sean Costello - + + Embedded ZynAddSubFX + Вбудований ZynAddSubFX Mathematical expression parser - + sf2Instrument + Bank Банк + Patch Патч + Gain Посилення + Reverb Луна - Chorus - Хор (Приспів) + + Reverb Roomsize + Об'єм луни - A soundfont %1 could not be loaded. - soundfont %1 не вдається завантажити. + + Reverb Damping + Загасання луни - Reverb room size - + + Reverb Width + Довгота луни - Reverb damping - + + Reverb Level + Рівень луни - Reverb width - + + Chorus + Хор (Приспів) - Reverb level - + + Chorus Lines + Лінії хору - Chorus voices - + + Chorus Level + Рівень хору - Chorus level - + + Chorus Speed + Швидкість хору - Chorus speed - + + Chorus Depth + Глибина хору - Chorus depth - + + A soundfont %1 could not be loaded. + soundfont %1 не вдається завантажити. sf2InstrumentView + + Open other SoundFont file + Відкрити інший файл SoundFront + + + + Click here to open another SF2 file + Натисніть тут щоб відкрити інший файл SF2 + + + + Choose the patch + Вибрати патч + + + + Gain + Підсилення + + + Apply reverb (if supported) Створити відлуння (якщо підтримується) - Apply chorus (if supported) - Створити ефект хору (якщо підтримується) + + This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. + Ця кнопка включає ефект луни. Це корисно для класних ефектів, але працює не для всіх файлів. - Open SoundFont file - Відкрити файл SoundFront + + Reverb Roomsize: + Розмір приміщення: - Choose patch - + + Reverb Damping: + Загасання луни: - Gain: - Підсилення: + + Reverb Width: + Довгота луни: - Room size: - + + Reverb Level: + Рівень відлуння: - Damping: - + + Apply chorus (if supported) + Створити ефект хору (якщо підтримується) - Width: - Ширина: + + This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. + Ця кнопка включає ефект хору. Це корисно для класних ефектів, але працює не для всіх файлів. - Level: - + + Chorus Lines: + Лінії хору: - Voices: - + + Chorus Level: + Рівень хору: - Speed: - Швидкість: + + Chorus Speed: + Швидкість хору: - Depth: - Глибина: + + Chorus Depth: + Глибина хору: + + + + Open SoundFont file + Відкрити файл SoundFront - SoundFont Files (*.sf2 *.sf3) - + + SoundFont2 Files (*.sf2) + Файли SoundFont2 (*.sf2) sfxrInstrument - Wave - + + Wave Form + Форма хвилі sidInstrument + + Cutoff + Зріз + + + Resonance Підсилення + Filter type Тип фільтру + Voice 3 off Голос 3 відкл + Volume Гучність + Chip model Модель чіпа - - Cutoff frequency - Зріз частоти - sidInstrumentView + Volume: Гучність: + Resonance: Підсилення: + + Cutoff frequency: Частота зрізу: + + High-Pass filter + Вис.ЧФ + + + + Band-Pass filter + Серед.ЧФ + + + + Low-Pass filter + Низ.ЧФ + + + + Voice3 Off + Голос 3 відкл + + + MOS6581 SID MOS6581 SID + MOS8580 SID MOS8580 SID + + Attack: Вступ: + + Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. + Тривалість вступу визначає, наскільки швидко гучність %1-го голосу зростає від нуля до максимального значення. + + + + Decay: Згасання: + + Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. + Тривалість спаду визначає, наскільки швидко гучність падає від максимуму до залишкового рівня. + + + Sustain: Витримка: + + Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. + Гучність %1-го голосу залишатиметься на рівні амплітуди витримки, поки триває нота. + + + + Release: Зменшення: + + The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. + Гучність %1-го голосу буде падати від залишкового рівня до нуля з вказаною тут швидкістю. + + + + Pulse Width: Довжина імпульсу: + + The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. + Тривалість імпульсу дозволяє м'яко регулювати проходження імпульсу без помітних збоїв. Імпульсна хвиля повинна бути обрана на осцилляторі %1, щоб отримати звучання. + + + Coarse: Грубість: - Noise - Шум + + The Coarse detuning allows to detune Voice %1 one octave up or down. + Грубі налаштування дозволяють підлаштувати Голос %1 на одну октаву вгору або вниз. - Sync - Синхро + + Pulse Wave + Пульсуюча хвиля - Filtered - Відфільтрований + + Triangle Wave + Трикутник - Test - Тест + + SawTooth + Зигзаг - High-pass filter - + + Noise + Шум - Band-pass filter - + + Sync + Синхро - Low-pass filter - + + Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. + Синхро синхронізує фундаментальну частоту осцилляторів %1 фундаментальною частотою осциллятора %2, створюючи ефект "Залізної синхронізації". - Voice 3 off - + + Ring-Mod + Круговий режим - Pulse wave - + + Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. + Круговий режим замінює трикутні хвилі на виході осциллятора %1 "Круговою модуляцією" комбінацією осцилляторів %1 і %2. - Triangle wave - + + Filtered + Відфільтрований - Saw wave - Зигзаг + + When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. + Якщо цей прапорець встановлено, то %1-й голос буде проходити через фільтр. Інакше голос № %1 буде подаватися прямо на вихід. - Ring modulation - + + Test + Тест - Pulse width: - + + Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. + Якщо «прапорець» встановлено, то %1-й осциллятор видає нульовий сигнал (поки прапорець не зніметься). stereoEnhancerControlDialog - Width: - Ширина: + + WIDE + ШИРШЕ - WIDTH - + + Width: + Ширина: stereoEnhancerControls + Width Ширина @@ -4760,18 +12515,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControlDialog + Left to Left Vol: Від лівого на лівий: + Left to Right Vol: Від лівого на правий: + Right to Left Vol: Від правого на лівий: + Right to Right Vol: Від правого на правий: @@ -4779,18 +12538,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControls + Left to Left Від лівого на лівий + Left to Right Від лівого на правий + Right to Left Від правого на лівий + Right to Right Від правого на правий @@ -4798,191 +12561,380 @@ This chip was used in the Commodore 64 computer. vestigeInstrument + Loading plugin Завантаження модуля - Please wait while loading the VST plugin... - + + Please wait while loading VST-plugin... + Будь ласка зачекайте поки завантажеться модуль VST... vibed + String %1 volume Гучність %1-й струни + String %1 stiffness Жорсткість %1-й струни + Pick %1 position Лад %1 + Pickup %1 position Положення %1-го звукознімача - Impulse %1 - Імпульс %1 + + Pan %1 + Бал %1 - String %1 panning - + + Detune %1 + Підстроювання %1 - String %1 detune - + + Fuzziness %1 + Нечіткість %1 - String %1 fuzziness - + + Length %1 + Довжина %1 - String %1 length - + + Impulse %1 + Імпульс %1 - String %1 - + + Octave %1 + Октава %1 vibedView + + Volume: + Гучність: + + + + The 'V' knob sets the volume of the selected string. + Регулятор 'V' встановлює гучність поточної струни. + + + String stiffness: Жорсткість: + + The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. + Регулятор 'S' встановлює жорсткість поточної струни. Цей параметр відповідає за тривалість звучання струни (чим більше значення жорсткості, тим довше дзвенить струна). + + + Pick position: Ударна позиція: + + The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. + Регулятор 'P' встановлює місце струни, де вона буде "притиснута". Чим нижче значення, тим ближче це місце буде до кобилки. + + + Pickup position: Положення звукознімача: + + The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. + Регулятор 'PU' встановлює місце струни, звідки буде зніматися звук. Чим нижче значення, тим ближче це місце буде до мосту. + + + + Pan: + Бал: + + + + The Pan knob determines the location of the selected string in the stereo field. + Ця ручка встановлює стереобаланс для поточної струни. + + + + Detune: + Підлаштувати: + + + + The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. + Ручка підстроювання змінює зсув частоти для поточної струни. Від'ємні значення змусять струну звучати плоско, позитивні - гостро. + + + + Fuzziness: + Нечіткість: + + + + The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. + Ця ручка додає розмитість звуку, що найбільш помітно під час наростання, втім, це може використовуватися, щоб зробити звук більш "металевим". + + + + Length: + Довжина: + + + + The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. + Ручка довжини встановлює довжину поточної струни. Чим довша струна, тим більш чистий і довгий звук вона дає; однак це вимагає більше ресурсів ЦП. + + + + Impulse or initial state + Початкова швидкість/початковий стан + + + + The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. + Перемикач "Imp" встановлює режим роботи струни: якщо він включений, то зазначена форма сигналу інтерпретується як початковий імпульс, інакше - як початкова форма струни. + + + Octave Октава + + The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. + Перемикач октав дозволяє вказати гармоніку основної частоти, на якій буде звучати струна. Наприклад, "-2" означає, що струна буде звучати двома октавами нижче основної частоти, "F" змусить струну дзвеніти на основній частоті інструменту, а "6" - на частоті, на шість октав більш високій, ніж основна. + + + Impulse Editor Редактор сигналу + + The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. + +The waveform can also be drawn in the graph. + +The 'S' button will smooth the waveform. + +The 'N' button will normalize the waveform. + Редактор форми дозволяє явно вказати профіль струни в початковий момент часу, або її початковий імпульс (в залежності від стану перемикача "Imp"). +Кнопки праворуч від малюнка дозволяють задавати деякі стандартні форми, причому кнопка '?' служить для задання форми з довільного звукового файлу (завантажуються перші 128 елементів вибірки). + +Також форма сигналу може бути просто намальована за допомогою миші. + +Кнопка 'S' згладить поточну форму. + +Кнопка 'N' нормалізує рівень. + + + + Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. + +The graph allows you to control the initial state or impulse used to set the string in motion. + +The 'V' knob controls the volume. The 'S' knob controls the string's stiffness. The 'P' knob controls the pick position. The 'PU' knob controls the pickup position. + +'Pan' and 'Detune' hopefully don't need explanation. The 'Slap' knob adds a bit of fuzz to the sound of the string. + +The 'Length' knob controls the length of the string. + +The LED in the lower right corner of the waveform editor determines whether the string is active in the current instrument. + Інструмент "Vibed" моделює до дев'яти незалежних одночасно звучних струн. + +Перемикач "Strings" дозволяє вибрати струну, чиї властивості редагуються. + +Перемикач "Imp" встановлює режим роботи струни: якщо він включений, то зазначена форма сигналу інтерпретується як початковий імпульс, інакше - як початкова форма струни. + +Перемикач "Octave" дозволяє вказати гармоніку основної частоти, на якій буде звучати струна. + +Редактор форми дозволяє явно вказати профіль струни в початковий момент часу, або її початковий імпульс. + +Ручка 'V' встановлює гучність поточної струни, 'S' - жорсткість, 'P' - місце, де притиснута струна, а 'PU' '- положення звукознімача. + +Ручка підстроювання і стереобалансу, сподіваємося не потребує пояснень. + +Ручка "Довжина" регулює довжину струни + +Індикатор-перемикач зліва внизу визначає, чи включена поточна струна. + + + Enable waveform Включити сигнал + + Click here to enable/disable waveform. + Натисніть, щоб увімкнути/вимкнути сигнал. + + + String Струна + + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + Перемикач струн дозволяє вибрати струну, чиї властивості редагуються. Інструмент Vibed містить до дев'яти незалежно звучних струн, індикатор в лівому нижньому куті показує, активна чи поточна струна (тобто чи буде вона чутна). + + + Sine wave Синусоїда + + Use a sine-wave for current oscillator. + Генерувати гармонійний (синусоїдальний) сигнал. + + + Triangle wave Трикутник - Saw wave - Зигзаг + + Use a triangle-wave for current oscillator. + Генерувати трикутний сигнал. - Square wave - Квадратна хвиля + + Saw wave + Зигзаг - String volume: - + + Use a saw-wave for current oscillator. + Генерувати зигзагоподібний сигнал. - String panning: - + + Square wave + Квадратна хвиля - String detune: - + + Use a square-wave for current oscillator. + Генерувати квадрат. - String fuzziness: - + + White noise wave + Білий шум - String length: - + + Use white-noise for current oscillator. + Генерувати білий шум. - Impulse - + + User defined wave + Користувацька - Enable/disable string - + + Use a user-defined waveform for current oscillator. + Задати форму сигналу. - White noise - Білий шум + + Smooth + Згладити - User-defined wave - + + Click here to smooth waveform. + Клацніть щоб згладити форму сигналу. - Smooth waveform - Згладжений сигнал + + Normalize + Нормалізувати - Normalize waveform - + + Click here to normalize waveform. + Натисніть, щоб нормалізувати сигнал. voiceObject + Voice %1 pulse width Голос %1 довжина сигналу + Voice %1 attack Вступ %1-го голосу + Voice %1 decay Згасання %1-го голосу + Voice %1 sustain Витримка для %1-го голосу + Voice %1 release Зменшення %1-го голосу + Voice %1 coarse detuning Підналаштування %1-голосу (грубо) + Voice %1 wave shape Форма сигналу для %1-го голосу + Voice %1 sync Синхронізація %1-го голосу + Voice %1 ring modulate Голос %1 кільцевий модулятор + Voice %1 filtered Фільтрований %1-й голос + Voice %1 test Голос %1 тест @@ -4990,53 +12942,85 @@ This chip was used in the Commodore 64 computer. waveShaperControlDialog + INPUT ВХІД + Input gain: Вхідне підсилення: + OUTPUT ВИХІД + Output gain: Вихідне підсилення: - Clip input - Зрізати вхідний сигнал + + Reset waveform + Скидання сигналу + + + + Click here to reset the wavegraph back to default + Натисніть тут, щоб скинути граф хвилі назад за замовчуванням + + + + Smooth waveform + Згладжений сигнал + + + + Click here to apply smoothing to wavegraph + Натисніть тут, щоб застосувати згладжування графа хвилі - Reset wavegraph - + + Increase graph amplitude by 1dB + Збільште амплітуди графа хвилі на 1дБ - Smooth wavegraph - + + Click here to increase wavegraph amplitude by 1dB + Натисніть тут, щоб збільшити амплітуду графа хвилі на 1дБ - Increase wavegraph amplitude by 1 dB - + + Decrease graph amplitude by 1dB + Зменшення амплітуди графа хвилі на 1дБ - Decrease wavegraph amplitude by 1 dB - + + Click here to decrease wavegraph amplitude by 1dB + Натисніть тут, щоб зменшити амплітуду графа хвилі на 1дБ + + + + Clip input + Зрізати вхідний сигнал - Clip input signal to 0 dB - + + Clip input signal to 0dB + Зрізати вхідний сигнал до 0дБ waveShaperControls + Input gain Вхідне підсилення + Output gain Вихідне підсилення diff --git a/data/locale/zh_TW.ts b/data/locale/zh_TW.ts index 15c0059bcae..261d7c6665a 100644 --- a/data/locale/zh_TW.ts +++ b/data/locale/zh_TW.ts @@ -1,37 +1,123 @@ - - - + + + AboutDialog + + + About LMMS + 關於 LMMS + + + + LMMS + LMMS + + + + Version %1 (%2/%3, Qt %4, %5) + 版本 %1 (%2/%3, Qt %4, %5) + + + + About + 關於 + + + + LMMS - easy music production for everyone + LMMS - 人人都是作曲家 + + + + Copyright © %1 + 版權所有 © %1 + + + + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="https://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">https://lmms.io</span></a></p></body></html> + + + + Authors + 作者 + + + + Involved + 參與者 + + + + Contributors ordered by number of commits: + 貢獻者名單(以提交次數排序): + + + + Translation + 翻譯 + + + + Current language not translated (or native English). + +If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! + 當前語言是中文(台灣) + +翻譯人員: +TonyChyi <tonychee1989 at gmail.com> +Min Zhang <zm1990s at gmail.com> +Jeff Bai <jeffbaichina at gmail.com> +Mingye Wang <arthur2e5@aosc.xyz> +Zixing Liu <liushuyu@aosc.xyz> +BrLi <brli at chakraos.org> + +若你有興趣提高翻譯品質,請聯絡維護團隊 (https://github.com/AOSC-Dev/translations)、之前的譯者或本項目維護者! + + + + License + 授權協議 + + AmplifierControlDialog + VOL VOL + Volume: 音量: + PAN PAN + Panning: 聲相: + LEFT + Left gain: 左增益: + RIGHT + Right gain: 右增益: @@ -39,4270 +125,11717 @@ AmplifierControls + Volume 音量 + Panning 聲相 + Left gain 左增益 + Right gain 右增益 + + AudioAlsaSetupWidget + + + DEVICE + 裝置 + + + + CHANNELS + 聲道數 + + AudioFileProcessorView - Reverse sample - 反轉取樣 + + Open other sample + 開啟其他取樣 - Amplify: - 放大: + + Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. + 如果想打開另一個音訊檔,請點擊這裡。接著會出現檔案選擇視窗。諸如循環模式 (looping-mode),起始/結束點,放大率 (amplify-value) 之類的值不會被重置。因此聽起來會和取樣來源有差異。 - Continue sample playback across notes - 跨音符繼續播放採樣 + + Reverse sample + 反轉取樣 + + + + If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. + 如果點擊此按鈕,整個取樣將會被反轉。能用於製作很酷的效果,例如 reversed crash. + Disable loop 停用循環 + + This button disables looping. The sample plays only once from start to end. + 點擊此按鈕可以禁止循環播放。取樣檔案將從頭到尾播放一次。 + + + + Enable loop 啟用循環 - Loopback point: - 循環點: + + This button enables forwards-looping. The sample loops between the end point and the loop point. + 點擊此按鈕後,Forwards-looping 會被打開,採樣將在終止點(End Point)和循環點(Loop Point)之間播放。 - Open sample - + + This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. + 點擊此按鈕後,Ping-pong-looping 會被打開,採樣將在終止點 (End Point) 和循環點 (Loop Point) 之間來回播放。 - Enable ping-pong loop - + + Continue sample playback across notes + 跨音符繼續播放採樣 - Start point: - + + Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) + - End point: - + + Amplify: + 放大: - - - AudioFileProcessorWaveView - Sample length: - 採樣長度: + + With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + 此旋鈕用於調整放大比率。當設爲100% 時採樣不會變化。除此之外,不是放大就是減弱(原始的採樣文件不會被改變) - - - BassBoosterControlDialog - FREQ - 頻率 + + Startpoint: + 起始點: - Frequency: - 頻率: + + With this knob you can set the point where AudioFileProcessor should begin playing your sample. + 調節此旋鈕,以告訴 AudioFileProcessor 在哪裏開始播放。 - GAIN - 增益 + + Endpoint: + 終點: - Gain: - 增益: + + With this knob you can set the point where AudioFileProcessor should stop playing your sample. + 調節此旋鈕,以告訴 AudioFileProcessor 在哪裏停止播放。 - RATIO - 比率 + + Loopback point: + 循環點: - Ratio: - 比率: + + With this knob you can set the point where the loop starts. + 調節此旋鈕,以設置循環開始的地方。 - BassBoosterControls - - Frequency - 頻率 - - - Gain - 增益 - + AudioFileProcessorWaveView - Ratio - 比率 + + Sample length: + 採樣長度: - BitcrushControlDialog + AudioJack - IN - 輸入 + + JACK client restarted + JACK 客戶端已重啓 - OUT - 輸出 + + LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. + LMMS 由於某些原因與 JACK 中斷連線,因此 LMMS 的 JACK 後端已重新啟動,您必須手動重新連線。 - GAIN - 增益 + + JACK server down + JACK 伺服器發生問題 - CLIP - 壓限 + + The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. + JACK 伺服器似乎發生問題,而且無法重新啟動,因此 LMMS 無法繼續執行。請儲存專案,然後重新啟動 JACK 和 LMMS。 - Sample rate: - 採樣率: + + CLIENT-NAME + 客戶端名稱 - Stereo difference: - 雙聲道差異: + + CHANNELS + 聲道數 + + + AudioOss::setupWidget - Levels: - 級別: + + DEVICE + 裝置 - NOISE - + + CHANNELS + 聲道數 + + + AudioPortAudio::setupWidget - FREQ - 頻率 + + BACKEND + 後端 - STEREO - + + DEVICE + 裝置 + + + AudioPulseAudio::setupWidget - QUANT - + + DEVICE + 裝置 - Input gain: - 輸入增益: + + CHANNELS + 聲道數 + + + AudioSdl::setupWidget - Input noise: - + + DEVICE + 裝置 + + + AudioSndio::setupWidget - Output gain: - 輸出增益: + + DEVICE + 裝置 - Output clip: - + + CHANNELS + 聲道數 + + + AudioSoundIo::setupWidget - Rate enabled - + + BACKEND + 後端 - Enable sample-rate crushing - + + DEVICE + 裝置 + + + AutomatableModel - Depth enabled - + + &Reset (%1%2) + 重設(%1%2)(&R) - Enable bit-depth crushing - + + &Copy value (%1%2) + 複製值(%1%2)(&C) - - - BitcrushControls - Input gain - 輸入增益 + + &Paste value (%1%2) + 貼上值(%1%2)(&P) - Input noise - + + Edit song-global automation + 編輯歌曲全局的自動控制裝置 - Output gain - 輸出增益 + + Remove song-global automation + 移除歌曲全域自動控制裝置 - Output clip - + + Remove all linked controls + 移除所有已連線的控制器 - Sample rate - + + Connected to %1 + 已連線至 %1 - Stereo difference - + + Connected to controller + 連線至控制器 - Levels - + + Edit connection... + 編輯連線… - Rate enabled - + + Remove connection + 移除連線 - Depth enabled - + + Connect to controller... + 連線至控制器… - CarlaInstrumentView + AutomationEditor - Show GUI - 顯示圖形界面 + + Please open an automation pattern with the context menu of a control! + 請透過控制的右鍵選單開啟自動控制模式! + + + + Values copied + 值已複製 + + + + All selected values were copied to the clipboard. + 所有選中的值已複製。 - CrossoverEQControlDialog + AutomationEditorWindow - Band 1/2 crossover: - + + Play/pause current pattern (Space) + 播放/暫停當前片段(空格) - Band 2/3 crossover: - + + Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. + 點擊這裏播放片段。編輯時很有用,片段會自動循環播放。 - Band 3/4 crossover: - + + Stop playing of current pattern (Space) + 停止當前片段(空格) - Band 1 gain - + + Click here if you want to stop playing of the current pattern. + 點擊這裏停止播放片段。 - Band 1 gain: - + + Edit actions + 編輯功能 - Band 2 gain - + + Draw mode (Shift+D) + 繪製模式 (Shift+D) - Band 2 gain: - + + Erase mode (Shift+E) + 擦除模式 (Shift+E) - Band 3 gain - + + Flip vertically + 垂直翻轉 - Band 3 gain: - + + Flip horizontally + 水平翻轉 - Band 4 gain - + + Click here and the pattern will be inverted.The points are flipped in the y direction. + 點擊這裡來翻轉圖形 (pattern)。圖上的點會隨y軸翻轉。 - Band 4 gain: - + + Click here and the pattern will be reversed. The points are flipped in the x direction. + 點擊這裡來翻轉圖形 (pattern)。圖上的點會隨x軸翻轉。 - Band 1 mute - + + Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. + 點擊這裏啓用繪製模式。在此模式下你可以增加或移動單個值。 大部分時間下默認使用此模式。你也可以按鍵盤上的 ‘Shift+D’激活此模式。 - Mute band 1 - + + Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. + 點擊啓用擦除模式。此模式下你可以擦除單個值。你可以按鍵盤上的 'Shift+E' 啓用此模式。 - Band 2 mute - + + Interpolation controls + 補間控制 - Mute band 2 - + + Discrete progression + 區間進程 (Discrete progression) - Band 3 mute - + + Linear progression + 線性進程 (Linear progression) - Mute band 3 - + + Cubic Hermite progression + - Band 4 mute - + + Tension value for spline + - Mute band 4 - + + A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. + - - - DelayControls - Feedback - + + Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. + - Output gain - 輸出增益 + + Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. + - Delay samples - + + Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. + - LFO frequency - + + Tension: + - LFO amount - + + Cut selected values (%1+X) + 剪下選擇的值 (%1+X) - - - DelayControlsDialog - Gain - 增益 + + Copy selected values (%1+C) + 複製選擇的值 (%1+C) - DELAY - + + Paste values from clipboard (%1+V) + 從剪貼簿貼上值 (%1+V) - FDBK - + + Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + 點擊這裏,選擇的值將會被剪切到剪切板。你可以使用粘貼按鈕將它們粘貼到任意地方,存爲任意片段。 - RATE - + + Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + 點擊這裏,選擇的值將會被複制到剪切板。你可以使用粘貼按鈕將它們粘貼到任意地方,存爲任意片段。 - AMNT - + + Click here and the values from the clipboard will be pasted at the first visible measure. + 點擊這裏,選擇的值將從剪貼板粘貼到第一個可見的小節。 + + + + Zoom controls + 縮放控制 + + + + Quantization controls + 量化控制 - Delay time - + + Quantization + 量化 - Feedback amount - + + Quantization. Sets the smallest step size for the Automation Point. By default this also sets the length, clearing out other points in the range. Press <Ctrl> to override this behaviour. + - LFO frequency - + + + Automation Editor - no pattern + 自動控制編輯器 - 沒有片段 - LFO amount - + + + Automation Editor - %1 + 自動控制編輯器 - %1 - Out gain - + + Model is already connected to this pattern. + 模型已連接到此片段。 - DualFilterControlDialog + AutomationPattern - Filter 1 enabled - 已啓用過濾器 1 + + Drag a control while pressing <%1> + 按住<%1>拖動控制器 + + + AutomationPatternView - Filter 2 enabled - 已啓用過濾器 2 + + double-click to open this pattern in automation editor + 雙擊在自動編輯器中打開此片段 - FREQ - 頻率 + + Open in Automation editor + 在自動編輯器(Automation editor)中打開 - Cutoff frequency - 切除頻率 + + Clear + 清除 - RESO - + + Reset name + 重置名稱 - Resonance - 共鳴 + + Change name + 修改名稱 - GAIN - 增益 + + Set/clear record + 設置/清除錄製 - Gain - 增益 + + Flip Vertically (Visible) + 垂直翻轉 (可見) - MIX - + + Flip Horizontally (Visible) + 水平翻轉 (可見) - Mix - 混合 + + %1 Connections + %1個連接 - Enable/disable filter 1 - + + Disconnect "%1" + 斷開“%1”的連接 - Enable/disable filter 2 - + + Model is already connected to this pattern. + 模型已連接到此片段。 - DualFilterControls + AutomationTrack - Filter 1 enabled - 過濾器1 已啓用 + + Automation track + 自動控制軌道 + + + BBEditor - Filter 1 type - 過濾器 1 類型 + + Beat+Bassline Editor + 節拍+低音線編輯器 - Q/Resonance 1 - 濾波器 1 Q值 + + Play/pause current beat/bassline (Space) + 播放/暫停當前節拍/低音線(空格) - Gain 1 - 增益 1 + + Stop playback of current beat/bassline (Space) + 停止播放當前節拍/低音線(空格) - Mix - 混合 + + Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. + 點擊這裏停止播放當前節拍/低音線。當結束時節拍/低音線會自動循環播放。 - Filter 2 enabled - 已啓用過濾器 2 + + Click here to stop playing of current beat/bassline. + 點擊這裏停止播發當前節拍/低音線。 - Filter 2 type - 過濾器 1 類型 {2 ?} + + Beat selector + 節拍選擇器 - Q/Resonance 2 - 濾波器 2 Q值 + + Track and step actions + - Gain 2 - 增益 2 + + Add beat/bassline + 添加節拍/低音線 - Notch - 凹口濾波器 + + Add sample-track + 新增採樣音軌 - Moog - Moog + + Add automation-track + 添加自動控制軌道 - 2x Moog - + + Remove steps + 移除音階 - SV Notch - + + Add steps + 添加音階 - Fast Formant - + + Clone Steps + + + + BBTCOView - Tripole - + + Open in Beat+Bassline-Editor + 在節拍+Bassline編輯器中打開 - Cutoff frequency 1 - + + Reset name + 重置名稱 - Cutoff frequency 2 - + + Change name + 修改名稱 - Low-pass - + + Change color + 改變顏色 - Hi-pass - + + Reset color to default + 重置顏色 + + + BBTrack - Band-pass csg - + + Beat/Bassline %1 + 節拍/Bassline %1 - Band-pass czpg - + + Clone of %1 + %1 的副本 + + + BassBoosterControlDialog - All-pass - + + FREQ + 頻率 - 2x Low-pass - + + Frequency: + 頻率: - RC Low-pass 12 dB/oct - + + GAIN + 增益 - RC Band-pass 12 dB/oct - + + Gain: + 增益: - RC High-pass 12 dB/oct - + + RATIO + 比率 - RC Low-pass 24 dB/oct - + + Ratio: + 比率: + + + BassBoosterControls - RC Band-pass 24 dB/oct - + + Frequency + 頻率 - RC High-pass 24 dB/oct - + + Gain + 增益 - Vocal Formant - + + Ratio + 比率 + + + BitcrushControlDialog - SV Low-pass - + + IN + 輸入 - SV Band-pass - + + OUT + 輸出 - SV High-pass - + + + GAIN + 增益 - - - EqControls - Input gain - 輸入增益 + + Input Gain: + 輸入增益: - Output gain - 輸出增益 + + NOISE + - Peak 1 gain - + + Input Noise: + 輸入噪音: - Peak 2 gain - + + Output Gain: + 輸出增益: - Peak 3 gain - - - - Peak 4 gain - + + CLIP + 壓限 - HP res - + + Output Clip: + 輸出壓限: - Peak 1 BW - + + Rate Enabled + - Peak 2 BW - + + Enable samplerate-crushing + - Peak 3 BW - + + Depth Enabled + 深度已啓用 - Peak 4 BW - + + Enable bitdepth-crushing + - LP res - + + FREQ + 頻率 - HP freq - + + Sample rate: + 採樣率: - Peak 1 freq - + + STEREO + - Peak 2 freq - + + Stereo difference: + 雙聲道差異: - Peak 3 freq - + + QUANT + - Peak 4 freq - + + Levels: + 級別: + + + CaptionMenu - LP freq - + + &Help + 幫助(&H) - HP active - + + Help (not available) + 幫助(不可用) + + + CarlaInstrumentView - Peak 1 active - + + Show GUI + 顯示圖形界面 - Peak 2 active - + + Click here to show or hide the graphical user interface (GUI) of Carla. + 點擊此處可以顯示或隱藏 Carla 的圖形界面。 + + + Controller - Peak 3 active - + + Controller %1 + 控制器%1 + + + ControllerConnectionDialog - Peak 4 active - + + Connection Settings + 連接設置 - LP active - + + MIDI CONTROLLER + MIDI控制器 - LP 12 - + + Input channel + 輸入通道 - LP 24 - + + CHANNEL + 通道 - LP 48 - + + Input controller + 輸入控制器 - HP 12 - + + CONTROLLER + 控制器 - HP 24 - + + + Auto Detect + 自動檢測 - HP 48 - + + MIDI-devices to receive MIDI-events from + 用來接收 MIDI 事件的MIDI 設備 - Analyse IN - + + USER CONTROLLER + 用戶控制器 - Analyse OUT - + + MAPPING FUNCTION + 映射函數 - Low-shelf gain - + + OK + 確定 - High-shelf gain - + + Cancel + 取消 - Low-shelf res - + + LMMS + LMMS - High-shelf res - + + Cycle Detected. + 檢測到環路。 + + + ControllerRackView - Low-shelf freq - + + Controller Rack + 控制器機架 - High-shelf freq - + + Add + 增加 - Low-shelf active - + + Confirm Delete + 刪除前確認 - High-shelf active - + + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. + 確定要刪除嗎?此控制器仍處於被連接狀態。此操作不可撤銷。 + + + ControllerView - Low-pass type - + + Controls + 控制器 - High-pass type - + + Controllers are able to automate the value of a knob, slider, and other controls. + 控制器可以自動控制旋鈕,滑塊和其他控件的值。 - - - EqControlsDialog - HP - + + Rename controller + 重命名控制器 - Peak 1 - + + Enter the new name for this controller + 輸入這個控制器的新名稱 - Peak 2 - + + LFO + - Peak 3 - + + &Remove this controller + - Peak 4 - + + Re&name this controller + + + + CrossoverEQControlDialog - LP - + + Band 1/2 Crossover: + - Gain - 增益 + + Band 2/3 Crossover: + - Bandwidth: - + + Band 3/4 Crossover: + - Resonance : - + + Band 1 Gain: + - Frequency: - 頻率: + + Band 2 Gain: + - Octave - + + Band 3 Gain: + - Low-shelf - + + Band 4 Gain: + - High-shelf - + + Band 1 Mute + - Input gain - 輸入增益 + + Mute Band 1 + - Output gain - 輸出增益 + + Band 2 Mute + - LP group - + + Mute Band 2 + - HP group - + + Band 3 Mute + - - - EqHandle - Reso: - + + Mute Band 3 + - BW: - + + Band 4 Mute + - Freq: - + + Mute Band 4 + - FlangerControls - - Seconds - - + DelayControls - Regen - + + Delay Samples + - Noise - 噪音 + + Feedback + - Invert - 反轉 + + Lfo Frequency + - Delay samples - + + Lfo Amount + - LFO frequency - + + Output gain + 輸出增益 - FlangerControlsDialog + DelayControlsDialog + DELAY - - - - RATE - + - AMNT - + + Delay Time + 延遲時間 - Amount: - + + FDBK + - FDBK - + + Feedback Amount + - NOISE - + + RATE + - Invert - 反轉 + + Lfo + - Period: - + + AMNT + - Delay time: - + + Lfo Amt + - Feedback amount: - + + Out Gain + - White noise amount: - + + Gain + 增益 - FreeBoyInstrument + DualFilterControlDialog - Sweep time - + + + FREQ + 頻率 - Sweep direction - + + + Cutoff frequency + 切除頻率 - Channel 1 volume - + + + RESO + - Volume sweep direction - + + + Resonance + 共鳴 - Length of each step in sweep - + + + GAIN + 增益 - Channel 2 volume - + + + Gain + 增益 - Channel 3 volume - + + MIX + - Channel 4 volume - + + Mix + 混合 - Channel 1 to SO2 (Left) - + + Filter 1 enabled + 已啓用過濾器 1 - Channel 2 to SO2 (Left) - + + Filter 2 enabled + 已啓用過濾器 2 - Channel 3 to SO2 (Left) - + + Click to enable/disable Filter 1 + 點擊啓用/禁用過濾器 1 - Channel 4 to SO2 (Left) - + + Click to enable/disable Filter 2 + 點擊啓用/禁用過濾器 2 + + + DualFilterControls - Channel 1 to SO1 (Right) - + + Filter 1 enabled + 過濾器1 已啓用 - Channel 2 to SO1 (Right) - + + Filter 1 type + 過濾器 1 類型 - Channel 3 to SO1 (Right) - + + Cutoff 1 frequency + 濾波器 1 截頻 - Channel 4 to SO1 (Right) - + + Q/Resonance 1 + 濾波器 1 Q值 - Treble - + + Gain 1 + 增益 1 - Bass - 低音 + + Mix + 混合 - Shift Register width - + + Filter 2 enabled + 已啓用過濾器 2 - Sweep rate shift amount - + + Filter 2 type + 過濾器 1 類型 {2 ?} - Wave pattern duty cycle - + + Cutoff 2 frequency + 濾波器 2 截頻 - Right output level - + + Q/Resonance 2 + 濾波器 2 Q值 - Left output level - + + Gain 2 + 增益 2 - - - FreeBoyInstrumentView - Length of each step in sweep: - + + + LowPass + 低通 - Length of each step in sweep - + + + HiPass + 高通 - Treble: - + + + BandPass csg + 帶通 csg - Treble - + + + BandPass czpg + 帶通 czpg - Bass: - + + + Notch + 凹口濾波器 - Bass - 低音 + + + Allpass + 全通 - Sweep time: - + + + Moog + Moog - Sweep time - + + + 2x LowPass + 2 個低通串聯 - Sweep rate shift amount: - + + + RC LowPass 12dB + RC 低通(12dB) - Sweep rate shift amount - + + + RC BandPass 12dB + RC 帶通(12dB) - Wave pattern duty cycle: - + + + RC HighPass 12dB + RC 高通(12dB) - Wave pattern duty cycle - + + + RC LowPass 24dB + RC 低通(24dB) - Square channel 1 volume: - + + + RC BandPass 24dB + RC 帶通(24dB) - Square channel 1 volume - + + + RC HighPass 24dB + RC 高通(24dB) - Square channel 2 volume: - + + + Vocal Formant Filter + 人聲移除過濾器 - Square channel 2 volume - + + + 2x Moog + - Wave pattern channel volume: - + + + SV LowPass + - Wave pattern channel volume - + + + SV BandPass + - Noise channel volume: - + + + SV HighPass + - Noise channel volume - + + + SV Notch + - SO1 volume (Right): - + + + Fast Formant + - SO1 volume (Right) - + + + Tripole + + + + Editor - SO2 volume (Left): - + + Transport controls + - SO2 volume (Left) - + + Play (Space) + 播放(空格) - Sweep direction - + + Stop (Space) + 停止(空格) - Volume sweep direction - + + Record + 錄音 - Shift register width - + + Record while playing + 播放時錄音 + + + Effect - Channel 1 to SO1 (Right) - + + Effect enabled + 啓用效果器 - Channel 2 to SO1 (Right) - + + Wet/Dry mix + 幹/溼混合 - Channel 3 to SO1 (Right) - + + Gate + 門限 - Channel 4 to SO1 (Right) - + + Decay + 衰減 + + + EffectChain - Channel 1 to SO2 (Left) - + + Effects enabled + 啓用效果器 + + + EffectRackView - Channel 2 to SO2 (Left) - + + EFFECTS CHAIN + 效果器鏈 - Channel 3 to SO2 (Left) - + + Add effect + 增加效果器 + + + EffectSelectDialog - Channel 4 to SO2 (Left) - + + Add effect + 增加效果器 - Wave pattern graph - + + + Name + 名稱 - - - GigInstrument - Bank - + + Type + 類型 - Patch - 音色 + + Description + 描述 - Gain - 增益 + + Author + - GigInstrumentView + EffectView - Open GIG file - 打開 GIG 文件 + + Toggles the effect on or off. + 打開或關閉效果. - GIG Files (*.gig) - GIG 文件 (*.gig) + + On/Off + 開/關 - Choose patch - + + W/D + W/D - Gain: - 增益: + + Wet Level: + 效果度: - - - InstrumentTrack - Default preset - 預置 + + The Wet/Dry knob sets the ratio between the input signal and the effect signal that forms the output. + 旋轉幹溼度旋鈕以調整原信號與有效果的信號的比例。 - - - LadspaControlDialog - Link Channels - 連接通道 + + DECAY + 衰減 - Channel - 通道 + + Time: + 時間: - - - LadspaEffect - Unknown LADSPA plugin %1 requested. - 已請求未知 LADSPA 插件 %1. + + The Decay knob controls how many buffers of silence must pass before the plugin stops processing. Smaller values will reduce the CPU overhead but run the risk of clipping the tail on delay and reverb effects. + 衰減旋鈕控制在插件停止工作前,緩衝區中加入的靜音時常。較小的數值會降低CPU佔用率但是可能導致延遲或混響產生撕裂。 - - - MidiImport - Setup incomplete - 設置不完整 + + GATE + 門限 - You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. - 你在編譯 LMMS 時沒有加入 SoundFont2 播放器支持, 此播放器默認用於添加導入的 MIDI 文件。因此在 MIDI 文件導入後, 將沒有聲音。 + + Gate: + 門限: - Track - 軌道 + + The Gate knob controls the signal level that is considered to be 'silence' while deciding when to stop processing signals. + 門限旋鈕設置自動靜音時,被認爲是靜音的信號幅度。 - You have not set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. - + + Controls + 控制 - - - MonstroInstrument - Osc 3 Stereo phase offset - + + Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. + +The On/Off switch allows you to bypass a given plugin at any point in time. + +The Wet/Dry knob controls the balance between the input signal and the effected signal that is the resulting output from the effect. The input for the stage is the output from the previous stage. So, the 'dry' signal for effects lower in the chain contains all of the previous effects. + +The Decay knob controls how long the signal will continue to be processed after the notes have been released. The effect will stop processing signals when the volume has dropped below a given threshold for a given length of time. This knob sets the 'given length of time'. Longer times will require more CPU, so this number should be set low for most effects. It needs to be bumped up for effects that produce lengthy periods of silence, e.g. delays. + +The Gate knob controls the 'given threshold' for the effect's auto shutdown. The clock for the 'given length of time' will begin as soon as the processed signal level drops below the level specified with this knob. + +The Controls button opens a dialog for editing the effect's parameters. + +Right clicking will bring up a context menu where you can change the order in which the effects are processed or delete an effect altogether. + - Selected view - + + Move &up + 向上移(&U) - Sine wave - 正弦波 + + Move &down + 向下移(&D) - Bandlimited Triangle wave - + + &Remove this plugin + 移除此插件(&R) + + + EnvelopeAndLfoParameters - Bandlimited Saw wave - + + Predelay + 預延遲 - Bandlimited Ramp wave - + + Attack + 打進聲 - Bandlimited Square wave - + + Hold + 保持 - Bandlimited Moog saw wave - + + Decay + 衰減 - Soft square wave - + + Sustain + 持續 - Absolute sine wave - + + Release + 釋放 - Exponential wave - + + Modulation + 調製 - White noise - + + LFO Predelay + LFO 預延遲 - Digital Triangle wave - + + LFO Attack + LFO 打進聲(attack) - Digital Saw wave - + + LFO speed + LFO 速度 - Digital Ramp wave - + + LFO Modulation + LFO 調製 - Digital Square wave - + + LFO Wave Shape + LFO 波形形狀 - Digital Moog saw wave - + + Freq x 100 + 頻率 x 100 - Triangle wave - 三角波 + + Modulate Env-Amount + 調製所有包絡 + + + EnvelopeAndLfoView - Saw wave - 鋸齒波 + + + DEL + DEL - Ramp wave - + + Predelay: + 預延遲: - Square wave - 方波 + + Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. + 使用預延遲旋鈕設定此包絡的預延遲,較大的值會加長包絡開始的時間。 - Moog saw wave - + + + ATT + ATT - Abs. sine wave - + + Attack: + 打進聲: - Random - 隨機 + + Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. + 使用起音旋鈕設定此包絡的起音時間,較大的值會讓包絡達到起音值的時間增加。爲鋼琴等樂器選擇小值而絃樂選擇大值。 - Random smooth - + + HOLD + 持續 - Osc 1 volume - + + Hold: + 持續: - Osc 1 panning - + + Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. + 使用持續旋鈕設定此包絡的持續時間。較大的值會在它衰減到持續值時,保持包絡在起音值更久。 - Osc 1 coarse detune - + + DEC + 衰減 - Osc 1 fine detune left - + + Decay: + 衰減: - Osc 1 fine detune right - + + Use this knob for setting decay-time of the current envelope. The bigger this value the longer the envelope needs to decrease from attack-level to sustain-level. Choose a small value for instruments like pianos. + 使用衰減旋鈕設定此包絡的衰減值。較大的值會延長包絡從起音值衰減到持續值的時間。爲鋼琴等樂器選擇一個小值。 - Osc 1 stereo phase offset - + + SUST + 持續 - Osc 1 pulse width - + + Sustain: + 持續: - Osc 1 sync send on rise - + + Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. + 使用持續旋鈕設置此包絡的持續值,較大的值會增加釋放前,包絡在此保持的值。 - Osc 1 sync send on fall - + + REL + 釋音 - Osc 2 volume - + + Release: + 釋音: - Osc 2 panning - + + Use this knob for setting release-time of the current envelope. The bigger this value the longer the envelope needs to decrease from sustain-level to zero. Choose a big value for soft instruments like strings. + 使用釋音旋鈕設定此包絡的釋音時間,較大值會增加包絡衰減到零的時間。爲絃樂等樂器選擇一個大值。 - Osc 2 coarse detune - + + + AMT + - Osc 2 fine detune left - + + + Modulation amount: + 調製量: - Osc 2 fine detune right - + + Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. + 使用調製量旋鈕設置LFO對此包絡的調製量,較大的值會對此包絡控制的值(如音量或截頻)影響更大。 - Osc 2 stereo phase offset - + + LFO predelay: + LFO 預延遲: - Osc 2 waveform - + + Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. + - Osc 2 sync hard - + + LFO- attack: + - Osc 2 sync reverse - + + Use this knob for setting attack-time of the current LFO. The bigger this value the longer the LFO needs to increase its amplitude to maximum. + - Osc 3 volume - + + SPD + - Osc 3 panning - + + LFO speed: + - Osc 3 coarse detune - + + Use this knob for setting speed of the current LFO. The bigger this value the faster the LFO oscillates and the faster will be your effect. + - Osc 3 sub-oscillator mix - + + Use this knob for setting modulation amount of the current LFO. The bigger this value the more the selected size (e.g. volume or cutoff-frequency) will be influenced by this LFO. + - Osc 3 waveform 1 - + + Click here for a sine-wave. + 點擊這裡使用正弦波。 - Osc 3 waveform 2 - + + Click here for a triangle-wave. + 點擊這裡使用三角波。 - Osc 3 sync hard - + + Click here for a saw-wave for current. + 點擊這裡使用鋸齒波。 - Osc 3 Sync reverse - + + Click here for a square-wave. + 點擊這裡使用方形波。 - LFO 1 waveform - + + Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. + 點擊這裡使用自訂波形。之後請把所用波形的樣本檔案拖到LFO Graph上。 - LFO 1 attack - + + Click here for random wave. + 點擊這裡使用隨機波形。 - LFO 1 rate - + + FREQ x 100 + 頻率 x 100 - LFO 1 phase - + + Click here if the frequency of this LFO should be multiplied by 100. + 點擊這裡把這個LFO的頻率乘以100。 - LFO 2 waveform - + + multiply LFO-frequency by 100 + - LFO 2 attack - + + MODULATE ENV-AMOUNT + - LFO 2 rate - + + Click here to make the envelope-amount controlled by this LFO. + - LFO 2 phase - + + control envelope-amount by this LFO + - Env 1 pre-delay - + + ms/LFO: + - Env 1 attack - + + Hint + 提示 - Env 1 hold - + + Drag a sample from somewhere and drop it in this window. + 把樣本檔案拖到這個視窗上放開。 + + + EqControls - Env 1 decay - + + Input gain + 輸入增益 - Env 1 sustain - + + Output gain + 輸出增益 - Env 1 release - + + Low shelf gain + - Env 1 slope - + + Peak 1 gain + - Env 2 pre-delay - + + Peak 2 gain + - Env 2 attack - + + Peak 3 gain + - Env 2 hold - + + Peak 4 gain + - Env 2 decay - + + High Shelf gain + - Env 2 sustain - + + HP res + - Env 2 release - + + Low Shelf res + - Env 2 slope - + + Peak 1 BW + - Osc 2+3 modulation - + + Peak 2 BW + - Osc 1 - Vol env 1 - + + Peak 3 BW + - Osc 1 - Vol env 2 - + + Peak 4 BW + - Osc 1 - Vol LFO 1 - + + High Shelf res + - Osc 1 - Vol LFO 2 - + + LP res + - Osc 2 - Vol env 1 - + + HP freq + - Osc 2 - Vol env 2 - + + Low Shelf freq + - Osc 2 - Vol LFO 1 - + + Peak 1 freq + - Osc 2 - Vol LFO 2 - + + Peak 2 freq + - Osc 3 - Vol env 1 - + + Peak 3 freq + - Osc 3 - Vol env 2 - + + Peak 4 freq + - Osc 3 - Vol LFO 1 - + + High shelf freq + - Osc 3 - Vol LFO 2 - + + LP freq + - Osc 1 - Phs env 1 - + + HP active + - Osc 1 - Phs env 2 - + + Low shelf active + - Osc 1 - Phs LFO 1 - + + Peak 1 active + - Osc 1 - Phs LFO 2 - + + Peak 2 active + - Osc 2 - Phs env 1 - + + Peak 3 active + - Osc 2 - Phs env 2 - + + Peak 4 active + - Osc 2 - Phs LFO 1 - + + High shelf active + - Osc 2 - Phs LFO 2 - + + LP active + - Osc 3 - Phs env 1 - + + LP 12 + - Osc 3 - Phs env 2 - + + LP 24 + - Osc 3 - Phs LFO 1 - + + LP 48 + - Osc 3 - Phs LFO 2 - + + HP 12 + - Osc 1 - Pit env 1 - + + HP 24 + - Osc 1 - Pit env 2 - + + HP 48 + - Osc 1 - Pit LFO 1 - + + low pass type + - Osc 1 - Pit LFO 2 - + + high pass type + - Osc 2 - Pit env 1 - + + Analyse IN + - Osc 2 - Pit env 2 - + + Analyse OUT + + + + EqControlsDialog - Osc 2 - Pit LFO 1 - + + HP + - Osc 2 - Pit LFO 2 - + + Low Shelf + - Osc 3 - Pit env 1 - + + Peak 1 + - Osc 3 - Pit env 2 - + + Peak 2 + - Osc 3 - Pit LFO 1 - + + Peak 3 + - Osc 3 - Pit LFO 2 - + + Peak 4 + - Osc 1 - PW env 1 - + + High Shelf + - Osc 1 - PW env 2 - + + LP + - Osc 1 - PW LFO 1 - + + In Gain + - Osc 1 - PW LFO 2 - + + + + Gain + 增益 - Osc 3 - Sub env 1 - + + Out Gain + - Osc 3 - Sub env 2 - + + Bandwidth: + - Osc 3 - Sub LFO 1 - + + Octave + - Osc 3 - Sub LFO 2 - + + Resonance : + - - - MonstroView - Operators view - + + Frequency: + 頻率: - Matrix view - 矩陣視圖 + + lp grp + - Volume - 音量 + + hp grp + + + + EqHandle - Panning - 聲相 + + Reso: + - Coarse detune - + + BW: + - semitones - 半音 + + + Freq: + + + + ExportProjectDialog - cents - + + Export project + 導出工程 - Stereo phase offset - + + Output + 輸出 - deg - + + File format: + 檔案格式: - Pulse width - + + Samplerate: + 採樣率: - Send sync on pulse rise - + + 44100 Hz + 44100 Hz - Send sync on pulse fall - + + 48000 Hz + 48000 Hz - Hard sync oscillator 2 - + + 88200 Hz + 88200 Hz - Reverse sync oscillator 2 - + + 96000 Hz + 96000 Hz - Sub-osc mix - + + 192000 Hz + 192000 Hz - Hard sync oscillator 3 - + + Depth: + 位深: - Reverse sync oscillator 3 - + + 16 Bit Integer + 16 位整形 - Attack - 打進聲 + + 24 Bit Integer + 24 位元整數 - Rate - + + 32 Bit Float + 32 位浮點型 - Phase - + + Stereo mode: + - Pre-delay - + + Stereo + - Hold - 保持 + + Joint Stereo + - Decay - 衰減 + + Mono + - Sustain - 持續 + + Bitrate: + 碼率: - Release - 釋放 + + 64 KBit/s + 64 KBit/s - Slope - + + 128 KBit/s + 128 KBit/s - Modulation amount - 調製量 + + 160 KBit/s + 160 KBit/s - Fine tune left - + + 192 KBit/s + 192 KBit/s - Fine tune right - + + 256 KBit/s + 256 KBit/s - Mix osc 2 with osc 3 - + + 320 KBit/s + 320 KBit/s - Modulate amplitude of osc 3 by osc 2 - + + Use variable bitrate + 使用可變位元率 - Modulate frequency of osc 3 by osc 2 - + + Quality settings + 質量設置 - Modulate phase of osc 3 by osc 2 - + + Interpolation: + 補間: - - - MultitapEchoControlDialog - Length - 長度 + + Zero Order Hold + 零階保持 - Step length: - 步進長度: + + Sinc Fastest + 最快 Sinc 補間 - Dry - 幹聲 + + Sinc Medium (recommended) + 中等 Sinc 補間 (推薦) - Stages - + + Sinc Best (very slow!) + 最佳 Sinc 補間 (很慢!) - Swap inputs - + + Oversampling (use with care!): + 過採樣 (請謹慎使用!): - Dry gain: - + + 1x (None) + 1x (無) - Low-pass stages: - + + 2x + 2x - Swap left and right input channels for reflections - + + 4x + 4x - - - NesInstrument - Channel 2 Coarse detune - + + 8x + 8x - Channel 2 Volume - + + Export as loop (remove end silence) + 導出爲迴環loop(移除結尾的靜音) - Master volume - 主音量 + + Export between loop markers + 只導出迴環標記中間的部分 - Vibrato - + + Start + 開始 - Channel 1 coarse detune - + + Cancel + 取消 - Channel 1 volume - + + Could not open file + 無法開啟檔案 - Channel 1 envelope length - + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + 無法開啟 %1 以進行寫入。 +請確認您有權限存取此檔案,以及包含此檔案的目錄後再試一次。 - Channel 1 duty cycle - + + Export project to %1 + 導出項目到 %1 - Channel 1 sweep amount - + + Error + 錯誤 - Channel 1 sweep rate - + + Error while determining file-encoder device. Please try to choose a different output format. + 偵測檔案編碼裝置時發生錯誤。請嘗試使用其他輸出格式。 - Channel 2 envelope length - + + Rendering: %1% + 渲染中:%1% - Channel 2 duty cycle - + Compression level: + - Channel 2 sweep amount - + (fastest) + - Channel 2 sweep rate - + (default) + - Channel 3 coarse detune - + (smallest) + + + + Expressive - Channel 3 volume - + Selected graph + - Channel 4 volume - + A1 + - Channel 4 envelope length - + A2 + - Channel 4 noise frequency - + A3 + - Channel 4 noise frequency sweep - + W1 smoothing + - - - NesInstrumentView - Volume - 音量 + W2 smoothing + - Coarse detune - + W3 smoothing + - Envelope length - + PAN1 + - Enable channel 1 - + PAN2 + - Enable envelope 1 - + REL TRANS + + + + Fader - Enable envelope 1 loop - + + + Please enter a new value between %1 and %2: + 請輸入一個介於%1和%2之間的數值: + + + FileBrowser - Enable sweep 1 - + + Browser + 瀏覽器 - Sweep amount - + Search + - Sweep rate - + Refresh list + + + + FileBrowserTreeWidget - 12.5% Duty cycle - + + Send to active instrument-track + 發送到活躍的樂器軌道 - 25% Duty cycle - + + Open in new instrument-track/Song Editor + 在新的樂器軌道/歌曲編輯器中打開 - 50% Duty cycle - + + Open in new instrument-track/B+B Editor + 在新樂器軌道/B+B 編輯器中打開 - 75% Duty cycle - + + Loading sample + 加載採樣中 - Enable channel 2 - + + Please wait, loading sample for preview... + 請稍候,加載採樣中... - Enable envelope 2 - + + Error + 錯誤 - Enable envelope 2 loop - + + does not appear to be a valid + 並不是一個有效的 - Enable sweep 2 - + + file + 檔案 - Enable channel 3 - + + --- Factory files --- + --- 內建檔案 --- + + + FlangerControls - Noise Frequency - + + Delay Samples + - Frequency sweep - + + Lfo Frequency + - Enable channel 4 - + + Seconds + - Enable envelope 4 - + + Regen + - Enable envelope 4 loop - + + Noise + 噪音 - Quantize noise frequency when using note frequency - - - - Use note frequency for noise - - - - Noise mode - - - - Vibrato - - - - Master volume - 主音量 + + Invert + 反轉 - OpulenzInstrument + FlangerControlsDialog - Patch - 音色 + + DELAY + - Op 1 attack - + + Delay Time: + 延遲時間: - Op 1 decay - + + RATE + - Op 1 sustain - + + Period: + - Op 1 release - + + AMNT + - Op 1 level - + + Amount: + - Op 1 level scaling - + + FDBK + - Op 1 frequency multiplier - + + Feedback Amount: + - Op 1 feedback - + + NOISE + - Op 1 key scaling rate - + + White Noise Amount: + 白噪音數量: - Op 1 percussive envelope - + + Invert + 反轉 + + + FxLine - Op 1 tremolo - + + Channel send amount + 通道發送的數量 - Op 1 vibrato - + + The FX channel receives input from one or more instrument tracks. + It in turn can be routed to multiple other FX channels. LMMS automatically takes care of preventing infinite loops for you and doesn't allow making a connection that would result in an infinite loop. + +In order to route the channel to another channel, select the FX channel and click on the "send" button on the channel you want to send to. The knob under the send button controls the level of signal that is sent to the channel. + +You can remove and move FX channels in the context menu, which is accessed by right-clicking the FX channel. + + - Op 1 waveform - + + Move &left + 向左移(&L) - Op 2 attack - + + Move &right + 向右移(&R) - Op 2 decay - + + Rename &channel + 重命名通道(&C) - Op 2 sustain - + + R&emove channel + 刪除通道(&E) - Op 2 release - + + Remove &unused channels + 移除所有未用通道(&U) + + + FxMixer - Op 2 level - + + Master + 主控 - Op 2 level scaling - + + + + FX %1 + FX %1 - Op 2 frequency multiplier - + + Volume + 音量 - Op 2 key scaling rate - + + Mute + 靜音 - Op 2 percussive envelope - + + Solo + 獨奏 + + + FxMixerView - Op 2 tremolo - + + FX-Mixer + 效果混合器 - Op 2 vibrato - + + FX Fader %1 + FX 衰減器 %1 - Op 2 waveform - + + Mute + 靜音 - FM - + + Mute this FX channel + 靜音此效果通道 - Vibrato depth - + + Solo + 獨奏 - Tremolo depth - + + Solo FX channel + 獨奏效果通道 - OpulenzInstrumentView + FxRoute - Attack - 打進聲 + + + Amount to send from channel %1 to channel %2 + 從通道 %1 發送到通道 %2 的量 + + + GigInstrument - Decay - 衰減 + + Bank + - Release - 釋放 + + Patch + 音色 - Frequency multiplier - + + Gain + 增益 - OscillatorObject + GigInstrumentView - Osc %1 volume - Osc %1 音量 + + Open other GIG file + 打開另外的 GIG 文件 - Osc %1 panning - Osc %1 聲像 + + Click here to open another GIG file + 點擊這裏打開另外一個 GIG 文件 - Osc %1 coarse detuning - + + Choose the patch + 選擇路徑 - Osc %1 fine detuning left - + + Click here to change which patch of the GIG file to use + 點擊這裏選擇另一種 GIG 音色 - Osc %1 fine detuning right - + + + Change which instrument of the GIG file is being played + 更換正在使用的 GIG 文件中的樂器 - Osc %1 phase-offset - + + Which GIG file is currently being used + 哪一個 GIG 文件正在被使用 - Osc %1 stereo phase-detuning - + + Which patch of the GIG file is currently being used + GIG 文件的哪一個音色正在被使用 - Osc %1 wave shape - + + Gain + 增益 - Modulation type %1 - + + Factor to multiply samples by + - Osc %1 waveform - Osc %1 波形 + + Open GIG file + 開啟 GIG 檔案 - Osc %1 harmonic - + + GIG Files (*.gig) + GIG 檔案 (*.gig) - PatchesDialog + GuiApplication - Qsynth: Channel Preset - Qsynth: 通道預設 + + Working directory + 工作目錄 - Bank selector - 音色選擇器 + + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. + LMMS工作目錄%1不存在,現在新建一個嗎?你可以稍後在 編輯 -> 設置 中更改此設置。 - Bank - + + Preparing UI + 正在準備界面 - Program selector - + + Preparing song editor + 正在準備歌曲編輯器 - Patch - 音色 + + Preparing mixer + 正在準備混音器 - Name - 名稱 + + Preparing controller rack + 正在準備控制機架 - OK - 確定 + + Preparing project notes + 正在準備專案音符 - Cancel - 取消 + + Preparing beat/bassline editor + 正在準備節拍/低音線編輯器 + + + + Preparing piano roll + 正在準備鋼琴捲簾 + + + + Preparing automation editor + 正在準備自動化控制編輯器 - PatmanView + InstrumentFunctionArpeggio - Loop - 循環 + + Arpeggio + - Loop mode - 循環模式 + + Arpeggio type + - Tune - 調音 + + Arpeggio range + - Tune mode - 調音模式 + + Cycle steps + - No file selected - 未選擇文件 + + Skip rate + - Open patch file - 打開音色文件 + + Miss rate + - Patch-Files (*.pat) - 音色文件 (*.pat) + + Arpeggio time + - Open patch - + + Arpeggio gate + - - - PeakControllerEffectControlDialog - BASE - 基準 + + Arpeggio direction + - Modulation amount: - 調製量: + + Arpeggio mode + - Attack: - 打擊聲: + + Up + 向上 - Release: - 釋音: + + Down + 向下 - AMNT - + + Up and down + 上和下 - MULT - + + Down and up + 下和上 - ATCK - 打擊 + + Random + 隨機 - DCAY - + + Free + 自由 - Treshold: - + + Sort + 排序 - TRSH - + + Sync + 同步 + + + InstrumentFunctionArpeggioView - Base: - + + ARPEGGIO + 琶音 - Amount multiplicator: - + + An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. + - Mute output - 輸出靜音 + + RANGE + 範圍 - Absolute value - + + Arpeggio range: + - - - PeakControllerEffectControls - Base value - 基準值 + + octave(s) + - Modulation amount - 調製量 + + Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. + - Mute output - 輸出靜音 + + CYCLE + - Attack - 打進聲 + + Cycle notes: + - Release - 釋放 + + note(s) + - Treshold - 閥值 + + Jumps over n steps in the arpeggio and cycles around if we're over the note range. If the total note range is evenly divisible by the number of steps jumped over you will get stuck in a shorter arpeggio or even on one note. + - Absolute value - + + SKIP + - Amount multiplicator - + + Skip rate: + - - - QWidget - Name: - 名稱: + + + + % + % - Maker: - 製作者: + + The skip function will make the arpeggiator pause one step randomly. From its start in full counter clockwise position and no effect it will gradually progress to full amnesia at maximum setting. + - Copyright: - 版權: + + MISS + - Requires Real Time: - 要求實時: + + Miss rate: + - Yes - + + The miss function will make the arpeggiator miss the intended note. + - No - + + TIME + 時長 - Real Time Capable: - 是否支持實時: + + Arpeggio time: + - In Place Broken: - + + ms + 毫秒 - Channels In: - 輸入通道: + + Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. + - Channels Out: - 輸出通道: + + GATE + 門限 - File: - 文件: + + Arpeggio gate: + - File: %1 - 文件:%1 + + Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. + - - - ReverbSCControlDialog - Input - 輸入 + + Chord: + 和絃: - Size - + + Direction: + 方向: - Size: - + + Mode: + 模式: + + + InstrumentFunctionNoteStacking - Color - + + octave + octave - Color: - + + + Major + Major - Output - 輸出 + + Majb5 + Majb5 - Input gain: - 輸入增益: + + minor + minor - Output gain: - 輸出增益: + + minb5 + minb5 - - - ReverbSCControls - Size - + + sus2 + sus2 - Color - + + sus4 + sus4 - Input gain - 輸入增益 + + aug + aug - Output gain - 輸出增益 + + augsus4 + augsus4 - - - SpectrumAnalyzerControlDialog - Linear spectrum - 線性頻譜圖 + + tri + tri - Linear Y axis - 線性 Y 軸 + + 6 + 6 - - - SpectrumAnalyzerControls - Linear spectrum - 線性頻譜圖 + + 6sus4 + 6sus4 - Linear Y axis - 線性 Y 軸 + + 6add9 + 6add9 - Channel mode - 通道模式 + + m6 + m6 - - - TrackContainer - Cancel - 取消 + + m6add9 + m6add9 - Please wait... - 請稍等... + + 7 + 7 - Importing MIDI-file... - 正在導入 MIDI-文件... + + 7sus4 + 7sus4 - - - TripleOscillatorView - Synchronize oscillator 1 with oscillator 2 - + + 7#5 + 7#5 - Synchronize oscillator 2 with oscillator 3 - + + 7b5 + 7b5 - Osc %1 volume: - + + 7#9 + 7#9 - Osc %1 panning: - + + 7b9 + 7b9 - Osc %1 coarse detuning: - + + 7#5#9 + 7#5#9 - semitones - + + 7#5b9 + 7#5b9 - Osc %1 fine detuning left: - + + 7b5b9 + 7b5b9 - cents - 音分 cents + + 7add11 + 7add11 - Osc %1 fine detuning right: - + + 7add13 + 7add13 - Osc %1 phase-offset: - + + 7#11 + 7#11 - degrees - + + Maj7 + Maj7 - Osc %1 stereo phase-detuning: - + + Maj7b5 + Maj7b5 - Modulate phase of oscillator 1 by oscillator 2 - + + Maj7#5 + Maj7#5 - Modulate amplitude of oscillator 1 by oscillator 2 - + + Maj7#11 + Maj7#11 - Mix output of oscillators 1 & 2 - + + Maj7add13 + Maj7add13 - Modulate frequency of oscillator 1 by oscillator 2 - + + m7 + m7 - Modulate phase of oscillator 2 by oscillator 3 - + + m7b5 + m7b5 - Modulate amplitude of oscillator 2 by oscillator 3 - + + m7b9 + m7b9 - Mix output of oscillators 2 & 3 - + + m7add11 + m7add11 - Modulate frequency of oscillator 2 by oscillator 3 - + + m7add13 + m7add13 - Sine wave - 正弦波 + + m-Maj7 + m-Maj7 - Triangle wave - 三角波 + + m-Maj7add11 + m-Maj7add11 - Saw wave - 鋸齒波 + + m-Maj7add13 + m-Maj7add13 - Square wave - 方波 + + 9 + 9 - Moog-like saw wave - + + 9sus4 + 9sus4 - Exponential wave - + + add9 + add9 - White noise - + + 9#5 + 9#5 - User-defined wave - + + 9b5 + 9b5 - - - VestigeInstrumentView - Show/hide GUI - 顯示/隱藏界面 + + 9#11 + 9#11 - Turn off all notes - 全部靜音 + + 9b13 + 9b13 - DLL-files (*.dll) - DLL-文件 (*.dll) + + Maj9 + Maj9 - EXE-files (*.exe) - EXE-文件 (*.exe) + + Maj9sus4 + Maj9sus4 - Previous (-) - 上一個 (-) + + Maj9#5 + Maj9#5 - Save preset - 保存預置 + + Maj9#11 + Maj9#11 - Next (+) - 下一個 (+) + + m9 + m9 - Preset - 預置 + + madd9 + madd9 - by - + + m9b5 + m9b5 - - VST plugin control - - VST插件控制 + + m9-Maj7 + m9-Maj7 - Open VST plugin - + + 11 + 11 - Control VST plugin from LMMS host - + + 11b9 + 11b9 - Open VST plugin preset - + + Maj11 + Maj11 - No VST plugin loaded - + + m11 + m11 - - - VstEffectControlDialog - Show/hide - 顯示/隱藏 + + m-Maj11 + m-Maj11 - Previous (-) - 上一個 (-) + + 13 + 13 - Next (+) - 下一個 (+) + + 13#9 + 13#9 - Save preset - 保存預置 + + 13b9 + 13b9 - Effect by: - + + 13b5b9 + 13b5b9 - &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> - + + Maj13 + Maj13 - Control VST plugin from LMMS host - + + m13 + m13 - Open VST plugin preset - + + m-Maj13 + m-Maj13 - - - VstPlugin - Loading plugin - 載入插件 + + Harmonic minor + Harmonic minor - Open Preset - 打開預置 + + Melodic minor + Melodic minor - Vst Plugin Preset (*.fxp *.fxb) - VST插件預置文件(*.fxp *.fxb) + + Whole tone + - : default - : 默認 + + Diminished + Diminished - " - " + + Major pentatonic + Major pentatonic - ' - ' + + Minor pentatonic + Minor pentatonic - Save Preset - 保存預置 + + Jap in sen + Jap in sen - .fxp - .fxp + + Major bebop + Major bebop - .FXP - .FXP + + Dominant bebop + Dominant bebop - .FXB - .FXB + + Blues + Blues - .fxb - .fxb + + Arabic + Arabic - Please wait while loading VST plugin... - 正在載入VST插件,請稍候…… + + Enigmatic + Enigmatic - The VST plugin %1 could not be loaded. - 無法載入VST插件 %1。 + + Neopolitan + Neopolitan - - - WatsynInstrument - Volume A1 - + + Neopolitan minor + Neopolitan minor - Volume A2 - + + Hungarian minor + Hungarian minor - Volume B1 - + + Dorian + Dorian - Volume B2 - + + Phrygian + - Panning A1 - + + Lydian + Lydian - Panning A2 - + + Mixolydian + Mixolydian - Panning B1 - + + Aeolian + Aeolian - Panning B2 - + + Locrian + Locrian - Freq. multiplier A1 - + + Minor + Minor - Freq. multiplier A2 - + + Chromatic + Chromatic - Freq. multiplier B1 - + + Half-Whole Diminished + - Freq. multiplier B2 - + + 5 + 5 - Left detune A1 - + + Phrygian dominant + - Left detune A2 - + + Persian + - Left detune B1 - + + Chords + Chords - Left detune B2 - + + Chord type + Chord type - Right detune A1 - + + Chord range + Chord range + + + InstrumentFunctionNoteStackingView - Right detune A2 - + + STACKING + 堆疊 - Right detune B1 - + + Chord: + 和絃: - Right detune B2 - + + RANGE + 範圍 - A-B Mix - + + Chord range: + 和絃範圍: - A-B Mix envelope amount - + + octave(s) + - A-B Mix envelope attack - + + Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. + + + + InstrumentMidiIOView - A-B Mix envelope hold - + + ENABLE MIDI INPUT + 啓用MIDI輸入 - A-B Mix envelope decay - + + + CHANNEL + 通道 - A1-B2 Crosstalk - + + + VELOCITY + 力度 - A2-A1 modulation - + + ENABLE MIDI OUTPUT + 啓用MIDI輸出 - B2-B1 modulation - + + PROGRAM + 樂器 - Selected graph - + + NOTE + 音符 - - - WatsynView - Select oscillator A1 - + + MIDI devices to receive MIDI events from + 用於接收 MIDI 事件的 MIDI 設備 - Select oscillator A2 - + + MIDI devices to send MIDI events to + 用於發送 MIDI 事件的 MIDI 設備 - Select oscillator B1 - + + CUSTOM BASE VELOCITY + 自定義基準力度 - Select oscillator B2 - + + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity + - Mix output of A2 to A1 - + + BASE VELOCITY + 基準力度 + + + InstrumentMiscView - Mix output of B2 to B1 - + + MASTER PITCH + 主音高 - Draw your own waveform here by dragging your mouse on this graph. - + + Enables the use of Master Pitch + 啓用主音高 + + + InstrumentSoundShaping - Load waveform - 載入波形 + + VOLUME + 音量 - Phase left - + + Volume + 音量 - Phase right - + + CUTOFF + 切除 - Normalize - 標準化 + + + Cutoff frequency + 切除頻率 - Invert - 反轉 + + RESO + - Smooth - 平滑 + + Resonance + 共鳴 - Sine wave - 正弦波 + + Envelopes/LFOs + 壓限/低頻振盪 - Triangle wave - 三角波 + + Filter type + 過濾器類型 - Square wave - 方波 + + Q/Resonance + - Volume - 音量 + + LowPass + 低通 - Panning - 聲相 + + HiPass + 高通 - Freq. multiplier - + + BandPass csg + 帶通 csg - Left detune - + + BandPass czpg + 帶通 czpg - cents - + + Notch + 凹口濾波器 - Right detune - + + Allpass + 全通 - A-B Mix - + + Moog + Moog - Mix envelope amount - + + 2x LowPass + 2 個低通串聯 - Mix envelope attack - + + RC LowPass 12dB + RC 低通(12dB) - Mix envelope hold - + + RC BandPass 12dB + RC 帶通(12dB) - Mix envelope decay - + + RC HighPass 12dB + RC 高通(12dB) - Crosstalk - + + RC LowPass 24dB + RC 低通(24dB) - Modulate amplitude of A1 by output of A2 - + + RC BandPass 24dB + RC 帶通(24dB) - Ring modulate A1 and A2 - + + RC HighPass 24dB + RC 高通(24dB) - Modulate phase of A1 by output of A2 - + + Vocal Formant Filter + 人聲移除過濾器 - Modulate amplitude of B1 by output of B2 - + + 2x Moog + - Ring modulate B1 and B2 - + + SV LowPass + - Modulate phase of B1 by output of B2 - + + SV BandPass + - Load a waveform from a sample file - + + SV HighPass + - Shift phase by -15 degrees - + + SV Notch + - Shift phase by +15 degrees - + + Fast Formant + - Saw wave - 鋸齒波 + + Tripole + - Xpressive + InstrumentSoundShapingView - Selected graph - + + TARGET + 目標 - A1 - + + These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! + - A2 - + + FILTER + - A3 - + + Here you can select the built-in filter you want to use for this instrument-track. Filters are very important for changing the characteristics of a sound. + - W1 smoothing - + + FREQ + 頻率 - W2 smoothing - + + cutoff frequency: + - W3 smoothing - + + Hz + Hz - Panning 1 - + + Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... + - Panning 2 - + + RESO + - Rel trans - + + Resonance: + 共鳴: - - - XpressiveView - Draw your own waveform here by dragging your mouse on this graph. - + + Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. + - Select oscillator W1 - + + Envelopes, LFOs and filters are not supported by the current instrument. + 包絡和低頻振盪 (LFO) 不被當前樂器支持。 + + + InstrumentTrack - Select oscillator W2 - + + With this knob you can set the volume of the opened channel. + 使用此旋鈕可以設置開放通道的音量。 - Select oscillator W3 - + + + unnamed_track + 未命名軌道 - Select output O1 - + + Base note + 基本音 - Select output O2 - + + Volume + 音量 - Open help window - + + Panning + 聲相 - Sine wave - 正弦波 + + Pitch + 音高 - Moog-saw wave - + + Pitch range + 音域範圍 - Exponential wave - + + FX channel + 效果通道 - Saw wave - 鋸齒波 + + Master Pitch + 主音高 - User-defined wave - + + + Default preset + 預置 + + + InstrumentTrackView - Triangle wave - 三角波 + + Volume + 音量 - Square wave - 方波 + + Volume: + 音量: - White noise - + + VOL + VOL - WaveInterpolate - + + Panning + 聲相 - ExpressionValid - + + Panning: + 聲相: - General purpose 1: - + + PAN + PAN - General purpose 2: - + + MIDI + MIDI - General purpose 3: - + + Input + 輸入 - O1 panning: - + + Output + 輸出 - O2 panning: - + + FX %1: %2 + 效果 %1: %2 + + + InstrumentTrackWindow - Release transition: - + + GENERAL SETTINGS + 常規設置 - Smoothness - + + Use these controls to view and edit the next/previous track in the song editor. + 使用這些控制選項來查看和編輯在歌曲編輯器中的上個/下個軌道。 - - - ZynAddSubFxInstrument - Portamento - + + Instrument volume + 樂器音量 - Bandwidth - 帶寬 + + Volume: + 音量: - Filter frequency - + + VOL + VOL - Filter resonance - + + Panning + 聲相 - FM gain - + + Panning: + 聲相: - Resonance center frequency - + + PAN + PAN - Resonance bandwidth - + + Pitch + 音高 - Forward MIDI control change events - + + Pitch: + 音高: - - - ZynAddSubFxView - Show GUI - 顯示圖形界面 + + cents + 音分 cents - Portamento: - + + PITCH + - PORT - + + Pitch range (semitones) + 音域範圍(半音) - FREQ - 頻率 + + RANGE + 範圍 - RES - + + FX channel + 效果通道 - Bandwidth: - 帶寬: + + FX + 效果 - BW - + + Save current instrument track settings in a preset file + 儲存目前的樂器軌道設定為預設集檔案 - FM GAIN - + + Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. + 如果你想保存當前樂器軌道設置到預設文件, 請點擊這裏。稍後你可以在預設瀏覽器中雙擊以使用它。 - Resonance center frequency: - + + SAVE + 保存 - RES CF - + + Envelope, filter & LFO + - Resonance bandwidth: - + + Chord stacking & arpeggio + - RES BW - + + Effects + - Filter frequency: - + + MIDI settings + MIDI設置 - Filter resonance: - + + Miscellaneous + + + + + Save preset + 保存預置 - FM gain: - + + XML preset file (*.xpf) + XML 預設集檔案 (*.xpf) - Forward MIDI control changes - + + Plugin + - audioFileProcessor + Knob - Amplify - 增益 + + Set linear + 設置爲線性 - Start of sample - 採樣起始 + + Set logarithmic + 設置爲對數 - End of sample - 採樣結尾 + + Please enter a new value between -96.0 dBFS and 6.0 dBFS: + - Reverse sample - 反轉採樣 + + Please enter a new value between %1 and %2: + 請輸入一個介於%1和%2之間的數值: + + + LadspaControl - Stutter - + + Link channels + 關聯通道 + + + LadspaControlDialog - Loopback point + + Link Channels + 連接通道 + + + + Channel + 通道 + + + + LadspaControlView + + + Link channels + 連接通道 + + + + Value: + 值: + + + + Sorry, no help available. + 啊哦,這個沒有幫助文檔。 + + + + LadspaEffect + + + Unknown LADSPA plugin %1 requested. + 已請求未知 LADSPA 插件 %1. + + + + LcdSpinBox + + + Please enter a new value between %1 and %2: + 請輸入一個介於%1和%2之間的數值: + + + + LeftRightNav + + + + + Previous + 上個 + + + + + + Next + 下個 + + + + Previous (%1) + 上 (%1) + + + + Next (%1) + 下 (%1) + + + + LfoController + + + LFO Controller + LFO 控制器 + + + + Base value + 基準值 + + + + Oscillator speed + 振動速度 + + + + Oscillator amount + + + + + Oscillator phase + + + + + Oscillator waveform + 振動波形 + + + + Frequency Multiplier + + + + + LfoControllerDialog + + + LFO + + + + + LFO Controller + LFO 控制器 + + + + BASE + 基準 + + + + Base amount: + 基礎值: + + + + todo + + + + + SPD + + + + + LFO-speed: + + + + + Use this knob for setting speed of the LFO. The bigger this value the faster the LFO oscillates and the faster the effect. + + + + + AMNT + + + + + Modulation amount: + 調製量: + + + + Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. + + + + + PHS + + + + + Phase offset: + + + + + degrees + + + + + With this knob you can set the phase offset of the LFO. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + + + + + Click here for a sine-wave. + 點擊這裡使用正弦波。 + + + + Click here for a triangle-wave. + 點擊這裡使用三角波。 + + + + Click here for a saw-wave. + + + + + Click here for a square-wave. + 點擊這裡使用方形波。 + + + + Click here for a moog saw-wave. + + + + + Click here for an exponential wave. + + + + + Click here for white-noise. + + + + + Click here for a user-defined shape. +Double click to pick a file. + + + + + LmmsCore + + + Generating wavetables + 正在生成波形表 + + + + Initializing data structures + 正在初始化數據結構 + + + + Opening audio and midi devices + 正在啓動音頻和 MIDI 設備 + + + + Launching mixer threads + 生在啓動混音器線程 + + + + MainWindow + + + Configuration file + 設定檔 + + + + Error while parsing configuration file at line %1:%2: %3 + 解析設定檔時發生錯誤(行 %1:%2:%3) + + + + Could not open file + 無法開啟檔案 + + + + Could not open file %1 for writing. +Please make sure you have write permission to the file and the directory containing the file and try again! + 無法開啟 %1 以進行寫入。 +請確認您有權限存取此檔案,以及包含此檔案的目錄後再試一次。 + + + + Project recovery + 工程恢復 + + + + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + 發現復原檔案。可能是上一個工作階段未正常結束,或者另一個 LMMS 已在執行。您想要復原這個專案嗎? + + + + + + Recover + 恢復 + + + + Recover the file. Please don't run multiple instances of LMMS when you do this. + 復原檔案。請不要在復原檔案時同時開啟多個 LMMS 視窗。 + + + + + + Discard + 丟棄 + + + + Launch a default session and delete the restored files. This is not reversible. + 開啟新的預設工作階段並刪除已復原的檔案。此操作無法復原。 + + + + Version %1 + 版本 %1 + + + + Preparing plugin browser + 正在準備插件瀏覽器 + + + + Preparing file browsers + 正在準備檔案瀏覽器 + + + + My Projects + 我的工程 + + + + My Samples + 我的採樣 + + + + My Presets + 我的預設 + + + + My Home + 我的主目錄 + + + + Root directory + 根目錄 + + + + Volumes + 音量 + + + + My Computer + 我的電腦 + + + + Loading background artwork + 正在加載背景圖案 + + + + &File + 檔案(&F) + + + + &New + 新建(&N) + + + + New from template + 從模版新建工程 + + + + &Open... + 打開(&O)... + + + + &Recently Opened Projects + 最近打開的工程(&R) + + + + &Save + 保存(&S) + + + + Save &As... + 另存爲(&A)... + + + + Save as New &Version + 保存爲新版本(&V) + + + + Save as default template + 保存爲默認模板 + + + + Import... + 導入... + + + + E&xport... + 導出(&E)... + + + + E&xport Tracks... + 導出音軌(&X)... + + + + Export &MIDI... + 導出 MIDI (&M)... + + + + &Quit + 退出(&Q) + + + + &Edit + 編輯(&E) + + + + Undo + 撤銷 + + + + Redo + 重做 + + + + Settings + 設置 + + + + &View + 視圖 (&V) + + + + &Tools + 工具(&T) + + + + &Help + 幫助(&H) + + + + Online Help + 在線幫助 + + + + Help + 幫助 + + + + What's This? + 這是什麼? + + + + About + 關於 + + + + Create new project + 新建工程 + + + + Create new project from template + 從模版新建工程 + + + + Open existing project + 打開已有工程 + + + + Recently opened projects + 最近打開的工程 + + + + Save current project + 保存當前工程 + + + + Export current project + 導出當前工程 + + + + What's this? + 這是什麼? + + + + Toggle metronome + 開啓/關閉節拍器 + + + + Show/hide Song-Editor + 顯示/隱藏歌曲編輯器 + + + + By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. + 點擊這個按鈕, 你可以顯示/隱藏歌曲編輯器。在歌曲編輯器的幫助下, 你可以編輯歌曲播放列表並且設置哪個音軌在哪個時間播放。你還可以在播放列表中直接插入和移動採樣(如 RAP 採樣)。 + + + + Show/hide Beat+Bassline Editor + 顯示/隱藏節拍+旋律編輯器 + + + + By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. + + + + + Show/hide Piano-Roll + 顯示/隱藏鋼琴窗 + + + + Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. + 點擊這裏顯示或隱藏鋼琴窗。在鋼琴窗的幫助下, 你可以很容易地編輯旋律。 + + + + Show/hide Automation Editor + 顯示/隱藏自動控制編輯器 + + + + Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. + 點擊這裏顯示或隱藏自動控制編輯器。在自動控制編輯器的幫助下, 你可以很簡單地控制動態數值。 + + + + Show/hide FX Mixer + 顯示/隱藏混音器 + + + + Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. + 點擊這裏顯示或隱藏 FX 混音器。FX 混音器是管理你歌曲中不同音效的強大工具。你可以向不同的通道添加不同的效果。 + + + + Show/hide project notes + 顯示/隱藏工程註釋 + + + + Click here to show or hide the project notes window. In this window you can put down your project notes. + 點擊這裏顯示或隱藏工程註釋窗。在此窗口中你可以寫下工程的註釋。 + + + + Show/hide controller rack + 顯示/隱藏控制器機架 + + + + Untitled + 未命名 + + + + Recover session. Please save your work! + 恢復會話。請保存你的工作! + + + + LMMS %1 + LMMS %1 + + + + Recovered project not saved + 恢復的工程沒有保存 + + + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + 這個工程已從上一個會話中恢復。它現在沒有被保存, 並且如果你不保存, 它將會丟失。你現在想保存它嗎? + + + + Project not saved + 工程未保存 + + + + The current project was modified since last saving. Do you want to save it now? + 此工程自上次保存後有了修改,你想保存嗎? + + + + Open Project + 打開工程 + + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + + Save Project + 保存工程 + + + + LMMS Project + LMMS 工程 + + + + LMMS Project Template + LMMS 工程模板 + + + + Save project template + + + + + Overwrite default template? + 覆蓋默認的模板? + + + + This will overwrite your current default template. + 這將會覆蓋你的當前默認模板。 + + + + Help not available + 幫助不可用 + + + + Currently there's no help available in LMMS. +Please visit http://lmms.sf.net/wiki for documentation on LMMS. + LMMS現在沒有可用的幫助 +請訪問 http://lmms.sf.net/wiki 瞭解LMMS的相關文檔。 + + + + Song Editor + 顯示/隱藏歌曲編輯器 + + + + Beat+Bassline Editor + 顯示/隱藏節拍+旋律編輯器 + + + + Piano Roll + 顯示/隱藏鋼琴窗 + + + + Automation Editor + 顯示/隱藏自動控制編輯器 + + + + FX Mixer + 顯示/隱藏混音器 + + + + Project Notes + 顯示/隱藏工程註釋 + + + + Controller Rack + 顯示/隱藏控制器機架 + + + + Volume as dBFS + + + + + Smooth scroll + 平滑滾動 + + + + Enable note labels in piano roll + 在鋼琴窗中顯示音號 + + + + MeterDialog + + + + Meter Numerator + + + + + + Meter Denominator + + + + + TIME SIG + 拍子記號 + + + + MeterModel + + + Numerator + + + + + Denominator + + + + + MidiController + + + MIDI Controller + MIDI控制器 + + + + unnamed_midi_controller + + + + + MidiImport + + + + Setup incomplete + 設置不完整 + + + + You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. + 你還沒有在設置(在編輯->設置)中設置默認的 Soundfont。因此在導入此 MIDI 文件後將會沒有聲音。你需要下載一個通用 MIDI (GM) 的 Soundfont, 並且在設置對話框中選中後再試一次。 + + + + You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. + 您在編譯 LMMS 時未一併啟用 SoundFont2 播放器支援,此播放器用於為匯入的 MIDI 檔案加入預設聲音,因此在匯入此 MIDI 檔後不會有聲音。 + + + + Track + 軌道 + + + + MidiJack + + + JACK server down + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (title) + JACK服務崩潰 + + + + The JACK server seems to be shuted down. + When JACK(JACK Audio Connection Kit) disconnects, it will show the following message (dialog message) + + + + + MidiPort + + + Input channel + 輸入通道 + + + + Output channel + 輸出通道 + + + + Input controller + 輸入控制器 + + + + Output controller + 輸出控制器 + + + + Fixed input velocity + + + + + Fixed output velocity + + + + + Fixed output note + + + + + Output MIDI program + + + + + Base velocity + 基準力度 + + + + Receive MIDI-events + 接受 MIDI 事件 + + + + Send MIDI-events + 發送 MIDI 事件 + + + + MidiSetupWidget + + + DEVICE + 設備 + + + + MonstroInstrument + + + Osc 1 Volume + + + + + Osc 1 Panning + + + + + Osc 1 Coarse detune + + + + + Osc 1 Fine detune left + + + + + Osc 1 Fine detune right + + + + + Osc 1 Stereo phase offset + + + + + Osc 1 Pulse width + + + + + Osc 1 Sync send on rise + + + + + Osc 1 Sync send on fall + + + + + Osc 2 Volume + + + + + Osc 2 Panning + + + + + Osc 2 Coarse detune + + + + + Osc 2 Fine detune left + + + + + Osc 2 Fine detune right + + + + + Osc 2 Stereo phase offset + + + + + Osc 2 Waveform + + + + + Osc 2 Sync Hard + + + + + Osc 2 Sync Reverse + + + + + Osc 3 Volume + + + + + Osc 3 Panning + + + + + Osc 3 Coarse detune + + + + + Osc 3 Stereo phase offset + + + + + Osc 3 Sub-oscillator mix + + + + + Osc 3 Waveform 1 + + + + + Osc 3 Waveform 2 + + + + + Osc 3 Sync Hard + + + + + Osc 3 Sync Reverse + + + + + LFO 1 Waveform + + + + + LFO 1 Attack + + + + + LFO 1 Rate + + + + + LFO 1 Phase + + + + + LFO 2 Waveform + + + + + LFO 2 Attack + + + + + LFO 2 Rate + + + + + LFO 2 Phase + + + + + Env 1 Pre-delay + + + + + Env 1 Attack + + + + + Env 1 Hold + + + + + Env 1 Decay + + + + + Env 1 Sustain + + + + + Env 1 Release + + + + + Env 1 Slope + + + + + Env 2 Pre-delay + + + + + Env 2 Attack + + + + + Env 2 Hold + + + + + Env 2 Decay + + + + + Env 2 Sustain + + + + + Env 2 Release + + + + + Env 2 Slope + + + + + Osc2-3 modulation + + + + + Selected view + + + + + Vol1-Env1 + + + + + Vol1-Env2 + + + + + Vol1-LFO1 + + + + + Vol1-LFO2 + + + + + Vol2-Env1 + + + + + Vol2-Env2 + + + + + Vol2-LFO1 + + + + + Vol2-LFO2 + + + + + Vol3-Env1 + + + + + Vol3-Env2 + + + + + Vol3-LFO1 + + + + + Vol3-LFO2 + + + + + Phs1-Env1 + + + + + Phs1-Env2 + + + + + Phs1-LFO1 + + + + + Phs1-LFO2 + + + + + Phs2-Env1 + + + + + Phs2-Env2 + + + + + Phs2-LFO1 + + + + + Phs2-LFO2 + + + + + Phs3-Env1 + + + + + Phs3-Env2 + + + + + Phs3-LFO1 + + + + + Phs3-LFO2 + + + + + Pit1-Env1 + + + + + Pit1-Env2 + + + + + Pit1-LFO1 + + + + + Pit1-LFO2 + + + + + Pit2-Env1 + + + + + Pit2-Env2 + + + + + Pit2-LFO1 + + + + + Pit2-LFO2 + + + + + Pit3-Env1 + + + + + Pit3-Env2 + + + + + Pit3-LFO1 + + + + + Pit3-LFO2 + + + + + PW1-Env1 + + + + + PW1-Env2 + + + + + PW1-LFO1 + + + + + PW1-LFO2 + + + + + Sub3-Env1 + + + + + Sub3-Env2 + + + + + Sub3-LFO1 + + + + + Sub3-LFO2 + + + + + + Sine wave + 正弦波 + + + + Bandlimited Triangle wave + + + + + Bandlimited Saw wave + + + + + Bandlimited Ramp wave + + + + + Bandlimited Square wave + + + + + Bandlimited Moog saw wave + + + + + + Soft square wave + + + + + Absolute sine wave + + + + + + Exponential wave + + + + + White noise + + + + + Digital Triangle wave + + + + + Digital Saw wave + + + + + Digital Ramp wave + + + + + Digital Square wave + + + + + Digital Moog saw wave + + + + + Triangle wave + 三角波 + + + + Saw wave + 鋸齒波 + + + + Ramp wave + + + + + Square wave + 方波 + + + + Moog saw wave + + + + + Abs. sine wave + + + + + Random + 隨機 + + + + Random smooth + + + + + MonstroView + + + Operators view + + + + + The Operators view contains all the operators. These include both audible operators (oscillators) and inaudible operators, or modulators: Low-frequency oscillators and Envelopes. + +Knobs and other widgets in the Operators view have their own what's this -texts, so you can get more specific help for them that way. + + + + + Matrix view + 矩陣視圖 + + + + The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. + +The view is divided to modulation targets, grouped by the target oscillator. Available targets are volume, pitch, phase, pulse width and sub-osc ratio. Note: some targets are specific to one oscillator only. + +Each modulation target has 4 knobs, one for each modulator. By default the knobs are at 0, which means no modulation. Turning a knob to 1 causes that modulator to affect the modulation target as much as possible. Turning it to -1 does the same, but the modulation is inversed. + + + + + + + Volume + 音量 + + + + + + Panning + 聲相 + + + + + + Coarse detune + + + + + + + semitones + 半音 + + + + + Finetune left + + + + + + + + cents + + + + + + Finetune right + + + + + + + Stereo phase offset + + + + + + + + + deg + + + + + Pulse width + + + + + Send sync on pulse rise + + + + + Send sync on pulse fall + + + + + Hard sync oscillator 2 + + + + + Reverse sync oscillator 2 + + + + + Sub-osc mix + + + + + Hard sync oscillator 3 + + + + + Reverse sync oscillator 3 + + + + + + + + Attack + 打進聲 + + + + + Rate + + + + + + Phase + + + + + + Pre-delay + + + + + + Hold + 保持 + + + + + Decay + 衰減 + + + + + Sustain + 持續 + + + + + Release + 釋放 + + + + + Slope + + + + + Mix Osc2 with Osc3 + + + + + Modulate amplitude of Osc3 with Osc2 + + + + + Modulate frequency of Osc3 with Osc2 + + + + + Modulate phase of Osc3 with Osc2 + + + + + The CRS knob changes the tuning of oscillator 1 in semitone steps. + + + + + The CRS knob changes the tuning of oscillator 2 in semitone steps. + + + + + The CRS knob changes the tuning of oscillator 3 in semitone steps. + + + + + + + + FTL and FTR change the finetuning of the oscillator for left and right channels respectively. These can add stereo-detuning to the oscillator which widens the stereo image and causes an illusion of space. + + + + + + + The SPO knob modifies the difference in phase between left and right channels. Higher difference creates a wider stereo image. + + + + + The PW knob controls the pulse width, also known as duty cycle, of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, it doesn't produce bandlimited output, which means that you can use it as an audible oscillator but it will cause aliasing. You can also use it as an inaudible source of a sync signal, which can be used to synchronize oscillators 2 and 3. + + + + + Send Sync on Rise: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from low to high, ie. when the amplitude changes from -1 to 1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + + + + + Send Sync on Fall: When enabled, the Sync signal is sent every time the state of oscillator 1 changes from high to low, ie. when the amplitude changes from 1 to -1. Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, but its volume has no effect on them. Sync signals are sent independently for both left and right channels. + + + + + + Hard sync: Every time the oscillator receives a sync signal from oscillator 1, its phase is reset to 0 + whatever its phase offset is. + + + + + + Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, the amplitude of the oscillator gets inverted. + + + + + Choose waveform for oscillator 2. + + + + + Choose waveform for oscillator 3's first sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + + + + + Choose waveform for oscillator 3's second sub-osc. Oscillator 3 can smoothly interpolate between two different waveforms. + + + + + The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. Each sub-osc can be set to produce a different waveform, and oscillator 3 can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied to both sub-oscs/waveforms in the exact same way. + + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +Mix mode means no modulation: the outputs of the oscillators are simply mixed together. + + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. + + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch than "pure" frequency modulation. + + + + + In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by the output of oscillator 2. + +PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. It differs from frequency modulation in that the phase changes are not cumulative. + + + + + Select the waveform for LFO 1. +"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + + + + + Select the waveform for LFO 2. +"Random" and "Random smooth" are special waveforms: they produce random output, where the rate of the LFO controls how often the state of the LFO changes. The smooth version interpolates between these states with cosine interpolation. These random modes can be used to give "life" to your presets - add some of that analog unpredictability... + + + + + + Attack causes the LFO to come on gradually from the start of the note. + + + + + + Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. + + + + + + PHS controls the phase offset of the LFO. + + + + + + PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. + + + + + + ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. A value of 0 means instant. + + + + + + HOLD controls how long the envelope stays at peak after the attack phase. + + + + + + DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds it would take to go from peak to zero. The actual decay may be shorter if sustain is used. + + + + + + SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level as long as the note is held. + + + + + + REL, or release, controls how long the release is for the note, measured in how long it would take to fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. + + + + + + The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modulation amount + 調製量 + + + + MultitapEchoControlDialog + + + Length + 長度 + + + + Step length: + 步進長度: + + + + Dry + 幹聲 + + + + Dry Gain: + 幹聲增益: + + + + Stages + + + + + Lowpass stages: + + + + + Swap inputs + + + + + Swap left and right input channel for reflections + + + + + NesInstrument + + + Channel 1 Coarse detune + + + + + Channel 1 Volume + + + + + Channel 1 Envelope length + + + + + Channel 1 Duty cycle + + + + + Channel 1 Sweep amount + + + + + Channel 1 Sweep rate + + + + + Channel 2 Coarse detune + + + + + Channel 2 Volume + + + + + Channel 2 Envelope length + + + + + Channel 2 Duty cycle + + + + + Channel 2 Sweep amount + + + + + Channel 2 Sweep rate + + + + + Channel 3 Coarse detune + + + + + Channel 3 Volume + + + + + Channel 4 Volume + + + + + Channel 4 Envelope length + + + + + Channel 4 Noise frequency + + + + + Channel 4 Noise frequency sweep + + + + + Master volume + 主音量 + + + + Vibrato + + + + + NesInstrumentView + + + + + + Volume + 音量 + + + + + + Coarse detune + + + + + + + Envelope length + + + + + Enable channel 1 + + + + + Enable envelope 1 + + + + + Enable envelope 1 loop + + + + + Enable sweep 1 + + + + + + Sweep amount + + + + + + Sweep rate + + + + + + 12.5% Duty cycle + + + + + + 25% Duty cycle + + + + + + 50% Duty cycle + + + + + + 75% Duty cycle + + + + + Enable channel 2 + + + + + Enable envelope 2 + + + + + Enable envelope 2 loop + + + + + Enable sweep 2 + + + + + Enable channel 3 + + + + + Noise Frequency + + + + + Frequency sweep + + + + + Enable channel 4 + + + + + Enable envelope 4 + + + + + Enable envelope 4 loop + + + + + Quantize noise frequency when using note frequency + + + + + Use note frequency for noise + + + + + Noise mode + + + + + Master Volume + 主音量 + + + + Vibrato + + + + + OscillatorObject + + + Osc %1 waveform + Osc %1 波形 + + + + Osc %1 harmonic + + + + + + Osc %1 volume + Osc %1 音量 + + + + + Osc %1 panning + Osc %1 聲像 + + + + + Osc %1 fine detuning left + + + + + Osc %1 coarse detuning + + + + + Osc %1 fine detuning right + + + + + Osc %1 phase-offset + + + + + Osc %1 stereo phase-detuning + + + + + Osc %1 wave shape + + + + + Modulation type %1 + + + + + PatchesDialog + + + Qsynth: Channel Preset + Qsynth: 通道預設 + + + + Bank selector + 音色選擇器 + + + + Bank + + + + + Program selector + + + + + Patch + 音色 + + + + Name + 名稱 + + + + OK + 確定 + + + + Cancel + 取消 + + + + PatmanView + + + Open other patch + 打開其他音色 + + + + Click here to open another patch-file. Loop and Tune settings are not reset. + 點擊這裏打開另一個音色文件。循環和調音設置不會被重設。 + + + + Loop + 循環 + + + + Loop mode + 循環模式 + + + + Here you can toggle the Loop mode. If enabled, PatMan will use the loop information available in the file. + 在這裏你可以開關循環模式。如果啓用,PatMan 會使用文件中的循環信息。 + + + + Tune + 調音 + + + + Tune mode + 調音模式 + + + + Here you can toggle the Tune mode. If enabled, PatMan will tune the sample to match the note's frequency. + 這裏可以開關調音模式。如果啓用,PatMan 會將採樣調成和音符一樣的頻率。 + + + + No file selected + 未選擇檔案 + + + + Open patch file + 打開音色文件 + + + + Patch-Files (*.pat) + 音色文件 (*.pat) + + + + PatternView + + + use mouse wheel to set velocity of a step + + + + + double-click to open in Piano Roll + + + + + Open in piano-roll + 在鋼琴窗中打開 + + + + Clear all notes + 清除所有音符 + + + + Reset name + 重置名稱 + + + + Change name + 修改名稱 + + + + Add steps + 添加音階 + + + + Remove steps + 移除音階 + + + + Clone Steps + + + + + PeakController + + + Peak Controller + 峯值控制器 + + + + Peak Controller Bug + 峯值控制器 Bug + + + + Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. + 由於在舊版 LMMS 中的錯誤,峰值控制器可能並未正確地連線。請確認峰值控制器正確地連線後再次儲存檔案。造成您的不便,深感抱歉。 + + + + PeakControllerDialog + + + PEAK + + + + + LFO Controller + LFO 控制器 + + + + PeakControllerEffectControlDialog + + + BASE + 基準 + + + + Base amount: + 基礎值: + + + + AMNT + + + + + Modulation amount: + 調製量: + + + + MULT + + + + + Amount Multiplicator: + + + + + ATCK + 打擊 + + + + Attack: + 打擊聲: + + + + DCAY + + + + + Release: + 釋音: + + + + TRSH + + + + + Treshold: + + + + + PeakControllerEffectControls + + + Base value + 基準值 + + + + Modulation amount + 調製量 + + + + Attack + 打進聲 + + + + Release + 釋放 + + + + Treshold + 閥值 + + + + Mute output + 輸出靜音 + + + + Abs Value + + + + + Amount Multiplicator + + + + + PianoRoll + + + Note Velocity + 音符音量 + + + + Note Panning + 音符聲相偏移 + + + + Mark/unmark current semitone + 標記/取消標記當前半音 + + + + Mark/unmark all corresponding octave semitones + + + + + Mark current scale + + + + + Mark current chord + + + + + Unmark all + 取消標記所有 + + + + Select all notes on this key + 選中所有相同音調的音符 + + + + Note lock + 音符鎖定 + + + + Last note + 上一個音符 + + + + No scale + + + + + No chord + + + + + Velocity: %1% + 音量:%1% + + + + Panning: %1% left + 聲相:%1% 偏左 + + + + Panning: %1% right + 聲相:%1% 偏右 + + + + Panning: center + 聲相:居中 + + + + Please open a pattern by double-clicking on it! + 雙擊打開片段! + + + + + Please enter a new value between %1 and %2: + 請輸入一個介於 %1 和 %2 的值: + + + + PianoRollWindow + + + Play/pause current pattern (Space) + 播放/暫停當前片段(空格) + + + + Record notes from MIDI-device/channel-piano + 從 MIDI 設備/通道鋼琴(channel-piano) 錄製音符 + + + + Record notes from MIDI-device/channel-piano while playing song or BB track + + + + + Stop playing of current pattern (Space) + 停止當前片段(空格) + + + + Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. + + + + + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. + + + + + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. + + + + + Click here to stop playback of current pattern. + + + + + Edit actions + 編輯功能 + + + + Draw mode (Shift+D) + 繪製模式 (Shift+D) + + + + Erase mode (Shift+E) + 擦除模式 (Shift+E) + + + + Select mode (Shift+S) + 選擇模式 (Shift+S) + + + + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + + + + + Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. + 點擊啓用擦除模式。此模式下你可以擦除音符。你可以按鍵盤上的 'Shift+E' 啓用此模式。 + + + + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + + + + + Pitch Bend mode (Shift+T) + + + + + Click here and Pitch Bend mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + + + + + Quantize + + + + + Copy paste controls + + + + + Cut selected notes (%1+X) + 剪切選定音符 (%1+X) + + + + Copy selected notes (%1+C) + 複製選定音符 (%1+C) + + + + Paste notes from clipboard (%1+V) + 從剪貼板粘貼音符 (%1+V) + + + + Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + + + + + Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + + + + + Click here and the notes from the clipboard will be pasted at the first visible measure. + + + + + Timeline controls + 時間線控制 + + + + Zoom and note controls + + + + + This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. + + + + + The 'Q' stands for quantization, and controls the grid size notes and control points snap to. With smaller quantization values, you can draw shorter notes in Piano Roll, and more exact control points in the Automation Editor. + + + + + This lets you select the length of new notes. 'Last Note' means that LMMS will use the note length of the note you last edited + + + + + The feature is directly connected to the context-menu on the virtual keyboard, to the left in Piano Roll. After you have chosen the scale you want in this drop-down menu, you can right click on a desired key in the virtual keyboard, and then choose 'Mark current Scale'. LMMS will highlight all notes that belongs to the chosen scale, and in the key you have selected! + + + + + Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + + + + + + Piano-Roll - %1 + 鋼琴窗 - %1 + + + + + Piano-Roll - no pattern + 鋼琴窗 - 沒有片段 + + + + PianoView + + + Base note + 基本音 + + + + Plugin + + + Plugin not found + 未找到插件 + + + + The plugin "%1" wasn't found or could not be loaded! +Reason: "%2" + 插件“%1”無法找到或無法載入! +原因:%2 + + + + Error while loading plugin + 載入插件時發生錯誤 + + + + Failed to load plugin "%1"! + 載入插件“%1”失敗! + + + + PluginBrowser + + + Instrument Plugins + + + + + Instrument browser + 樂器瀏覽器 + + + + Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. + 將樂器插件拖入歌曲編輯器, 節拍低音線編輯器, 或者現有的樂器軌道。 + + + + PluginFactory + + + Plugin not found. + 未找到插件。 + + + + LMMS plugin %1 does not have a plugin descriptor named %2! + + + + + ProjectNotes + + + Project Notes + 顯示/隱藏工程註釋 + + + + Enter project notes here + + + + + Edit Actions + 編輯功能 + + + + &Undo + 撤銷(&U) + + + + %1+Z + %1+Z + + + + &Redo + 重做(&R) + + + + %1+Y + %1+Y + + + + &Copy + 複製(&C) + + + + %1+C + %1+C + + + + Cu&t + 剪切(&T) + + + + %1+X + %1+X + + + + &Paste + 粘貼(&P) + + + + %1+V + %1+V + + + + Format Actions + 格式功能 + + + + &Bold + 加粗(&B) + + + + %1+B + %1+B + + + + &Italic + 斜體(&I) + + + + %1+I + %1+I + + + + &Underline + 下劃線(&U) + + + + %1+U + %1+U + + + + &Left + 左對齊(&L) + + + + %1+L + %1+L + + + + C&enter + 居中(&E) + + + + %1+E + %1+E + + + + &Right + 右對齊(&R) + + + + %1+R + %1+R + + + + &Justify + 勻齊(&J) + + + + %1+J + %1+J + + + + &Color... + 顏色(&C)... + + + + ProjectRenderer + + + WAV-File (*.wav) + WAV-文件 (*.wav) + + + + Compressed OGG-File (*.ogg) + 壓縮的 OGG 文件(*.ogg) + + + FLAC-File (*.flac) + + + + + Compressed MP3-File (*.mp3) + + + + + QWidget + + + + + Name: + 名稱: + + + + + Maker: + 製作者: + + + + + Copyright: + 版權: + + + + + Requires Real Time: + 要求實時: + + + + + + + + + Yes + + + + + + + + + + No + + + + + + Real Time Capable: + 是否支持實時: + + + + + In Place Broken: + + + + + + Channels In: + 輸入通道: + + + + + Channels Out: + 輸出通道: + + + + File: %1 + 檔案:%1 + + + + File: + 檔案: + + + + RenameDialog + + + Rename... + 重命名... + + + + ReverbSCControlDialog + + + Input + 輸入 + + + + Input Gain: + 輸入增益: + + + + Size + + + + + Size: + + + + + Color + + + + + Color: + + + + + Output + 輸出 + + + + Output Gain: + 輸出增益: + + + + ReverbSCControls + + + Input Gain + + + + + Size + + + + + Color + + + + + Output Gain + + + + + SampleBuffer + + + Fail to open file + 無法開啟檔案 + + + + Audio files are limited to %1 MB in size and %2 minutes of playing time + 音訊檔案的檔案大小已限制為 %1 MB,播放時間已限制為 %2 分鐘。 + + + + Open audio file + 開啟音訊檔案 + + + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + 所有音訊檔案 (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + + + + Wave-Files (*.wav) + Wave 波形檔案 (*.wav) + + + + OGG-Files (*.ogg) + OGG 檔案 (*.ogg) + + + + DrumSynth-Files (*.ds) + DrumSynth 檔案 (*.ds) + + + + FLAC-Files (*.flac) + FLAC 檔案 (*.flac) + + + + SPEEX-Files (*.spx) + SPEEX 檔案 (*.spx) + + + + VOC-Files (*.voc) + VOC 檔案 (*.voc) + + + + AIFF-Files (*.aif *.aiff) + AIFF 檔案 (*.aif *.aiff) + + + + AU-Files (*.au) + AU 檔案 (*.au) + + + + RAW-Files (*.raw) + RAW 檔案 (*.raw) + + + + SampleTCOView + + + double-click to select sample + 雙擊選擇採樣 + + + + Delete (middle mousebutton) + 刪除 (鼠標中鍵) + + + + Cut + 剪切 + + + + Copy + 複製 + + + + Paste + 粘貼 + + + + Mute/unmute (<%1> + middle click) + 靜音/取消靜音 (<%1> + 鼠標中鍵) + + + + SampleTrack + + + Volume + 音量 + + + + Panning + 聲相 + + + + + Sample track + 採樣軌道 + + + + SampleTrackView + + + Track volume + 軌道音量 + + + + Channel volume: + 通道音量: + + + + VOL + VOL + + + + Panning + 聲相 + + + + Panning: + 聲相: + + + + PAN + PAN + + + + SetupDialog + + + Setup LMMS + 設置LMMS + + + + + General settings + 常規設置 + + + + BUFFER SIZE + 緩衝區大小 + + + + + Reset to default-value + 重置爲默認值 + + + + MISC + 雜項 + + + + Enable tooltips + 啓用工具提示 + + + + Show restart warning after changing settings + 在改變設置後顯示重啓警告 + + + + Display volume as dBFS + + + + + Compress project files per default + 預設壓縮專案檔 + + + + One instrument track window mode + 單樂器軌道窗口模式 + + + + HQ-mode for output audio-device + 對輸出設備使用高質量輸出 + + + + Compact track buttons + 緊湊化軌道圖標 + + + + Sync VST plugins to host playback + 同步 VST 插件和主機回放 + + + + Enable note labels in piano roll + 在鋼琴窗中顯示音號 + + + + Enable waveform display by default + 默認啓用波形圖 + + + + Keep effects running even without input + 在沒有輸入時也運行音頻效果 + + + + Create backup file when saving a project + 儲存專案時建立備份檔 + + + + Reopen last project on start + 啓動時打開最近的項目 + + + + Use built-in NaN handler + + + + + PLUGIN EMBEDDING + + + + + No embedding + + + + + Embed using Qt API + + + + + Embed using native Win32 API + + + + + Embed using XEmbed protocol + + + + + LANGUAGE + 語言 + + + + + Paths + 路徑 + + + + Directories + 目錄 + + + + LMMS working directory + LMMS工作目錄 + + + + Themes directory + 主題文件目錄 + + + + Background artwork + 背景圖片 + + + + VST-plugin directory + VST插件目錄 + + + + GIG directory + GIG 目錄 + + + + SF2 directory + SF2 目錄 + + + + LADSPA plugin directories + LADSPA 插件目錄 + + + + STK rawwave directory + STK rawwave 目錄 + + + + Default Soundfont File + 預設 SoundFont 檔案 + + + + + Performance settings + 性能設置 + + + + Auto save + 自動保存 + + + + Enable auto-save + + + + + Allow auto-save while playing + + + + + UI effects vs. performance + 界面特效 vs 性能 + + + + Smooth scroll in Song Editor + 歌曲編輯器中啓用平滑滾動 + + + + Show playback cursor in AudioFileProcessor + 在 AudioFileProcessor 中顯示播放指標 + + + + + Audio settings + 音頻設置 + + + + AUDIO INTERFACE + 音頻接口 + + + + + MIDI settings + MIDI設置 + + + + MIDI INTERFACE + MIDI接口 + + + + OK + 確定 + + + + Cancel + 取消 + + + + Restart LMMS + 重啓LMMS + + + + Please note that most changes won't take effect until you restart LMMS! + 請注意很多設置需要重啓LMMS纔可生效! + + + + Frames: %1 +Latency: %2 ms + 幀數: %1 +延遲: %2 毫秒 + + + + Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. + 在這裏,你可以設置 LMMS 所用緩衝區的大小。緩衝區越小,延遲越小,但聲音質量和性能可能會受影響。 + + + + Choose LMMS working directory + 選擇 LMMS 工作目錄 + + + + Choose your GIG directory + 選擇 GIG 目錄 + + + + Choose your SF2 directory + 選擇 SF2 目錄 + + + + Choose your VST-plugin directory + 選擇 VST 插件目錄 + + + + Choose artwork-theme directory + 選擇插圖目錄 + + + + Choose LADSPA plugin directory + 選擇 LADSPA 插件目錄 + + + + Choose STK rawwave directory + 選擇 STK rawwave 目錄 + + + + Choose default SoundFont + 選擇默認的 SoundFont + + + + Choose background artwork + 選擇背景圖片 + + + + minutes + 分鐘 + + + + minute + 分鐘 + + + + Disabled + + + + + Auto-save interval: %1 + + + + + Set the time between automatic backup to %1. +Remember to also save your project manually. You can choose to disable saving while playing, something some older systems find difficult. + + + + + Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. + 在這裏你可以選擇你想要的音頻接口。取決於你的系統和編譯時的設置, 你可以選擇 ALSA, JACK, OSS 等選項。在下面的方框中你可以設置音頻接口的控制項目。 + + + + Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. + 在這裏你可以選擇你想要的 MIDI 接口。取決於你的系統和編譯時的設置, 你可以選擇 ALSA, OSS 等選項。在下面的方框中你可以設置 MIDI 接口的控制項目。 + + + + Song + + + Tempo + 節奏 + + + + Master volume + 主音量 + + + + Master pitch + 主音高 + + + + LMMS Error report + LMMS錯誤報告 + + + + Project saved + 工程已保存 + + + + The project %1 is now saved. + 工程 %1 已保存。 + + + + Project NOT saved. + 工程 **沒有** 保存。 + + + + The project %1 was not saved! + 工程%1沒有保存! + + + + Import file + 匯入檔案 + + + + MIDI sequences + MIDI 音序器 + + + + Hydrogen projects + Hydrogen工程 + + + + All file types + 所有檔案類型 + + + + + Empty project + 空工程 + + + + + This project is empty so exporting makes no sense. Please put some items into Song Editor first! + 這個工程是空的所以就算導出也沒有意義,請在歌曲編輯器中加入一點聲音吧! + + + + Select directory for writing exported tracks... + 選擇寫入導出音軌的目錄... + + + + + untitled + 未命名 + + + + + Select file for project-export... + 匯出專案至… + + + + Save project + + + + + MIDI File (*.mid) + MIDI 檔案 (*.mid) + + + + The following errors occured while loading: + 載入時發生以下錯誤: + + + + SongEditor + + + Could not open file + 無法開啟檔案 + + + + Could not open file %1. You probably have no permissions to read this file. + Please make sure to have at least read permissions to the file and try again. + 無法開啟 %1。 +請確認您至少有權限讀取此檔案後再試一次。 + + + + Could not write file + 無法寫入檔案 + + + + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. + 無法開啟 %1 以進行寫入。請確認您有權限寫入此檔案後再試一次。 + + + + Error in file + 於檔案中發現錯誤 + + + + The file %1 seems to contain errors and therefore can't be loaded. + 檔案 %1 似乎包含錯誤,無法進行載入。 + + + + Version difference + + + + + This %1 was created with LMMS %2. + + + + + template + + + + + project + + + + + Tempo + 節奏 + + + + TEMPO/BPM + 節奏/BPM + + + + tempo of song + 歌曲的節奏 + + + + The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). + + + + + High quality mode + 高質量模式 + + + + + Master volume + 主音量 + + + + master volume + 主音量 + + + + + Master pitch + 主音高 + + + + master pitch + 主音高 + + + + Value: %1% + 值: %1% + + + + Value: %1 semitones + 值: %1 半音程 + + + + SongEditorWindow + + + Song-Editor + 歌曲編輯器 + + + + Play song (Space) + 播放歌曲(空格) + + + + Record samples from Audio-device + 從音頻設備錄製樣本 + + + + Record samples from Audio-device while playing song or BB track + 在播放歌曲或BB軌道時從音頻設備錄入樣本 + + + + Stop song (Space) + 停止歌曲(空格) + + + + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. + 點擊這裏完整播放歌曲。將從綠色歌曲標記開始播放。在播放的同時可以對它進行移動。 + + + + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. + 點擊這裏停止播放,歌曲位置標記會跳到歌曲的開頭。 + + + + Track actions + 軌道動作 + + + + Add beat/bassline + 添加節拍/Bassline + + + + Add sample-track + 添加採樣軌道 + + + + Add automation-track + 添加自動控制軌道 + + + + Edit actions + 編輯動作 + + + + Draw mode + 繪製模式 + + + + Edit mode (select and move) + 編輯模式(選定和移動) + + + + Timeline controls + 時間線控制 + + + + Zoom controls + 縮放控制 + + + + SpectrumAnalyzerControlDialog + + + Linear spectrum + 線性頻譜圖 + + + + Linear Y axis + 線性 Y 軸 + + + + SpectrumAnalyzerControls + + + Linear spectrum + 線性頻譜圖 + + + + Linear Y axis + 線性 Y 軸 + + + + Channel mode + 通道模式 + + + + SubWindow + + + Close + + + + + Maximize + + + + + Restore + + + + + TabWidget + + + + Settings for %1 + %1 的設定 + + + + TempoSyncKnob + + + + Tempo Sync + + + + + No Sync + 無同步 + + + + Eight beats + + + + + Whole note + + + + + Half note + + + + + Quarter note + + + + + 8th note + + + + + 16th note + + + + + 32nd note + + + + + Custom... + + + + + Custom + + + + + Synced to Eight Beats + + + + + Synced to Whole Note + + + + + Synced to Half Note + + + + + Synced to Quarter Note + + + + + Synced to 8th Note + + + + + Synced to 16th Note + + + + + Synced to 32nd Note + + + + + TimeDisplayWidget + + + click to change time units + 點擊改變時間單位 + + + + MIN + + + + + SEC + + + + + MSEC + + + + + BAR + + + + + BEAT + + + + + TICK + + + + + TimeLineWidget + + + Enable/disable auto-scrolling + 啓用/禁用自動滾動 + + + + Enable/disable loop-points + 啓用/禁用循環點 + + + + After stopping go back to begin + 停止後前往開頭 + + + + After stopping go back to position at which playing was started + 停止後前往播放開始的地方 + + + + After stopping keep position + 停止後保持位置不變 + + + + + Hint + 提示 + + + + Press <%1> to disable magnetic loop points. + 按住 <%1> 禁用磁性吸附。 + + + + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + 按住 <Shift> 移動起始循環點;按住 <%1> 禁用磁性吸附。 + + + + Track + + + Mute + 靜音 + + + + Solo + 獨奏 + + + + TrackContainer + + + Couldn't import file + 無法匯入檔案 + + + + Couldn't find a filter for importing file %1. +You should convert this file into a format supported by LMMS using another software. + 不支援 %1 的檔案類型。 +請使用其他軟體將此檔案轉換成 LMMS 支援的格式。 + + + + Couldn't open file + 無法開啟檔案 + + + + Couldn't open file %1 for reading. +Please make sure you have read-permission to the file and the directory containing the file and try again! + 無法開啟 %1。 +請確認您有權限讀取此檔案,以及包含此檔案的目錄後再試一次。 + + + + Loading project... + 正在加載工程... + + + + + Cancel + 取消 + + + + + Please wait... + 請稍等... + + + + Loading cancelled + + + + + Project loading was cancelled. + + + + + Loading Track %1 (%2/Total %3) + + + + + Importing MIDI-file... + 正在匯入 MIDI 檔案… + + + + TrackContentObject + + + Mute + 靜音 + + + + TrackContentObjectView + + + Current position + 當前位置 + + + + + Hint + 提示 + + + + Press <%1> and drag to make a copy. + 按住 <%1> 並拖動以創建副本。 + + + + Current length + 當前長度 + + + + Press <%1> for free resizing. + 按住 <%1> 自由調整大小。 + + + + + %1:%2 (%3:%4 to %5:%6) + %1:%2 (%3:%4 到 %5:%6) + + + + Delete (middle mousebutton) + 刪除 (鼠標中鍵) + + + + Cut + 剪切 + + + + Copy + 複製 + + + + Paste + 粘貼 + + + + Mute/unmute (<%1> + middle click) + 靜音/取消靜音 (<%1> + 鼠標中鍵) + + + + TrackOperationsWidget + + + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + + + + + Actions for this track + + + + + Mute + 靜音 + + + + + Solo + 獨奏 + + + + Mute this track + + + + + Clone this track + + + + + Remove this track + + + + + Clear this track + + + + + FX %1: %2 + 效果 %1: %2 + + + + Assign to new FX Channel + + + + + Turn all recording on + + + + + Turn all recording off + + + + + TripleOscillatorView + + + Use phase modulation for modulating oscillator 1 with oscillator 2 + + + + + Use amplitude modulation for modulating oscillator 1 with oscillator 2 + + + + + Mix output of oscillator 1 & 2 + + + + + Synchronize oscillator 1 with oscillator 2 + + + + + Use frequency modulation for modulating oscillator 1 with oscillator 2 + + + + + Use phase modulation for modulating oscillator 2 with oscillator 3 + + + + + Use amplitude modulation for modulating oscillator 2 with oscillator 3 + + + + + Mix output of oscillator 2 & 3 + + + + + Synchronize oscillator 2 with oscillator 3 + + + + + Use frequency modulation for modulating oscillator 2 with oscillator 3 + + + + + Osc %1 volume: + + + + + With this knob you can set the volume of oscillator %1. When setting a value of 0 the oscillator is turned off. Otherwise you can hear the oscillator as loud as you set it here. + + + + + Osc %1 panning: + + + + + With this knob you can set the panning of the oscillator %1. A value of -100 means 100% left and a value of 100 moves oscillator-output right. + + + + + Osc %1 coarse detuning: + + + + + semitones + + + + + With this knob you can set the coarse detuning of oscillator %1. You can detune the oscillator 24 semitones (2 octaves) up and down. This is useful for creating sounds with a chord. + + + + + Osc %1 fine detuning left: + + + + + + cents + 音分 cents + + + + With this knob you can set the fine detuning of oscillator %1 for the left channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + + + + + Osc %1 fine detuning right: + + + + + With this knob you can set the fine detuning of oscillator %1 for the right channel. The fine-detuning is ranged between -100 cents and +100 cents. This is useful for creating "fat" sounds. + + + + + Osc %1 phase-offset: + + + + + + degrees + + + + + With this knob you can set the phase-offset of oscillator %1. That means you can move the point within an oscillation where the oscillator begins to oscillate. For example if you have a sine-wave and have a phase-offset of 180 degrees the wave will first go down. It's the same with a square-wave. + + + + + Osc %1 stereo phase-detuning: + + + + + With this knob you can set the stereo phase-detuning of oscillator %1. The stereo phase-detuning specifies the size of the difference between the phase-offset of left and right channel. This is very good for creating wide stereo sounds. + + + + + Use a sine-wave for current oscillator. + 爲當前振盪器使用正弦波。 + + + + Use a triangle-wave for current oscillator. + 爲當前振盪器使用三角波。 + + + + Use a saw-wave for current oscillator. + 爲當前振盪器使用鋸齒波。 + + + + Use a square-wave for current oscillator. + 爲當前振盪器使用方波。 + + + + Use a moog-like saw-wave for current oscillator. + + + + + Use an exponential wave for current oscillator. + + + + + Use white-noise for current oscillator. + 爲當前振盪器使用白噪音。 + + + + Use a user-defined waveform for current oscillator. + 爲當前振盪器使用用戶自定波形。 + + + + VersionedSaveDialog + + + Increment version number + 遞增版本號 + + + + Decrement version number + 遞減版本號 + + + + already exists. Do you want to replace it? + + + + + VestigeInstrumentView + + + Open other VST-plugin + 打開其他的VST插件 + + + + Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. + + + + + Control VST-plugin from LMMS host + 從 LMMS 宿主控制 VST-插件 + + + + Click here, if you want to control VST-plugin from host. + + + + + Open VST-plugin preset + 打開 VST-插件預設 + + + + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + + + + + Previous (-) + 上一個 (-) + + + + + Click here, if you want to switch to another VST-plugin preset program. + + + + + Save preset + 保存預置 + + + + Click here, if you want to save current VST-plugin preset program. + 點擊這裏, 如果你想保存當前 VST-插件預設。 + + + + Next (+) + 下一個 (+) + + + + Click here to select presets that are currently loaded in VST. + + + + + Show/hide GUI + 顯示/隱藏界面 + + + + Click here to show or hide the graphical user interface (GUI) of your VST-plugin. + 點此顯示/隱藏VST插件的界面。 + + + + Turn off all notes + 全部靜音 + + + + Open VST-plugin + 打開VST插件 + + + + DLL-files (*.dll) + DLL 檔案 (*.dll) + + + + EXE-files (*.exe) + EXE 檔案 (*.exe) + + + + No VST-plugin loaded + 未載入VST插件 + + + + Preset + 預置 + + + + by + + + + + - VST plugin control + - VST插件控制 + + + + VisualizationWidget + + + click to enable/disable visualization of master-output + 點擊啓用/禁用視覺化主輸出 + + + + Click to enable + 點擊啓用 + + + + VstEffectControlDialog + + + Show/hide + 顯示/隱藏 + + + + Control VST-plugin from LMMS host + 從 LMMS 宿主控制 VST-插件 + + + + Click here, if you want to control VST-plugin from host. + + + + + Open VST-plugin preset + 打開 VST-插件預設 + + + + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + + + + + Previous (-) + 上一個 (-) + + + + + Click here, if you want to switch to another VST-plugin preset program. + + + + + Next (+) + 下一個 (+) + + + + Click here to select presets that are currently loaded in VST. + + + + + Save preset + 保存預置 + + + + Click here, if you want to save current VST-plugin preset program. + 點擊這裏, 如果你想保存當前 VST-插件預設。 + + + + + Effect by: + + + + + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> + + + + + VstPlugin + + + + The VST plugin %1 could not be loaded. + 無法載入VST插件 %1。 + + + + Open Preset + 打開預置 + + + + + Vst Plugin Preset (*.fxp *.fxb) + VST插件預置文件(*.fxp *.fxb) + + + + : default + : 默認 + + + + " + " + + + + ' + ' + + + + Save Preset + 保存預置 + + + + .fxp + .fxp + + + + .FXP + .FXP + + + + .FXB + .FXB + + + + .fxb + .fxb + + + + Loading plugin + 載入插件 + + + + Please wait while loading VST plugin... + 正在載入VST插件,請稍候…… + + + + WatsynInstrument + + + Volume A1 + + + + + Volume A2 + + + + + Volume B1 + + + + + Volume B2 + + + + + Panning A1 + + + + + Panning A2 + + + + + Panning B1 + + + + + Panning B2 + + + + + Freq. multiplier A1 + + + + + Freq. multiplier A2 + + + + + Freq. multiplier B1 + + + + + Freq. multiplier B2 + + + + + Left detune A1 + + + + + Left detune A2 + + + + + Left detune B1 + + + + + Left detune B2 + + + + + Right detune A1 + + + + + Right detune A2 + + + + + Right detune B1 + + + + + Right detune B2 + + + + + A-B Mix + + + + + A-B Mix envelope amount + + + + + A-B Mix envelope attack + + + + + A-B Mix envelope hold + + + + + A-B Mix envelope decay + + + + + A1-B2 Crosstalk + + + + + A2-A1 modulation + + + + + B2-B1 modulation + + + + + Selected graph + + + + + WatsynView + + + + + + Volume + 音量 + + + + + + + Panning + 聲相 + + + + + + + Freq. multiplier + + + + + + + + Left detune + + + + + + + + + + + + cents + + + + + + + + Right detune + + + + + A-B Mix + + + + + Mix envelope amount + + + + + Mix envelope attack + + + + + Mix envelope hold + + + + + Mix envelope decay + + + + + Crosstalk + + + + + Select oscillator A1 + + + + + Select oscillator A2 + + + + + Select oscillator B1 + + + + + Select oscillator B2 + + + + + Mix output of A2 to A1 + + + + + Modulate amplitude of A1 with output of A2 + + + + + Ring-modulate A1 and A2 + + + + + Modulate phase of A1 with output of A2 + + + + + Mix output of B2 to B1 + + + + + Modulate amplitude of B1 with output of B2 + + + + + Ring-modulate B1 and B2 + + + + + Modulate phase of B1 with output of B2 + + + + + + + + Draw your own waveform here by dragging your mouse on this graph. + + + + + Load waveform + 載入波形 + + + + Click to load a waveform from a sample file + + + + + Phase left + + + + + Click to shift phase by -15 degrees + + + + + Phase right + + + + + Click to shift phase by +15 degrees + + + + + Normalize + 標準化 + + + + Click to normalize + + + + + Invert + 反轉 + + + + Click to invert + + + + + Smooth + 平滑 + + + + Click to smooth + + + + + Sine wave + 正弦波 + + + + Click for sine wave + + + + + + Triangle wave + 三角波 + + + + Click for triangle wave + + + + + Click for saw wave + + + + + Square wave + 方波 + + + + Click for square wave + + + + + ZynAddSubFxInstrument + + + Portamento + + + + + Filter Frequency + + + + + Filter Resonance + + + + + Bandwidth + 帶寬 + + + + FM Gain + FM 增益 + + + + Resonance Center Frequency + + + + + Resonance Bandwidth + + + + + Forward MIDI Control Change Events + + + + + ZynAddSubFxView + + + Portamento: + + + + + PORT + + + + + Filter Frequency: + + + + + FREQ + 頻率 + + + + Filter Resonance: + + + + + RES + + + + + Bandwidth: + 帶寬: + + + + BW + + + + + FM Gain: + + + + + FM GAIN + + + + + Resonance center frequency: + + + + + RES CF + + + + + Resonance bandwidth: + + + + + RES BW + + + + + Forward MIDI Control Changes + + + + + Show GUI + 顯示圖形界面 + + + + Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + + + + + audioFileProcessor + + + Amplify + 增益 + + + + Start of sample + 採樣起始 + + + + End of sample + 採樣結尾 + + + + Loopback point 循環點 - Loop mode - 循環模式 + + Reverse sample + 反轉採樣 + + + + Loop mode + 循環模式 + + + + Stutter + + + + + Interpolation mode + 補間方式 + + + + None + + + + + Linear + 線性插補 + + + + Sinc + 辛格(Sinc)插補 + + + + Sample not found: %1 + 採樣未找到: %1 + + + + bitInvader + + + Samplelength + 採樣長度 + + + + bitInvaderView + + + Sample Length + 採樣長度 + + + + Draw your own waveform here by dragging your mouse on this graph. + + + + + Sine wave + 正弦波 + + + + Click for a sine-wave. + + + + + Triangle wave + 三角波 + + + + Click here for a triangle-wave. + 點擊這裡使用三角波。 + + + + Saw wave + 鋸齒波 + + + + Click here for a saw-wave. + + + + + Square wave + 方波 + + + + Click here for a square-wave. + 點擊這裡使用方形波。 + + + + White noise wave + 白噪音 + + + + Click here for white-noise. + + + + + User defined wave + 用戶自定義波形 + + + + Click here for a user-defined shape. + + + + + Smooth + 平滑 + + + + Click here to smooth waveform. + 點擊這裏平滑波形。 + + + + Interpolation + + + + + Normalize + 標準化 + + + + dynProcControlDialog + + + INPUT + 輸入 + + + + Input gain: + 輸入增益: + + + + OUTPUT + 輸出 + + + + Output gain: + 輸出增益: + + + + ATTACK + + + + + Peak attack time: + + + + + RELEASE + + + + + Peak release time: + + + + + Reset waveform + 重置波形 + + + + Click here to reset the wavegraph back to default + + + + + Smooth waveform + 平滑波形 + + + + Click here to apply smoothing to wavegraph + 點擊這裏來使波形圖更爲平滑 + + + + Increase wavegraph amplitude by 1dB + + + + + Click here to increase wavegraph amplitude by 1dB + + + + + Decrease wavegraph amplitude by 1dB + + + + + Click here to decrease wavegraph amplitude by 1dB + + + + + Stereomode Maximum + + + + + Process based on the maximum of both stereo channels + + + + + Stereomode Average + + + + + Process based on the average of both stereo channels + + + + + Stereomode Unlinked + + + + + Process each stereo channel independently + + + + + dynProcControls + + + Input gain + 輸入增益 + + + + Output gain + 輸出增益 + + + + Attack time + + + + + Release time + + + + + Stereo mode + + + + + expressiveView + + Select oscillator W1 + + + + Select oscillator W2 + + + + Select oscillator W3 + + + + Select OUTPUT 1 + + + + Select OUTPUT 2 + + + + Open help window + + + + Sine wave + 正弦波 + + + Click for a sine-wave. + + + + Moog-Saw wave + + + + Click for a Moog-Saw-wave. + + + + Exponential wave + + + + Click for an exponential wave. + + + + Saw wave + 鋸齒波 + + + Click here for a saw-wave. + + + + User defined wave + 用戶自定義波形 + + + Click here for a user-defined shape. + + + + Triangle wave + 三角波 + + + Click here for a triangle-wave. + 點擊這裡使用三角波。 + + + Square wave + 方波 + + + Click here for a square-wave. + 點擊這裡使用方形波。 + + + White noise wave + 白噪音 + + + Click here for white-noise. + + + + WaveInterpolate + + + + ExpressionValid + + + + General purpose 1: + + + + General purpose 2: + + + + General purpose 3: + + + + O1 panning: + + + + O2 panning: + + + + Release transition: + + + + Smoothness + + + + + fxLineLcdSpinBox + + + Assign to: + 分配給: + + + + New FX Channel + 新的效果通道 + + + + graphModel + + + Graph + 圖形 + + + + kickerInstrument + + + Start frequency + 起始頻率 + + + + End frequency + 結束頻率 + + + + Length + 長度 + + + + Distortion Start + 起始失真度 + + + + Distortion End + 結束失真度 + + + + Gain + 增益 + + + + Envelope Slope + 包絡線傾斜度 + + + + Noise + 噪音 + + + + Click + 力度 + + + + Frequency Slope + 頻率傾斜度 + + + + Start from note + 從哪個音符開始 + + + + End to note + 到哪個音符結束 + + + + kickerInstrumentView + + + Start frequency: + 起始頻率: + + + + End frequency: + 結束頻率: + + + + Frequency Slope: + 頻率傾斜度: + + + + Gain: + 增益: + + + + Envelope Length: + 包絡長度: + + + + Envelope Slope: + 包絡線傾斜度: + + + + Click: + 力度: + + + + Noise: + 噪音: + + + + Distortion Start: + 起始失真度: + + + + Distortion End: + 結束失真度: + + + + ladspaBrowserView + + + + Available Effects + 可用效果器 + + + + + Unavailable Effects + 不可用效果器 + + + + + Instruments + 樂器插件 + + + + + Analysis Tools + 分析工具 + + + + + Don't know + 未知 + + + + This dialog displays information on all of the LADSPA plugins LMMS was able to locate. The plugins are divided into five categories based upon an interpretation of the port types and names. + +Available Effects are those that can be used by LMMS. In order for LMMS to be able to use an effect, it must, first and foremost, be an effect, which is to say, it has to have both input channels and output channels. LMMS identifies an input channel as an audio rate port containing 'in' in the name. Output channels are identified by the letters 'out'. Furthermore, the effect must have the same number of inputs and outputs and be real time capable. + +Unavailable Effects are those that were identified as effects, but either didn't have the same number of input and output channels or weren't real time capable. + +Instruments are plugins for which only output channels were identified. + +Analysis Tools are plugins for which only input channels were identified. + +Don't Knows are plugins for which no input or output channels were identified. + +Double clicking any of the plugins will bring up information on the ports. + 這個對話框顯示 LMMS 找到的所有 LADSPA 插件信息。這些插件根據接口類型和名字被分爲五個類別。 + +"可用效果" 是指可以被 LMMS 使用的插件。爲了讓 LMMS 可以開啓效果, 首先, 這個插件需要是有效果的。也就是說, 這個插件需要有輸入和輸出通道。LMMS 會將音頻接口名稱中有 ‘in’ 的接口識別爲輸入接口, 將音頻接口名稱中有 ‘out’ 的接口識別爲輸出接口。並且, 效果插件需要有相同的輸入輸出通道, 還要能支持實時處理。 + +"不可用效果" 是指被識別爲效果插件的插件, 但是輸入輸出通道數不同或者不支持實時音頻處理。 + +"樂器" 是指只檢測到有輸出通道的插件。 + +"分析工具" 是指只檢測到有輸入通道的插件。 + +"未知" 是指沒有檢測到任何輸出或輸出通道的插件。 + +雙擊任意插件將會顯示接口信息。 + + + + Type: + 類型: + + + + ladspaDescription + + + Plugins + 插件 + + + + Description + 描述 + + + + ladspaPortDialog + + + Ports + + + + + Name + 名稱 + + + + Rate + + + + + Direction + 方向 + + + + Type + 類型 + + + + Min < Default < Max + 最小 < 默認 < 最大 + + + + Logarithmic + 對數 + + + + SR Dependent + + + + + Audio + 音頻 + + + + Control + 控制 + + + + Input + 輸入 + + + + Output + 輸出 + + + + Toggled + + + + + Integer + 整型 + + + + Float + 浮點 + + + + + Yes + + + + + lb302Synth + + + VCF Cutoff Frequency + + + + + VCF Resonance + + + + + VCF Envelope Mod + - Interpolation mode - 補間方式 + + VCF Envelope Decay + - None - + + Distortion + 失真 - Linear - 線性插補 + + Waveform + 波形 - Sinc - 辛格(Sinc)插補 + + Slide Decay + - Sample not found: %1 - 採樣未找到: %1 + + Slide + + + + + Accent + - - - bitInvader - Sample length - + + Dead + + + + + 24dB/oct Filter + - bitInvaderView + lb302SynthView - Sine wave - 正弦波 + + Cutoff Freq: + - Triangle wave - 三角波 + + Resonance: + 共鳴: + + + + Env Mod: + + + + + Decay: + 衰減: + + 303-es-que, 24dB/octave, 3 pole filter + + + + + Slide Decay: + + + + + DIST: + + + + Saw wave 鋸齒波 + + Click here for a saw-wave. + + + + + Triangle wave + 三角波 + + + + Click here for a triangle-wave. + 點擊這裡使用三角波。 + + + Square wave 方波 - Interpolation - + + Click here for a square-wave. + 點擊這裡使用方形波。 - Normalize - 標準化 + + Rounded square wave + - Draw your own waveform here by dragging your mouse on this graph. - + + Click here for a square-wave with a rounded end. + - Sample length - + + Moog wave + - White noise - + + Click here for a moog-like wave. + - User-defined wave - + + Sine wave + 正弦波 - Smooth waveform - 平滑波形 + + Click for a sine-wave. + - - - dynProcControlDialog - INPUT - 輸入 + + + White noise wave + 白噪音 - Input gain: - 輸入增益: + + Click here for an exponential wave. + - OUTPUT - 輸出 + + Click here for white-noise. + - Output gain: - 輸出增益: + + Bandlimited saw wave + - ATTACK - + + Click here for bandlimited saw wave. + - Peak attack time: - + + Bandlimited square wave + - RELEASE - + + Click here for bandlimited square wave. + - Peak release time: - + + Bandlimited triangle wave + - Process based on the maximum of both stereo channels - + + Click here for bandlimited triangle wave. + - Process based on the average of both stereo channels - + + Bandlimited moog saw wave + - Process each stereo channel independently - + + Click here for bandlimited moog saw wave. + + + + malletsInstrument - Reset wavegraph - + + Hardness + - Smooth wavegraph - + + Position + - Increase wavegraph amplitude by 1 dB - + + Vibrato Gain + - Decrease wavegraph amplitude by 1 dB - + + Vibrato Freq + - Stereo mode: maximum - + + Stick Mix + - Stereo mode: average - + + Modulator + - Stereo mode: unlinked - + + Crossfade + - - - dynProcControls - Input gain - 輸入增益 + + LFO Speed + - Output gain - 輸出增益 + + LFO Depth + - Attack time - + + ADSR + - Release time - + + Pressure + - Stereo mode - + + Motion + - - - kickerInstrument - Start frequency - 起始頻率 + + Speed + - End frequency - 結束頻率 + + Bowed + - Gain - 增益 + + Spread + - Length - 長度 + + Marimba + - Noise - 噪音 + + Vibraphone + - Click - 力度 + + Agogo + - Start from note - 從哪個音符開始 + + Wood1 + - End to note - 到哪個音符結束 + + Reso + + + + + Wood2 + + + + + Beats + + + + + Two Fixed + + + + + Clump + + + + + Tubular Bells + - Start distortion - + + Uniform Bar + - End distortion - + + Tuned Bar + - Envelope slope - + + Glass + - Frequency slope - + + Tibetan Bowl + - kickerInstrumentView + malletsInstrumentView - Start frequency: - 起始頻率: + + Instrument + - End frequency: - 結束頻率: + + Spread + - Gain: - 增益: + + Spread: + - Click: - 力度: + + Missing files + 檔案遺失 - Noise: - 噪音: + + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! + + + + + Hardness + - Frequency slope: - + + Hardness: + - Envelope length: - + + Position + - Envelope slope: - + + Position: + - Start distortion: - + + Vib Gain + - End distortion: - + + Vib Gain: + - - - ladspaBrowserView - Available Effects - 可用效果器 + + Vib Freq + - Unavailable Effects - 不可用效果器 + + Vib Freq: + - Instruments - 樂器插件 + + Stick Mix + - Analysis Tools - 分析工具 + + Stick Mix: + - Don't know - 未知 + + Modulator + - Type: - 類型: + + Modulator: + - - - ladspaDescription - Plugins - 插件 + + Crossfade + - Description - 描述 + + Crossfade: + - - - ladspaPortDialog - Ports - + + LFO Speed + - Name - 名稱 + + LFO Speed: + - Rate - + + LFO Depth + - Direction - 方向 + + LFO Depth: + - Type - 類型 + + ADSR + - Min < Default < Max - 最小 < 默認 < 最大 + + ADSR: + - Logarithmic - 對數 + + Pressure + - SR Dependent - + + Pressure: + - Audio - 音頻 + + Speed + - Control - 控制 + + Speed: + + + + + manageVSTEffectView + + + - VST parameter control + - VST 參數控制 - Input - 輸入 + + VST Sync + VST 同步 - Output - 輸出 + + Click here if you want to synchronize all parameters with VST plugin. + 點擊這裏, 如果你想與 VST 插件同步所有參數。 - Toggled - + + + Automated + 自動 - Integer - 整型 + + Click here if you want to display automated parameters only. + - Float - 浮點 + + Close + 關閉 - Yes - + + Close VST effect knob-controller window. + - lb302Synth + manageVestigeInstrumentView - VCF Cutoff Frequency - + + + - VST plugin control + - VST插件控制 - VCF Resonance - + + VST Sync + VST 同步 - VCF Envelope Mod - + + Click here if you want to synchronize all parameters with VST plugin. + 點擊這裏, 如果你想與 VST 插件同步所有參數。 - VCF Envelope Decay - + + + Automated + 自動 - Distortion - 失真 + + Click here if you want to display automated parameters only. + - Waveform - 波形 + + Close + 關閉 - Slide Decay - + + Close VST plugin knob-controller window. + + + + opl2instrument - Slide - + + Patch + 音色 - Accent - + + Op 1 Attack + - Dead - + + Op 1 Decay + - 24dB/oct Filter - + + Op 1 Sustain + - - - lb302SynthView - Cutoff Freq: - + + Op 1 Release + - Resonance: - 共鳴: + + Op 1 Level + - Env Mod: - + + Op 1 Level Scaling + - Decay: - 衰減: + + Op 1 Frequency Multiple + - 303-es-que, 24dB/octave, 3 pole filter - + + Op 1 Feedback + - Slide Decay: - + + Op 1 Key Scaling Rate + - DIST: - + + Op 1 Percussive Envelope + - Saw wave - 鋸齒波 + + Op 1 Tremolo + - Click here for a saw-wave. - + + Op 1 Vibrato + - Triangle wave - 三角波 + + Op 1 Waveform + - Click here for a triangle-wave. - 點擊這裡使用三角波。 + + Op 2 Attack + - Square wave - 方波 + + Op 2 Decay + - Click here for a square-wave. - 點擊這裡使用方形波。 + + Op 2 Sustain + - Rounded square wave - + + Op 2 Release + - Click here for a square-wave with a rounded end. - + + Op 2 Level + - Moog wave - + + Op 2 Level Scaling + - Click here for a moog-like wave. - + + Op 2 Frequency Multiple + - Sine wave - 正弦波 + + Op 2 Key Scaling Rate + - Click for a sine-wave. - + + Op 2 Percussive Envelope + - White noise wave - 白噪音 + + Op 2 Tremolo + - Click here for an exponential wave. - + + Op 2 Vibrato + - Click here for white-noise. - + + Op 2 Waveform + - Bandlimited saw wave - + + FM + - Click here for bandlimited saw wave. - + + Vibrato Depth + - Bandlimited square wave - + + Tremolo Depth + + + + opl2instrumentView - Click here for bandlimited square wave. - + + + Attack + 打進聲 - Bandlimited triangle wave - + + + Decay + 衰減 - Click here for bandlimited triangle wave. - + + + Release + 釋放 - Bandlimited moog saw wave - + + + Frequency multiplier + + + + + organicInstrument + + + Distortion + 失真 - Click here for bandlimited moog saw wave. - + + Volume + 音量 - malletsInstrument + organicInstrumentView - Hardness - + + Distortion: + 失真: - Position - + + The distortion knob adds distortion to the output of the instrument. + - Modulator - + + Volume: + 音量: - Crossfade - + + The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. + - ADSR - + + Randomise + 隨機 - Pressure - + + The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. + - Motion - + + + Osc %1 waveform: + - Speed - + + Osc %1 volume: + - Bowed - + + Osc %1 panning: + - Spread - + + Osc %1 stereo detuning + - Marimba - + + cents + 音分 cents - Vibraphone - + + Osc %1 harmonic: + + + + FreeBoyInstrument - Agogo - + + Sweep time + - Reso - + + Sweep direction + - Beats - + + Sweep RtShift amount + - Clump - + + + Wave Pattern Duty + - Glass - + + Channel 1 volume + - Vibrato gain - + + + + Volume sweep direction + - Vibrato frequency - + + + + Length of each step in sweep + - Stick mix - + + Channel 2 volume + - LFO speed - LFO 速度 + + Channel 3 volume + - LFO depth - + + Channel 4 volume + - Wood 1 - + + Shift Register width + - Wood 2 - + + Right Output level + 右聲道輸出電平 - Two fixed - + + Left Output level + - Tubular bells - + + Channel 1 to SO2 (Left) + - Uniform bar - + + Channel 2 to SO2 (Left) + - Tuned bar - + + Channel 3 to SO2 (Left) + - Tibetan bowl - + + Channel 4 to SO2 (Left) + - - - malletsInstrumentView - Instrument - + + Channel 1 to SO1 (Right) + - Spread - + + Channel 2 to SO1 (Right) + - Spread: - + + Channel 3 to SO1 (Right) + - Hardness - + + Channel 4 to SO1 (Right) + - Hardness: - + + Treble + - Position - + + Bass + 低音 + + + FreeBoyInstrumentView - Position: - + + Sweep Time: + - Modulator - + + Sweep Time + - Modulator: - + + The amount of increase or decrease in frequency + - Crossfade - + + Sweep RtShift amount: + - Crossfade: - + + Sweep RtShift amount + - ADSR - + + The rate at which increase or decrease in frequency occurs + - ADSR: - + + + Wave pattern duty: + - Pressure - + + Wave Pattern Duty + - Pressure: - + + + The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. + - Speed - + + + Square Channel 1 Volume: + - Speed: - + + Square Channel 1 Volume + - Missing files - + + + + Length of each step in sweep: + - Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! - + + + + Length of each step in sweep + - Vibrato gain - + + + + The delay between step change + - Vibrato gain: - + + Wave pattern duty + - Vibrato frequency - + + Square Channel 2 Volume: + - Vibrato frequency: - + + + Square Channel 2 Volume + - Stick mix - + + Wave Channel Volume: + - Stick mix: - + + + Wave Channel Volume + - LFO speed - LFO 速度 + + Noise Channel Volume: + - LFO speed: - + + + Noise Channel Volume + - LFO depth - + + SO1 Volume (Right): + - LFO depth: - + + SO1 Volume (Right) + - - - manageVSTEffectView - - VST parameter control - - VST 參數控制 + + SO2 Volume (Left): + - Automated - 自動 + + SO2 Volume (Left) + - Close - 關閉 + + Treble: + - VST sync - + + Treble + - - - manageVestigeInstrumentView - - VST plugin control - - VST插件控制 + + Bass: + - VST Sync - VST 同步 + + Bass + 低音 - Automated - 自動 + + Sweep Direction + - Close - 關閉 + + + + + + Volume Sweep Direction + - - - organicInstrument - Distortion - 失真 + + Shift Register Width + - Volume - 音量 + + Channel1 to SO1 (Right) + - - - organicInstrumentView - Distortion: - 失真: + + Channel2 to SO1 (Right) + - Volume: - 音量: + + Channel3 to SO1 (Right) + - Randomise - 隨機 + + Channel4 to SO1 (Right) + - Osc %1 waveform: - + + Channel1 to SO2 (Left) + - Osc %1 volume: - + + Channel2 to SO2 (Left) + - Osc %1 panning: - + + Channel3 to SO2 (Left) + - cents - 音分 cents + + Channel4 to SO2 (Left) + - Osc %1 stereo detuning - + + Wave Pattern + - Osc %1 harmonic: - + + Draw the wave here + patchesDialog + Qsynth: Channel Preset Qsynth: 通道預設 + Bank selector 音色選擇器 + Bank + Program selector - + + Patch 音色 + Name 名稱 + OK 確定 + Cancel 取消 @@ -4310,449 +11843,634 @@ pluginBrowser - Incomplete monophonic imitation tb303 - + + no description + 沒有描述 - Plugin for freely manipulating stereo output - + + A native amplifier plugin + 原生增益插件 - Plugin for controlling knobs with sound peaks - + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + 簡單地在樂器欄使用採樣(比如鼓音源), 同時也提供多種設置 - Plugin for enhancing stereo separation of a stereo input file - + + Boost your bass the fast and simple way + - List installed LADSPA plugins - 列出已安裝的 LADSPA 插件 + + Customizable wavetable synthesizer + 可自定製的波表合成器 + + + + An oversampling bitcrusher + + + + + Carla Patchbay Instrument + Carla Patchbay 樂器 - GUS-compatible patch instrument - GUS 兼容音色的樂器 + + Carla Rack Instrument + Carla Rack 樂器 - Additive Synthesizer for organ-like sounds - + + A 4-band Crossover Equalizer + - Tuneful things to bang on - + + A native delay plugin + 原生的衰減插件 - VST-host for using VST(i)-plugins within LMMS - LMMS的VST(i)插件宿主 + + A Dual filter plugin + - Vibrating string modeler - + + plugin for processing dynamics in a flexible way + - plugin for using arbitrary LADSPA-effects inside LMMS. - 在 LMMS 中使用任意 LADSPA 效果的插件。 + + A native eq plugin + 原生的 EQ 插件 - Filter for importing MIDI-files into LMMS - + + A native flanger plugin + 一個原生的 鑲邊 (Flanger) 插件 - Emulation of the MOS6581 and MOS8580 SID. -This chip was used in the Commodore 64 computer. - 模擬 MOS6581 和 MOS8580 SID 的模擬器 -這些芯片曾在 Commodore 64 電腦上用過。 + + Player for GIG files + 播放 GIG 檔案的播放器 - Player for SoundFont files - 在工程中使用SoundFont + + Filter for importing Hydrogen files into LMMS + 匯入 Hydrogen 專案檔至 LMMS 的解析器 - Emulation of GameBoy (TM) APU - GameBoy (TM) APU 模擬器 + + Versatile drum synthesizer + 多功能鼓合成器 - Customizable wavetable synthesizer - 可自定製的波表合成器 + + List installed LADSPA plugins + 列出已安裝的 LADSPA 插件 - Embedded ZynAddSubFX - 內置的 ZynAddSubFX + + plugin for using arbitrary LADSPA-effects inside LMMS. + 在 LMMS 中使用任意 LADSPA 效果的插件。 - 2-operator FM Synth - + + Incomplete monophonic imitation tb303 + - Filter for importing Hydrogen files into LMMS - 導入 Hydrogen 工程文件到 LMMS 的解析器 + + Filter for exporting MIDI-files from LMMS + 從 LMMS 匯出 MIDI 檔的解析器 - LMMS port of sfxr - sfxr 的 LMMS 移植版本 + + Filter for importing MIDI-files into LMMS + 匯入 MIDI 檔至 LMMS 的解析器 + Monstrous 3-oscillator synth with modulation matrix - + - Three powerful oscillators you can modulate in several ways - + + A multitap echo delay plugin + - A native amplifier plugin - 原生增益插件 + + A NES-like synthesizer + 類似於 NES 的合成器 - Carla Rack Instrument - Carla Rack 樂器 + + 2-operator FM Synth + - 4-oscillator modulatable wavetable synth - + + Additive Synthesizer for organ-like sounds + - plugin for waveshaping - + + Emulation of GameBoy (TM) APU + GameBoy (TM) APU 模擬器 - Boost your bass the fast and simple way - + + GUS-compatible patch instrument + GUS 兼容音色的樂器 - Versatile drum synthesizer - 多功能鼓合成器 + + Plugin for controlling knobs with sound peaks + - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track - 簡單地在樂器欄使用採樣(比如鼓音源), 同時也提供多種設置 + + Reverb algorithm by Sean Costello + - plugin for processing dynamics in a flexible way - + + Player for SoundFont files + 播放 SoundFont 檔案的播放器 - Carla Patchbay Instrument - Carla Patchbay 樂器 + + LMMS port of sfxr + sfxr 的 LMMS 移植版本 - plugin for using arbitrary VST effects inside LMMS. - + + Emulation of the MOS6581 and MOS8580 SID. +This chip was used in the Commodore 64 computer. + 模擬 MOS6581 和 MOS8580 SID 的模擬器 +這些芯片曾在 Commodore 64 電腦上用過。 + Graphical spectrum analyzer plugin 圖形頻譜分析器插件 - A NES-like synthesizer - 類似於 NES 的合成器 - - - A native delay plugin - 原生的衰減插件 + + Plugin for enhancing stereo separation of a stereo input file + 用以增強雙聲道輸入檔的聲道分離插件 - Player for GIG files - 播放 GIG 文件的播放器 + + Plugin for freely manipulating stereo output + - A multitap echo delay plugin - + + Tuneful things to bang on + - A native flanger plugin - 一個原生的 鑲邊 (Flanger) 插件 + + Three powerful oscillators you can modulate in several ways + - An oversampling bitcrusher - + + VST-host for using VST(i)-plugins within LMMS + LMMS的VST(i)插件宿主 - A native eq plugin - 原生的 EQ 插件 + + Vibrating string modeler + - A 4-band Crossover Equalizer - + + plugin for using arbitrary VST effects inside LMMS. + - A Dual filter plugin - + + 4-oscillator modulatable wavetable synth + - Filter for exporting MIDI-files from LMMS - + + plugin for waveshaping + - Reverb algorithm by Sean Costello - + + Embedded ZynAddSubFX + 內置的 ZynAddSubFX Mathematical expression parser - + sf2Instrument + Bank + Patch 音色 + Gain 增益 + Reverb 混響 - Chorus - 合唱 + + Reverb Roomsize + 混響空間大小 - A soundfont %1 could not be loaded. - 無法載入Soundfont %1。 + + Reverb Damping + 混響阻尼 - Reverb room size - + + Reverb Width + 混響寬度 - Reverb damping - + + Reverb Level + 混響級別 - Reverb width - + + Chorus + 合唱 - Reverb level - + + Chorus Lines + 合唱聲部 - Chorus voices - + + Chorus Level + 合唱電平 - Chorus level - + + Chorus Speed + 合唱速度 - Chorus speed - + + Chorus Depth + 合唱深度 - Chorus depth - + + A soundfont %1 could not be loaded. + 無法載入Soundfont %1。 sf2InstrumentView + + Open other SoundFont file + 打開其他SoundFont文件 + + + + Click here to open another SF2 file + 點擊此處打開另一個SF2文件 + + + + Choose the patch + 選擇路徑 + + + + Gain + 增益 + + + Apply reverb (if supported) 應用混響(如果支持) - Apply chorus (if supported) - 應用合唱 (如果支持) + + This button enables the reverb effect. This is useful for cool effects, but only works on files that support it. + 此按鈕會啓用混響效果器。可以製作出很酷的效果,但僅對支持的文件有效。 - Open SoundFont file - 打開SoundFont文件 + + Reverb Roomsize: + 混響空間大小: - Choose patch - + + Reverb Damping: + 混響阻尼: - Gain: - 增益: + + Reverb Width: + 混響寬度: - Room size: - + + Reverb Level: + 混響級別: - Damping: - + + Apply chorus (if supported) + 應用合唱 (如果支持) - Width: - 寬度: + + This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. + 此按鈕會啓用合唱效果器。 - Level: - + + Chorus Lines: + 合唱聲部: - Voices: - + + Chorus Level: + 合唱級別: - Speed: - + + Chorus Speed: + 合唱速度: - Depth: - 位深: + + Chorus Depth: + 合唱深度: + + + + Open SoundFont file + 開啟 SoundFont 檔案 - SoundFont Files (*.sf2 *.sf3) - + + SoundFont2 Files (*.sf2) + SoundFont2 Files (*.sf2) sfxrInstrument - Wave - + + Wave Form + 波形 sidInstrument + + Cutoff + 切除 + + + Resonance 共鳴 + Filter type 過濾器類型 + Voice 3 off 聲音 3 關 + Volume 音量 + Chip model 芯片型號 - - Cutoff frequency - 切除頻率 - sidInstrumentView + Volume: 音量: + Resonance: 共鳴: + + Cutoff frequency: 頻譜刀頻率: + + High-Pass filter + 高通濾波器 + + + + Band-Pass filter + 帶通濾波器 + + + + Low-Pass filter + 低通濾波器 + + + + Voice3 Off + 聲音 3 關 + + + MOS6581 SID MOS6581 SID + MOS8580 SID MOS8580 SID + + Attack: 打進聲: + + Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. + + + + + Decay: 衰減: + + Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. + + + + Sustain: 振幅持平: + + Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. + + + + + Release: 聲音消失: + + The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. + + + + + Pulse Width: - + + + + + The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. + + Coarse: - + - Noise - 噪音 + + The Coarse detuning allows to detune Voice %1 one octave up or down. + - Sync - 同步 + + Pulse Wave + - Filtered - + + Triangle Wave + - Test - 測試 + + SawTooth + - High-pass filter - + + Noise + 噪音 - Band-pass filter - + + Sync + 同步 - Low-pass filter - + + Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. + - Voice 3 off - + + Ring-Mod + - Pulse wave - + + Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. + - Triangle wave - 三角波 + + Filtered + - Saw wave - 鋸齒波 + + When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. + - Ring modulation - + + Test + 測試 - Pulse width: - + + Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. + stereoEnhancerControlDialog - Width: - 寬度: + + WIDE + - WIDTH - + + Width: + 寬度: stereoEnhancerControls + Width 寬度 @@ -4760,18 +12478,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControlDialog + Left to Left Vol: 從左到左音量: + Left to Right Vol: 從左到右音量: + Right to Left Vol: 從右到左音量: + Right to Right Vol: 從右到右音量: @@ -4779,18 +12501,22 @@ This chip was used in the Commodore 64 computer. stereoMatrixControls + Left to Left 從左到左 + Left to Right 從左到右 + Right to Left 從右到左 + Right to Right 從右到右 @@ -4798,191 +12524,357 @@ This chip was used in the Commodore 64 computer. vestigeInstrument + Loading plugin 載入插件 - Please wait while loading the VST plugin... - + + Please wait while loading VST-plugin... + 請等待VST插件加載完成... vibed + String %1 volume - + + String %1 stiffness - + + Pick %1 position - + + Pickup %1 position - + - Impulse %1 - + + Pan %1 + 聲相 %1 - String %1 panning - + + Detune %1 + 去諧 %1 - String %1 detune - + + Fuzziness %1 + 模糊度 %1 - String %1 fuzziness - + + Length %1 + 長度 %1 - String %1 length - + + Impulse %1 + - String %1 - + + Octave %1 + 八度音 %1 vibedView + + Volume: + 音量: + + + + The 'V' knob sets the volume of the selected string. + + + + String stiffness: - + + + + + The 'S' knob sets the stiffness of the selected string. The stiffness of the string affects how long the string will ring out. The lower the setting, the longer the string will ring. + + Pick position: - + + + + + The 'P' knob sets the position where the selected string will be 'picked'. The lower the setting the closer the pick is to the bridge. + + Pickup position: - + + + + + The 'PU' knob sets the position where the vibrations will be monitored for the selected string. The lower the setting, the closer the pickup is to the bridge. + + + + + Pan: + + + + + The Pan knob determines the location of the selected string in the stereo field. + + + + + Detune: + 去諧: + + + + The Detune knob modifies the pitch of the selected string. Settings less than zero will cause the string to sound flat. Settings greater than zero will cause the string to sound sharp. + + + + + Fuzziness: + + + + + The Slap knob adds a bit of fuzz to the selected string which is most apparent during the attack, though it can also be used to make the string sound more 'metallic'. + + + + + Length: + 長度: + + + + The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. + + + + + Impulse or initial state + + + + + The 'Imp' selector determines whether the waveform in the graph is to be treated as an impulse imparted to the string by the pick or the initial state of the string. + + Octave - + - Impulse Editor - + + The Octave selector is used to choose which harmonic of the note the string will ring at. For example, '-2' means the string will ring two octaves below the fundamental, 'F' means the string will ring at the fundamental, and '6' means the string will ring six octaves above the fundamental. + + + Impulse Editor + + + + + The waveform editor provides control over the initial state or impulse that is used to start the string vibrating. The buttons to the right of the graph will initialize the waveform to the selected type. The '?' button will load a waveform from a file--only the first 128 samples will be loaded. + +The waveform can also be drawn in the graph. + +The 'S' button will smooth the waveform. + +The 'N' button will normalize the waveform. + + + + + Vibed models up to nine independently vibrating strings. The 'String' selector allows you to choose which string is being edited. The 'Imp' selector chooses whether the graph represents an impulse or the initial state of the string. The 'Octave' selector chooses which harmonic the string should vibrate at. + +The graph allows you to control the initial state or impulse used to set the string in motion. + +The 'V' knob controls the volume. The 'S' knob controls the string's stiffness. The 'P' knob controls the pick position. The 'PU' knob controls the pickup position. + +'Pan' and 'Detune' hopefully don't need explanation. The 'Slap' knob adds a bit of fuzz to the sound of the string. + +The 'Length' knob controls the length of the string. + +The LED in the lower right corner of the waveform editor determines whether the string is active in the current instrument. + + + + Enable waveform 啓用波形 + + Click here to enable/disable waveform. + 點擊這裏啓用/禁用波形。 + + + String - + + + + + The String selector is used to choose which string the controls are editing. A Vibed instrument can contain up to nine independently vibrating strings. The LED in the lower right corner of the waveform editor indicates whether the selected string is active. + + Sine wave 正弦波 + + Use a sine-wave for current oscillator. + 爲當前振盪器使用正弦波。 + + + Triangle wave 三角波 - Saw wave - 鋸齒波 + + Use a triangle-wave for current oscillator. + 爲當前振盪器使用三角波。 - Square wave - 方波 + + Saw wave + 鋸齒波 - String volume: - + + Use a saw-wave for current oscillator. + 爲當前振盪器使用鋸齒波。 - String panning: - + + Square wave + 方波 - String detune: - + + Use a square-wave for current oscillator. + 爲當前振盪器使用方波。 - String fuzziness: - + + White noise wave + 白噪音 - String length: - + + Use white-noise for current oscillator. + 爲當前振盪器使用白噪音。 - Impulse - + + User defined wave + 用戶自定義波形 - Enable/disable string - + + Use a user-defined waveform for current oscillator. + 爲當前振盪器使用用戶自定波形。 - White noise - + + Smooth + 平滑 - User-defined wave - + + Click here to smooth waveform. + 點擊這裏平滑波形。 - Smooth waveform - 平滑波形 + + Normalize + 標準化 - Normalize waveform - + + Click here to normalize waveform. + 點擊這裏標準化波形。 voiceObject + Voice %1 pulse width - + + Voice %1 attack - + + Voice %1 decay - + + Voice %1 sustain - + + Voice %1 release - + + Voice %1 coarse detuning - + + Voice %1 wave shape 聲音 %1 波形形狀 + Voice %1 sync 聲音 %1 同步 + Voice %1 ring modulate - + + Voice %1 filtered - + + Voice %1 test 聲音 %1 測試 @@ -4990,53 +12882,85 @@ This chip was used in the Commodore 64 computer. waveShaperControlDialog + INPUT 輸入 + Input gain: 輸入增益: + OUTPUT 輸出 + Output gain: 輸出增益: - Clip input - 輸入壓限 + + Reset waveform + 重置波形 + + + + Click here to reset the wavegraph back to default + + + + + Smooth waveform + 平滑波形 + + + + Click here to apply smoothing to wavegraph + 點擊這裏來使波形圖更爲平滑 - Reset wavegraph - + + Increase graph amplitude by 1dB + - Smooth wavegraph - + + Click here to increase wavegraph amplitude by 1dB + - Increase wavegraph amplitude by 1 dB - + + Decrease graph amplitude by 1dB + - Decrease wavegraph amplitude by 1 dB - + + Click here to decrease wavegraph amplitude by 1dB + + + + + Clip input + 輸入壓限 - Clip input signal to 0 dB - + + Clip input signal to 0dB + 將輸入信號限制到 0dB waveShaperControls + Input gain 輸入增益 + Output gain 輸出增益 diff --git a/data/presets/X-Pressive/Ambition.xpf b/data/presets/X-Pressive/Ambition.xpf deleted file mode 100644 index 2d93f7c052f..00000000000 --- a/data/presets/X-Pressive/Ambition.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Baby Violin.xpf b/data/presets/X-Pressive/Baby Violin.xpf deleted file mode 100644 index 2e887d3d2b5..00000000000 --- a/data/presets/X-Pressive/Baby Violin.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Bad Singer.xpf b/data/presets/X-Pressive/Bad Singer.xpf deleted file mode 100644 index ca9cfd5a333..00000000000 --- a/data/presets/X-Pressive/Bad Singer.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Cloud Bass.xpf b/data/presets/X-Pressive/Cloud Bass.xpf deleted file mode 100644 index 4e444f22a90..00000000000 --- a/data/presets/X-Pressive/Cloud Bass.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Creature.xpf b/data/presets/X-Pressive/Creature.xpf deleted file mode 100644 index b667a9c7f7a..00000000000 --- a/data/presets/X-Pressive/Creature.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Electric Shock.xpf b/data/presets/X-Pressive/Electric Shock.xpf deleted file mode 100644 index 7dea6fe4ac9..00000000000 --- a/data/presets/X-Pressive/Electric Shock.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Faded Colors.xpf b/data/presets/X-Pressive/Faded Colors.xpf deleted file mode 100644 index 84a37826a56..00000000000 --- a/data/presets/X-Pressive/Faded Colors.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Fat Flute.xpf b/data/presets/X-Pressive/Fat Flute.xpf deleted file mode 100644 index 92242114ec5..00000000000 --- a/data/presets/X-Pressive/Fat Flute.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Horn.xpf b/data/presets/X-Pressive/Horn.xpf deleted file mode 100644 index 09948056960..00000000000 --- a/data/presets/X-Pressive/Horn.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Piano-Gong.xpf b/data/presets/X-Pressive/Piano-Gong.xpf deleted file mode 100644 index 241f61a550d..00000000000 --- a/data/presets/X-Pressive/Piano-Gong.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Rubber Bass.xpf b/data/presets/X-Pressive/Rubber Bass.xpf deleted file mode 100644 index 73c3648bafc..00000000000 --- a/data/presets/X-Pressive/Rubber Bass.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Space Echoes.xpf b/data/presets/X-Pressive/Space Echoes.xpf deleted file mode 100644 index 1d4d2b543b6..00000000000 --- a/data/presets/X-Pressive/Space Echoes.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Speaker Swapper.xpf b/data/presets/X-Pressive/Speaker Swapper.xpf deleted file mode 100644 index cf80b930468..00000000000 --- a/data/presets/X-Pressive/Speaker Swapper.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Toss.xpf b/data/presets/X-Pressive/Toss.xpf deleted file mode 100644 index 27a0b3f96b9..00000000000 --- a/data/presets/X-Pressive/Toss.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Untuned Bell.xpf b/data/presets/X-Pressive/Untuned Bell.xpf deleted file mode 100644 index 74492706359..00000000000 --- a/data/presets/X-Pressive/Untuned Bell.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Vibrato.xpf b/data/presets/X-Pressive/Vibrato.xpf deleted file mode 100644 index 34795de1194..00000000000 --- a/data/presets/X-Pressive/Vibrato.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/X-Distorted.xpf b/data/presets/X-Pressive/X-Distorted.xpf deleted file mode 100644 index cbe3742a55f..00000000000 --- a/data/presets/X-Pressive/X-Distorted.xpf +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/data/presets/X-Pressive/Accordion.xpf b/data/presets/Xpressive/Accordion.xpf similarity index 100% rename from data/presets/X-Pressive/Accordion.xpf rename to data/presets/Xpressive/Accordion.xpf diff --git a/data/presets/Xpressive/Ambition.xpf b/data/presets/Xpressive/Ambition.xpf new file mode 100644 index 00000000000..dd64489779c --- /dev/null +++ b/data/presets/Xpressive/Ambition.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Baby Violin.xpf b/data/presets/Xpressive/Baby Violin.xpf new file mode 100644 index 00000000000..45e407fc87f --- /dev/null +++ b/data/presets/Xpressive/Baby Violin.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Bad Singer.xpf b/data/presets/Xpressive/Bad Singer.xpf new file mode 100644 index 00000000000..10fe3b30837 --- /dev/null +++ b/data/presets/Xpressive/Bad Singer.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Cloud Bass.xpf b/data/presets/Xpressive/Cloud Bass.xpf new file mode 100644 index 00000000000..15bf4188daa --- /dev/null +++ b/data/presets/Xpressive/Cloud Bass.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Creature.xpf b/data/presets/Xpressive/Creature.xpf new file mode 100644 index 00000000000..bee39f224fb --- /dev/null +++ b/data/presets/Xpressive/Creature.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/X-Pressive/Dream.xpf b/data/presets/Xpressive/Dream.xpf similarity index 100% rename from data/presets/X-Pressive/Dream.xpf rename to data/presets/Xpressive/Dream.xpf diff --git a/data/presets/Xpressive/Electric Shock.xpf b/data/presets/Xpressive/Electric Shock.xpf new file mode 100644 index 00000000000..3f9aef10429 --- /dev/null +++ b/data/presets/Xpressive/Electric Shock.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Faded Colors - notes test.xpf b/data/presets/Xpressive/Faded Colors - notes test.xpf new file mode 100644 index 00000000000..de4938f4dc4 --- /dev/null +++ b/data/presets/Xpressive/Faded Colors - notes test.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Faded Colors.xpf b/data/presets/Xpressive/Faded Colors.xpf new file mode 100644 index 00000000000..a514ee43837 --- /dev/null +++ b/data/presets/Xpressive/Faded Colors.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Fat Flute.xpf b/data/presets/Xpressive/Fat Flute.xpf new file mode 100644 index 00000000000..76d9e2f84d9 --- /dev/null +++ b/data/presets/Xpressive/Fat Flute.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/X-Pressive/Frog.xpf b/data/presets/Xpressive/Frog.xpf similarity index 100% rename from data/presets/X-Pressive/Frog.xpf rename to data/presets/Xpressive/Frog.xpf diff --git a/data/presets/Xpressive/Horn.xpf b/data/presets/Xpressive/Horn.xpf new file mode 100644 index 00000000000..d44b332b2ab --- /dev/null +++ b/data/presets/Xpressive/Horn.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/X-Pressive/Low Battery.xpf b/data/presets/Xpressive/Low Battery.xpf similarity index 64% rename from data/presets/X-Pressive/Low Battery.xpf rename to data/presets/Xpressive/Low Battery.xpf index c0e648ac908..78f1fc78f72 100644 --- a/data/presets/X-Pressive/Low Battery.xpf +++ b/data/presets/Xpressive/Low Battery.xpf @@ -1,20 +1,21 @@ - + - - + + - + + + - - - - + + + + - - - + + diff --git a/data/presets/Xpressive/Piano-Gong.xpf b/data/presets/Xpressive/Piano-Gong.xpf new file mode 100644 index 00000000000..a8244b7994f --- /dev/null +++ b/data/presets/Xpressive/Piano-Gong.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Rubber Bass.xpf b/data/presets/Xpressive/Rubber Bass.xpf new file mode 100644 index 00000000000..4b1409e224f --- /dev/null +++ b/data/presets/Xpressive/Rubber Bass.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Space Echoes.xpf b/data/presets/Xpressive/Space Echoes.xpf new file mode 100644 index 00000000000..be6de3653b1 --- /dev/null +++ b/data/presets/Xpressive/Space Echoes.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Speaker Swapper.xpf b/data/presets/Xpressive/Speaker Swapper.xpf new file mode 100644 index 00000000000..d4da5aa2f87 --- /dev/null +++ b/data/presets/Xpressive/Speaker Swapper.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Toss.xpf b/data/presets/Xpressive/Toss.xpf new file mode 100644 index 00000000000..387e78fd92f --- /dev/null +++ b/data/presets/Xpressive/Toss.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Untuned Bell.xpf b/data/presets/Xpressive/Untuned Bell.xpf new file mode 100644 index 00000000000..5dd61ec18d1 --- /dev/null +++ b/data/presets/Xpressive/Untuned Bell.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/Vibrato.xpf b/data/presets/Xpressive/Vibrato.xpf new file mode 100644 index 00000000000..a7dda25e9bb --- /dev/null +++ b/data/presets/Xpressive/Vibrato.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Xpressive/X-Distorted.xpf b/data/presets/Xpressive/X-Distorted.xpf new file mode 100644 index 00000000000..b42495d759d --- /dev/null +++ b/data/presets/Xpressive/X-Distorted.xpf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/ZynAddSubFX/Companion/0074-Smooth Expanded.xiz b/data/presets/ZynAddSubFX/Companion/0074-Smooth Expanded.xiz index cc060f775e4..6ef773a3375 100644 --- a/data/presets/ZynAddSubFX/Companion/0074-Smooth Expanded.xiz +++ b/data/presets/ZynAddSubFX/Companion/0074-Smooth Expanded.xiz @@ -19,7 +19,7 @@ Will Godfrey GPL V 2 or later Now has a slow long tail. -Only really noticable on lower notes. +Only really noticeable on lower notes. diff --git a/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz b/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz index 1687e8c3433..b4a00e1ea86 100644 Binary files a/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz and b/data/projects/demos/CapDan/CapDan-TwilightArea-OriginalByAlf42red.mmpz differ diff --git a/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz b/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz index 95a29daff1d..578c4f926d4 100644 Binary files a/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz and b/data/projects/demos/CapDan/CapDan-ZeroSumGame-OriginalByZakarra.mmpz differ diff --git a/data/projects/demos/EsoXLB-CPU.mmpz b/data/projects/demos/EsoXLB-CPU.mmpz index 1c2549027e4..bc2445e8761 100644 Binary files a/data/projects/demos/EsoXLB-CPU.mmpz and b/data/projects/demos/EsoXLB-CPU.mmpz differ diff --git a/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz b/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz index 2f862dd5113..9ea29b34d3f 100644 Binary files a/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz and b/data/projects/demos/Greippi - Krem Kaakkuja (Second Flight Remix).mmpz differ diff --git a/data/projects/demos/Impulslogik-Zen.mmpz b/data/projects/demos/Impulslogik-Zen.mmpz index 05fa375c49f..774ce89e3d5 100644 Binary files a/data/projects/demos/Impulslogik-Zen.mmpz and b/data/projects/demos/Impulslogik-Zen.mmpz differ diff --git a/data/projects/demos/Jousboxx-BuzzerBeater.mmpz b/data/projects/demos/Jousboxx-BuzzerBeater.mmpz index 60795608c70..59f0d63f6a0 100644 Binary files a/data/projects/demos/Jousboxx-BuzzerBeater.mmpz and b/data/projects/demos/Jousboxx-BuzzerBeater.mmpz differ diff --git a/data/projects/demos/Momo64-esp.mmpz b/data/projects/demos/Momo64-esp.mmpz index 68ae6822c4d..37d1a52b553 100644 Binary files a/data/projects/demos/Momo64-esp.mmpz and b/data/projects/demos/Momo64-esp.mmpz differ diff --git a/data/projects/demos/Namitryus-K-Project.mmpz b/data/projects/demos/Namitryus-K-Project.mmpz index 6d463cbb954..4d62826c9b4 100644 Binary files a/data/projects/demos/Namitryus-K-Project.mmpz and b/data/projects/demos/Namitryus-K-Project.mmpz differ diff --git a/data/projects/demos/Oglsdl-Dr8v2.mmpz b/data/projects/demos/Oglsdl-Dr8v2.mmpz index eb9d7559a21..14b1b0e8540 100644 Binary files a/data/projects/demos/Oglsdl-Dr8v2.mmpz and b/data/projects/demos/Oglsdl-Dr8v2.mmpz differ diff --git a/data/projects/demos/Oglsdl-PpTrip.mmpz b/data/projects/demos/Oglsdl-PpTrip.mmpz index d1baceeba51..776aeea2bdd 100644 Binary files a/data/projects/demos/Oglsdl-PpTrip.mmpz and b/data/projects/demos/Oglsdl-PpTrip.mmpz differ diff --git a/data/projects/demos/Popsip-Electric Dancer.mmpz b/data/projects/demos/Popsip-Electric Dancer.mmpz index fc93dd64a23..1c935dbe126 100644 Binary files a/data/projects/demos/Popsip-Electric Dancer.mmpz and b/data/projects/demos/Popsip-Electric Dancer.mmpz differ diff --git a/data/projects/demos/Root84-Initialize.mmpz b/data/projects/demos/Root84-Initialize.mmpz index 349fcb88f4b..05200823a78 100644 Binary files a/data/projects/demos/Root84-Initialize.mmpz and b/data/projects/demos/Root84-Initialize.mmpz differ diff --git a/data/projects/demos/Saber-FinalStep.mmpz b/data/projects/demos/Saber-FinalStep.mmpz index 5e3d1d1ffc6..05a5022a7d4 100644 Binary files a/data/projects/demos/Saber-FinalStep.mmpz and b/data/projects/demos/Saber-FinalStep.mmpz differ diff --git a/data/projects/demos/Settel-InnerRecreation.mmpz b/data/projects/demos/Settel-InnerRecreation.mmpz index aaa01e0bcfe..78e1d611de8 100644 Binary files a/data/projects/demos/Settel-InnerRecreation.mmpz and b/data/projects/demos/Settel-InnerRecreation.mmpz differ diff --git a/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz b/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz index 2d31bd7bdc2..3ec6a2cffde 100644 Binary files a/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz and b/data/projects/demos/Shovon-ProgressiveHousePluckDemo.mmpz differ diff --git a/data/projects/demos/Skiessi/Skiessi-C64.mmpz b/data/projects/demos/Skiessi/Skiessi-C64.mmpz index f0b3f5cdb4d..a9756453bea 100644 Binary files a/data/projects/demos/Skiessi/Skiessi-C64.mmpz and b/data/projects/demos/Skiessi/Skiessi-C64.mmpz differ diff --git a/data/projects/demos/Skiessi/Skiessi-Onion.mmpz b/data/projects/demos/Skiessi/Skiessi-Onion.mmpz index 0c40fb60a45..23a1ddc48cc 100644 Binary files a/data/projects/demos/Skiessi/Skiessi-Onion.mmpz and b/data/projects/demos/Skiessi/Skiessi-Onion.mmpz differ diff --git a/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz b/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz index d3c6e0f8d0e..bc2810567b9 100644 Binary files a/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz and b/data/projects/demos/Skiessi/Skiessi-RandomProjectNumber14253.mmpz differ diff --git a/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz b/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz index ee5be4b553e..47a0a3672c6 100644 Binary files a/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz and b/data/projects/demos/Skiessi/Skiessi-TurningPoint.mmpz differ diff --git a/data/projects/demos/Socceroos-Progress.mmpz b/data/projects/demos/Socceroos-Progress.mmpz index 74ff5774c94..854663787c3 100644 Binary files a/data/projects/demos/Socceroos-Progress.mmpz and b/data/projects/demos/Socceroos-Progress.mmpz differ diff --git a/data/projects/demos/TameAnderson-MakeMe.mmpz b/data/projects/demos/TameAnderson-MakeMe.mmpz index de015281881..b69a64e3afe 100644 Binary files a/data/projects/demos/TameAnderson-MakeMe.mmpz and b/data/projects/demos/TameAnderson-MakeMe.mmpz differ diff --git a/data/projects/demos/Thaledric-Armageddon.mmpz b/data/projects/demos/Thaledric-Armageddon.mmpz index 0e9d5f83fa9..731ea55f7d5 100644 Binary files a/data/projects/demos/Thaledric-Armageddon.mmpz and b/data/projects/demos/Thaledric-Armageddon.mmpz differ diff --git a/data/projects/demos/Thomasso-AxeFromThe80s.mmpz b/data/projects/demos/Thomasso-AxeFromThe80s.mmpz index af68b8b8b11..f7056d38c22 100644 Binary files a/data/projects/demos/Thomasso-AxeFromThe80s.mmpz and b/data/projects/demos/Thomasso-AxeFromThe80s.mmpz differ diff --git a/data/projects/demos/TobyDox-Psycho.mmpz b/data/projects/demos/TobyDox-Psycho.mmpz index 09ec6b6a6b4..c4fe7a1c428 100644 Binary files a/data/projects/demos/TobyDox-Psycho.mmpz and b/data/projects/demos/TobyDox-Psycho.mmpz differ diff --git a/data/projects/demos/unfa-Spoken.mmpz b/data/projects/demos/unfa-Spoken.mmpz index 659afa03a0f..66b7589d106 100644 Binary files a/data/projects/demos/unfa-Spoken.mmpz and b/data/projects/demos/unfa-Spoken.mmpz differ diff --git a/data/projects/shorties/DirtyLove.mmpz b/data/projects/shorties/DirtyLove.mmpz index 177c05ce516..37b766f4d29 100644 Binary files a/data/projects/shorties/DirtyLove.mmpz and b/data/projects/shorties/DirtyLove.mmpz differ diff --git a/data/projects/shorties/Root84-TrancyLoop.mmpz b/data/projects/shorties/Root84-TrancyLoop.mmpz index 22bd5f2fad7..f5eb032acbe 100644 Binary files a/data/projects/shorties/Root84-TrancyLoop.mmpz and b/data/projects/shorties/Root84-TrancyLoop.mmpz differ diff --git a/data/projects/shorties/Skiessi-222.mmpz b/data/projects/shorties/Skiessi-222.mmpz index a5683364580..a7076949cf6 100644 Binary files a/data/projects/shorties/Skiessi-222.mmpz and b/data/projects/shorties/Skiessi-222.mmpz differ diff --git a/data/projects/shorties/Surrender-Main.mmpz b/data/projects/shorties/Surrender-Main.mmpz index a94df2497ef..5565811708f 100644 Binary files a/data/projects/shorties/Surrender-Main.mmpz and b/data/projects/shorties/Surrender-Main.mmpz differ diff --git a/data/projects/shorties/sv-DnB-Startup.mmpz b/data/projects/shorties/sv-DnB-Startup.mmpz index c9d8d597055..db32d34520f 100644 Binary files a/data/projects/shorties/sv-DnB-Startup.mmpz and b/data/projects/shorties/sv-DnB-Startup.mmpz differ diff --git a/data/projects/shorties/sv-Trance-Startup.mmpz b/data/projects/shorties/sv-Trance-Startup.mmpz index c508b1500c2..bea731461c8 100644 Binary files a/data/projects/shorties/sv-Trance-Startup.mmpz and b/data/projects/shorties/sv-Trance-Startup.mmpz differ diff --git a/data/themes/classic/clone_bb_track_pattern.png b/data/themes/classic/clone_bb_track_pattern.png new file mode 100644 index 00000000000..bf4b3669d81 Binary files /dev/null and b/data/themes/classic/clone_bb_track_pattern.png differ diff --git a/data/themes/classic/midi_cc_rack.png b/data/themes/classic/midi_cc_rack.png new file mode 100644 index 00000000000..6ec1dd2ee0a Binary files /dev/null and b/data/themes/classic/midi_cc_rack.png differ diff --git a/data/themes/classic/proportional_snap.png b/data/themes/classic/proportional_snap.png new file mode 100644 index 00000000000..66a0bb04934 Binary files /dev/null and b/data/themes/classic/proportional_snap.png differ diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index 12d90981d56..65b496617f1 100644 --- a/data/themes/classic/style.css +++ b/data/themes/classic/style.css @@ -35,6 +35,7 @@ QLineEdit { border: 2px inset rgba(91,101,113,128); background: #49515b; color: #e0e0e0; + selection-background-color: #202020; } @@ -118,6 +119,11 @@ QMenu::indicator:selected { background-color: #747474; } +PositionLine { + qproperty-tailGradient: false; + qproperty-lineColor: rgb(255, 255, 255); +} + PianoRoll { background-color: rgb(0, 0, 0); qproperty-backgroundShade: rgba( 255, 255, 255, 10 ); @@ -133,6 +139,17 @@ PianoRoll { qproperty-ghostNoteBorders: true; qproperty-barColor: #4afd85; qproperty-markedSemitoneColor: rgba( 0, 255, 200, 60 ); + /* Piano keys */ + qproperty-whiteKeyWidth: 64; + qproperty-whiteKeyActiveTextColor: #000; + qproperty-whiteKeyActiveTextShadow: rgb( 240, 240, 240 ); + qproperty-whiteKeyActiveBackground: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #43e97b, stop:1 #3bcd6c); + qproperty-whiteKeyInactiveTextColor: rgb( 128, 128, 128); + qproperty-whiteKeyInactiveTextShadow: rgb( 240, 240, 240 ); + qproperty-whiteKeyInactiveBackground: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #eeeeee, stop:1 #ffffff); + qproperty-blackKeyWidth: 48; + qproperty-blackKeyActiveBackground: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #43e97b, stop:1 #3bcd6c); + qproperty-blackKeyInactiveBackground: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #333, stop:1 #000); /* Grid colors */ qproperty-lineColor: rgba( 128, 128, 128, 80 ); qproperty-beatLineColor: rgba( 128, 128, 128, 160 ); @@ -159,11 +176,10 @@ GroupBox { /* main toolbar oscilloscope - can have transparent bg now */ -VisualizationWidget { +Oscilloscope { background: none; border: none; qproperty-normalColor: rgb(71, 253, 133); - qproperty-warningColor: rgb(255, 192, 64); qproperty-clippingColor: rgb(255, 64, 64); } @@ -622,6 +638,8 @@ TrackContentObjectView { qproperty-textBackgroundColor: rgba(0, 0, 0, 75); qproperty-textShadowColor: rgb( 0, 0, 0 ); qproperty-gradient: true; /* boolean property, set true to have a gradient */ + /* finger tip offset of cursor */ + qproperty-mouseHotspotHand: 3px 3px; font-size: 11px; } @@ -897,7 +915,4 @@ LmmsPalette { qproperty-brightText: #4afd85; qproperty-highlight: #202020; qproperty-highlightedText: #ffffff; - /* the next two are used for whatsthis dialogs */ - qproperty-toolTipText: #000; - qproperty-toolTipBase: #c9c9c9; } diff --git a/data/themes/default/clear_ghost_note.png b/data/themes/default/clear_ghost_note.png index c9f85a2b4ab..b9565269f1a 100644 Binary files a/data/themes/default/clear_ghost_note.png and b/data/themes/default/clear_ghost_note.png differ diff --git a/data/themes/default/clone_bb_track_pattern.png b/data/themes/default/clone_bb_track_pattern.png new file mode 100644 index 00000000000..ed7d40fa191 Binary files /dev/null and b/data/themes/default/clone_bb_track_pattern.png differ diff --git a/data/themes/default/fullscreen.png b/data/themes/default/fullscreen.png new file mode 100755 index 00000000000..56f552e104a Binary files /dev/null and b/data/themes/default/fullscreen.png differ diff --git a/data/themes/default/ghost_note.png b/data/themes/default/ghost_note.png index 07344265978..9871fcf0a7e 100644 Binary files a/data/themes/default/ghost_note.png and b/data/themes/default/ghost_note.png differ diff --git a/data/themes/default/loop_points_off.png b/data/themes/default/loop_points_off.png index 23ba7c6babb..a08b304dd87 100644 Binary files a/data/themes/default/loop_points_off.png and b/data/themes/default/loop_points_off.png differ diff --git a/data/themes/default/loop_points_on.png b/data/themes/default/loop_points_on.png index ee6cf0d20f0..908eccd9cb9 100644 Binary files a/data/themes/default/loop_points_on.png and b/data/themes/default/loop_points_on.png differ diff --git a/data/themes/default/midi_cc_rack.png b/data/themes/default/midi_cc_rack.png new file mode 100644 index 00000000000..6ec1dd2ee0a Binary files /dev/null and b/data/themes/default/midi_cc_rack.png differ diff --git a/data/themes/default/proportional_snap.png b/data/themes/default/proportional_snap.png new file mode 100644 index 00000000000..66a0bb04934 Binary files /dev/null and b/data/themes/default/proportional_snap.png differ diff --git a/data/themes/default/record_step_off.png b/data/themes/default/record_step_off.png index 8da17a91009..8f81605f40a 100644 Binary files a/data/themes/default/record_step_off.png and b/data/themes/default/record_step_off.png differ diff --git a/data/themes/default/record_step_on.png b/data/themes/default/record_step_on.png index 700ba97f305..051a2baf7f6 100644 Binary files a/data/themes/default/record_step_on.png and b/data/themes/default/record_step_on.png differ diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 5d889295cae..832da176f28 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -9,16 +9,23 @@ QLabel, QTreeWidget, QListWidget, QGroupBox, QMenuBar { QTreeView { outline: none; + font-size: 12px; +} + +QTreeWidget::item { + padding: 1px; } QTreeWidget::item:hover, QTreeWidget::branch:hover { background-color: #3C444E; + padding-left: 0px; } QTreeWidget::item:selected, QTreeWidget::branch:selected { background-color: #17793b; + padding-left: 0px; } QTreeView::branch:has-children:open { @@ -55,6 +62,7 @@ QLineEdit { border: 1px; background: #101213; color: #d1d8e4; + selection-background-color: #17793b; } QLineEdit:read-only { @@ -81,6 +89,12 @@ TextFloat { } +/* splash screen text */ +QSplashScreen QLabel { + color: white; +} + + QMenu { border-top: 2px solid #08993E; background-color: #15191c; @@ -137,6 +151,11 @@ QMenu::indicator:selected { background-color: #101213; } +PositionLine { + qproperty-tailGradient: true; + qproperty-lineColor: rgb(255, 255, 255); +} + PianoRoll { background-color: #141616; qproperty-backgroundShade: rgba(255, 255, 255, 10); @@ -152,6 +171,17 @@ PianoRoll { qproperty-ghostNoteBorders: false; qproperty-barColor: #078f3a; qproperty-markedSemitoneColor: rgba(255, 255, 255, 30); + /* Piano keys */ + qproperty-whiteKeyWidth: 64; + qproperty-whiteKeyActiveTextColor: #000; + qproperty-whiteKeyActiveTextShadow: #fff; + qproperty-whiteKeyActiveBackground: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #43e97b, stop:1 #3bcd6c); + qproperty-whiteKeyInactiveTextColor: #000; + qproperty-whiteKeyInactiveTextShadow: #fff; + qproperty-whiteKeyInactiveBackground: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #eeeeee, stop:1 #ffffff); + qproperty-blackKeyWidth: 48; + qproperty-blackKeyActiveBackground: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #43e97b, stop:1 #3bcd6c); + qproperty-blackKeyInactiveBackground: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #333, stop:1 #000); /* Grid colors */ qproperty-lineColor: #292929; qproperty-beatLineColor: #2d6b45; @@ -178,11 +208,10 @@ GroupBox { /* main toolbar oscilloscope - can have transparent bg now */ -VisualizationWidget { +Oscilloscope { background: none; border: none; qproperty-normalColor: rgb(71, 253, 133); - qproperty-warningColor: rgb(255, 192, 64); qproperty-clippingColor: rgb(255, 64, 64); } @@ -647,6 +676,8 @@ TrackContentObjectView { qproperty-textBackgroundColor: rgba(0, 0, 0, 75); qproperty-textShadowColor: rgba(0,0,0,200); qproperty-gradient: false; /* boolean property, set true to have a gradient */ + /* finger tip offset of cursor */ + qproperty-mouseHotspotHand: 7px 2px; font-size: 11px; } @@ -920,7 +951,4 @@ LmmsPalette { qproperty-brightText: #d1d8e4; qproperty-highlight: #262b30; qproperty-highlightedText: #d1d8e4; - /* the next two are used for whatsthis dialogs */ - qproperty-toolTipText: #d1d8e4; - qproperty-toolTipBase: #101213; } diff --git a/data/themes/default/trackop.png b/data/themes/default/trackop.png index b26dd6ef26a..dd200d095f2 100644 Binary files a/data/themes/default/trackop.png and b/data/themes/default/trackop.png differ diff --git a/debian/control b/debian/control index 463353df0ef..63eba44d2e1 100644 --- a/debian/control +++ b/debian/control @@ -28,6 +28,7 @@ Build-Depends: libsoundio-dev, libstk0-dev, libvorbis-dev, + libx11-xcb-dev, libxcb-keysyms1-dev, libxcb-util0-dev, libxml-perl, @@ -37,18 +38,28 @@ Build-Depends: qttools5-dev, wine64-tools [amd64] | wine32-tools [i386] Standards-Version: 4.2.1.4 -Homepage: http://lmms.io/ +Homepage: https://lmms.io/ Vcs-Browser: https://salsa.debian.org/debian-edu-pkg-team/lmms.git Package: lmms-bin Architecture: any -Depends: lmms-common (>= ${source:Version}), ${shlibs:Depends}, ${misc:Depends}, - stk -Recommends: tap-plugins, caps, +Depends: + lmms-common (>= ${source:Version}), + ${shlibs:Depends}, + ${misc:Depends}, + stk, +Recommends: + caps, lmms-vst-server:i386 (>= ${source:Version}), - lmms-vst-server:amd64 (>= ${source:Version}) -Suggests: fil-plugins, mcp-plugins, omins, freepats, fluid-soundfont-gm, - ladspa-plugin + lmms-vst-server:amd64 (>= ${source:Version}), + tap-plugins, +Suggests: + fil-plugins, + fluid-soundfont-gm, + freepats, + ladspa-plugin, + mcp-plugins, + omins, Replaces: lmms-common (<< 1.0.0-1) Breaks: lmms-common (<< 1.0.0-1) Multi-Arch: allowed @@ -67,7 +78,9 @@ Description: Linux Multimedia Studio - minimal installation Package: lmms Architecture: any -Depends: lmms-bin, ${misc:Depends} +Depends: + lmms-bin, + ${misc:Depends}, Description: Linux Multimedia Studio LMMS aims to be a free alternative to popular (but commercial and closed- source) programs like FruityLoops, Cubase and Logic giving you the ability of @@ -83,7 +96,10 @@ Description: Linux Multimedia Studio Package: lmms-common Architecture: all -Depends: zynaddsubfx-data, ${shlibs:Depends}, ${misc:Depends} +Depends: + ${shlibs:Depends}, + ${misc:Depends}, + zynaddsubfx-data, Pre-Depends: ${misc:Pre-Depends} Description: Linux Multimedia Studio - common files LMMS aims to be a free alternative to popular (but commercial and closed- @@ -101,7 +117,10 @@ Description: Linux Multimedia Studio - common files Package: lmms-vst-server Architecture: amd64 i386 -Depends: wine64 [amd64] | wine64-development [amd64] | wine32 [i386] | wine32-development [i386], ${shlibs:Depends}, ${misc:Depends} +Depends: + wine64 [amd64] | wine64-development [amd64] | wine32 [i386] | wine32-development [i386], + ${shlibs:Depends}, + ${misc:Depends}, Recommends: lmms-bin:any Description: Linux Multimedia Studio - VST server This package contains a helper application that loads VST plugins. diff --git a/debian/copyright b/debian/copyright index 3fbf0917ee1..01b30459ea7 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,4 +1,4 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: LMMS Upstream-Contact: https://github.com/LMMS/lmms Source: https://github.com/LMMS/lmms/tags @@ -1367,7 +1367,7 @@ License: WOL documentation for any purpose is hereby granted without fee, provided that the above copyright notice and this license appear in all source copies. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF - ANY KIND. See http://www.dspguru.com/wol.htm for more information. + ANY KIND. See https://www.dspguru.com/wol.htm for more information. License: non-free This license does not comply with Debian Free Software Guidelines. diff --git a/debian/patches/contributors.patch b/debian/patches/contributors.patch deleted file mode 100644 index d2b55fd9ac4..00000000000 --- a/debian/patches/contributors.patch +++ /dev/null @@ -1,89 +0,0 @@ -Description: Add contributors - The list of contributors is missing from the source tarball. This list is - generated from upstream repository, running: - git shortlog -sne v1.1.3 | cut -c8- - See https://github.com/LMMS/lmms/issues/2914 for more information. -Author: Javier Serrano Polo - -Index: lmms-1.1.3/doc/CONTRIBUTORS -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ lmms-1.1.3/doc/CONTRIBUTORS 2016-07-12 00:41:47.000000000 +0200 -@@ -0,0 +1,77 @@ -+Tobias Doerffel -+Vesa -+Javier Serrano Polo -+Paul Giblock -+Tres Finocchiaro -+Lukas W -+Raine M. Ekman -+Wong Cho Ching -+Hannu Haahti -+Danny McRae -+Dave French -+Daniel Winzen -+Andreas Brandmaier -+Andrew Kelley -+Oskar Wallgren -+Mike Choi -+Alexandre Almeida -+NoiseByNorthwest -+Johannes Lorenz -+Stian Jørgensrud -+falkTX -+Csaba Hruska -+StakeoutPunch -+ma2moto -+mikobuntu -+8tab <8tab@wp.pl> -+Matthew Krafczyk -+Spekular -+Umcaruje -+DeRobyJ -+Jonathan Aquilina -+ra -+wongcc966422 -+Gurjot Singh -+Janne Sinisalo -+Krzysztof Foltman -+Lou Herard -+Paul Wayper -+Rüdiger Ranft -+Yann Collette -+grindhold -+midi-pascal -+unfa -+Ian Sannar -+Jaroslav Petrnoušek -+LYF610400210 -+Rafael Ruggiero -+psyomn -+quadro -+sarahkeefe -+Achim Settelmeier -+André Hentschel -+Armin Kazmi -+Attila Herman -+Christopher A. Oliver -+Devin Venable -+Fastigium -+Frank Mather -+Frederik -+Hexasoft -+Jens Lang -+Jesse Dubay -+Joel Muzzerall -+Kristi -+Markus Elfring -+Nikos Chantziaras -+Paul Nasca -+Peter Nelson -+Ra -+Steffen Baranowsky -+Thorsten Müller -+TonyChyi -+devin -+dnl-music -+fundamental -+groboclown -+zm1990s diff --git a/debian/patches/series b/debian/patches/series index aba1af04416..94ae11454e2 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,2 @@ -contributors.patch clang.patch build-amd64-20181013.patch diff --git a/doc/CONTRIBUTORS b/doc/CONTRIBUTORS index 4a791028fe3..eb030ad7106 100644 --- a/doc/CONTRIBUTORS +++ b/doc/CONTRIBUTORS @@ -9,24 +9,26 @@ Colin Wallace Oskar Wallgren Raine M. Ekman Umcaruje -Michael Gregorius +Hyunjin Song Javier Serrano Polo +Michael Gregorius grejppi Javier Serrano Polo -Hyunjin Song Wong Cho Ching Alexandre Almeida Daniel Winzen LMMS Service Account Steffen Baranowsky Danny McRae +Johannes Lorenz Garrett -Hyunin Song liushuyu +Dominic Clark +Hyunin Song Andrew Kelley +Spekular Andreas Brandmaier Fastigium -Spekular Amadeus Folego Jonas Trappenberg M374LX @@ -35,18 +37,17 @@ grindhold Mike Choi Karmo Rosental Christopher L. Simons -Dominic Clark NoiseByNorthwest -falkTX -Johannes Lorenz Rebecca DeField +falkTX Stian Jørgensrud +David Carlier Ryan Roden-Corrent +Shmuel H midi-pascal Augustin Cavalier BaraMGB Csaba Hruska -David Carlier DeRobyJ Hussam Eddin Alhomsi Rüdiger Ranft @@ -66,11 +67,15 @@ Jonathan Aquilina Mohammad Amin Sameti ra wongcc966422 +Cyp David CARLIER +Douglas <34612565+DouglasDGI@users.noreply.github.com> Gurjot Singh Janne Sinisalo Krzysztof Foltman Lou Herard +Noah Brecht +Olivier Humbert Paul Batchelor Paul Wayper Petter Reinholdtsen @@ -86,9 +91,8 @@ Cyrille Bollu Dan Williams Ian Sannar Jaroslav Petrnoušek -Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com> -Johannes Lorenz Kenneth Perry (thothonegan) +Kevin Zander LYF610400210 Lukas W Mark-Agent003 @@ -101,29 +105,37 @@ Rebecca LaVie Roberto Giaconia SecondFlight Steffen Baranowsky +T0NIT0 RMX TheTravelingSpaceman Thomas Clark gnudles liushuyu +makepost miketurn psyomn quadro sarahkeefe +thmueller64 <64359888+thmueller64@users.noreply.github.com> Achim Settelmeier +Alexandra Dutton +Andreas Müller André Hentschel Armin Kazmi +Artur Twardowski <32247490+artur-twardowski@users.noreply.github.com> Attila Herman Bastian Kummer Christopher A. Oliver +Cyp <48363+Cyp@users.noreply.github.com> Devin Venable Diego Ramos Ruggeri -Douglas <34612565+DouglasDGI@users.noreply.github.com> DragonEagle Filip Hron Frank Mather Frederik +Gingka Akiyama <33764485+GingkathFox@users.noreply.github.com> Greg Simpson Hexasoft +Hubert Figuière IvanMaldonado Ivo Wetzel Jens Lang @@ -138,17 +150,17 @@ Lee Avital LocoMatt Léo Andrès Markus Elfring +Martin Pavelek Maurizio Lo Bosco Mehdi Mikobuntu Mingcong Bai Nikos Chantziaras -Noah Brecht Ododo -Olivier Humbert Paul Nasca Peter Nelson Ra +Ron U Ryan Schmidt Shane Ambler Simon Jackson (Netbook) @@ -170,13 +182,15 @@ follower fundamental gandalf3 groboclown +https://gitlab.com/users/CYBERDEViLNL <1148379+CYBERDEViLNL@users.noreply.github.com> irrenhaus3 jasp00 justnope kamnxt +knittl lmmsservice m-xbutterfly -noahb01 +necrashter projectpitchin rgwan xhe diff --git a/doc/bash-completion/lmms b/doc/bash-completion/lmms index ccff8f249d9..9c4a0da6b1b 100644 --- a/doc/bash-completion/lmms +++ b/doc/bash-completion/lmms @@ -89,7 +89,7 @@ _lmms() pars_render=(--float --bitrate --format --interpolation) pars_render+=(--loop --mode --output --profile) pars_render+=(--samplerate --oversampling) - actions=(dump render rendertracks upgrade) + actions=(dump compress render rendertracks upgrade) actions_old=(-d --dump -r --render --rendertracks -u --upgrade) shortargs+=(-a -b -c -f -h -i -l -m -o -p -s -v -x) @@ -139,6 +139,10 @@ _lmms() filetypes='mid|midi|MID|MIDI|rmi|RMI|h2song|H2SONG' filemode='existing_files' ;; + --save-as) + filetypes='mmp|mmpz' + filemode='files' + ;; --mode|-m) params='s j m' ;; @@ -208,10 +212,9 @@ _lmms() done fi - if [[ $prev =~ -e|--help|-h|-version|-v ]] + if [[ $prev =~ --help|-h|-version|-v ]] then - # the -e flag (from --import) and help/version - # always mark the end of arguments + # help/version always mark the end of arguments return fi diff --git a/doc/lmms.1 b/doc/lmms.1 index a7e8be23258..58df4086411 100644 --- a/doc/lmms.1 +++ b/doc/lmms.1 @@ -63,8 +63,8 @@ Specify the prefered size and position of the main window. \fIgeometry\fP syntax is \fIxsize\fPx\fIysize\fP+\fIxoffset\fP+\fIyoffset\fP. .br Default: full screen. -.IP "\fB\ --import\fP \fIin\fP \fB\-e\fP -Import MIDI or Hydrogen file \fIin\fP. +.IP "\fB\ --import\fP \fIin\fP \fB\--save-as\fP \fIout\fP +Import MIDI or Hydrogen file \fIin\fP. If \fB\--save-as\fP is specifeied, lmms saves the imported file as \fIout\fP and then exits. .br .SH OPTIONS FOR RENDER AND RENDERTRACKS diff --git a/include/AudioAlsa.h b/include/AudioAlsa.h index 77938e16412..b1aa9647a61 100644 --- a/include/AudioAlsa.h +++ b/include/AudioAlsa.h @@ -80,10 +80,10 @@ class AudioAlsa : public QThread, public AudioDevice static DeviceInfoCollection getAvailableDevices(); private: - virtual void startProcessing(); - virtual void stopProcessing(); - virtual void applyQualitySettings(); - virtual void run(); + void startProcessing() override; + void stopProcessing() override; + void applyQualitySettings() override; + void run() override; int setHWParams( const ch_cnt_t _channels, snd_pcm_access_t _access ); int setSWParams(); diff --git a/include/AudioAlsaSetupWidget.h b/include/AudioAlsaSetupWidget.h index f087d2fd797..db88558a75b 100644 --- a/include/AudioAlsaSetupWidget.h +++ b/include/AudioAlsaSetupWidget.h @@ -46,7 +46,7 @@ class AudioAlsaSetupWidget : public AudioDeviceSetupWidget AudioAlsaSetupWidget( QWidget * _parent ); virtual ~AudioAlsaSetupWidget(); - virtual void saveSettings(); + void saveSettings() override; public slots: void onCurrentIndexChanged(int index); diff --git a/include/AudioDevice.h b/include/AudioDevice.h index 35f5ec6207f..c9ad7f4b3cd 100644 --- a/include/AudioDevice.h +++ b/include/AudioDevice.h @@ -115,7 +115,7 @@ class AudioDevice const fpp_t _frames ); // resample given buffer from samplerate _src_sr to samplerate _dst_sr - void resample( const surroundSampleFrame * _src, + fpp_t resample( const surroundSampleFrame * _src, const fpp_t _frames, surroundSampleFrame * _dst, const sample_rate_t _src_sr, diff --git a/include/AudioDummy.h b/include/AudioDummy.h index 5094caddc1a..0772c69eb36 100644 --- a/include/AudioDummy.h +++ b/include/AudioDummy.h @@ -64,11 +64,11 @@ class AudioDummy : public QThread, public AudioDevice { } - virtual void saveSettings() + void saveSettings() override { } - virtual void show() + void show() override { parentWidget()->hide(); QWidget::show(); @@ -78,17 +78,17 @@ class AudioDummy : public QThread, public AudioDevice private: - virtual void startProcessing() + void startProcessing() override { start(); } - virtual void stopProcessing() + void stopProcessing() override { stopProcessingThread( this ); } - virtual void run() + void run() override { MicroTimer timer; while( true ) diff --git a/include/AudioFileMP3.h b/include/AudioFileMP3.h index 497208e20e6..057fd13a48c 100644 --- a/include/AudioFileMP3.h +++ b/include/AudioFileMP3.h @@ -58,7 +58,7 @@ class AudioFileMP3 : public AudioFileDevice protected: virtual void writeBuffer( const surroundSampleFrame * /* _buf*/, const fpp_t /*_frames*/, - const float /*_master_gain*/ ); + const float /*_master_gain*/ ) override; private: void flushRemainingBuffers(); diff --git a/include/AudioFileOgg.h b/include/AudioFileOgg.h index 656a7174ef3..8082f37678b 100644 --- a/include/AudioFileOgg.h +++ b/include/AudioFileOgg.h @@ -59,7 +59,7 @@ class AudioFileOgg : public AudioFileDevice private: virtual void writeBuffer( const surroundSampleFrame * _ab, const fpp_t _frames, - const float _master_gain ); + const float _master_gain ) override; bool startEncoding(); void finishEncoding(); diff --git a/include/AudioFileWave.h b/include/AudioFileWave.h index 4d2778bad82..7c8d549642a 100644 --- a/include/AudioFileWave.h +++ b/include/AudioFileWave.h @@ -56,7 +56,7 @@ class AudioFileWave : public AudioFileDevice private: virtual void writeBuffer( const surroundSampleFrame * _ab, const fpp_t _frames, - float _master_gain ); + float _master_gain ) override; bool startEncoding(); void finishEncoding(); diff --git a/include/AudioJack.h b/include/AudioJack.h index c3207c82984..a80e8855201 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -34,6 +34,7 @@ #include "weak_libjack.h" #endif +#include #include #include #include @@ -57,6 +58,7 @@ class AudioJack : public QObject, public AudioDevice // the jack callback is handled here, we call the midi client so that it can read // it's midi data during the callback AudioJack * addMidiClient(MidiJack *midiClient); + void removeMidiClient(void) { m_midiClient = nullptr; } jack_client_t * jackClient() {return m_client;}; inline static QString name() @@ -106,9 +108,9 @@ private slots: jack_client_t * m_client; bool m_active; - bool m_stopped; + std::atomic m_stopped; - MidiJack *m_midiClient; + std::atomic m_midiClient; QVector m_outputPorts; jack_default_audio_sample_t * * m_tempOutBufs; surroundSampleFrame * m_outBuf; diff --git a/include/AudioOss.h b/include/AudioOss.h index bacfd959760..9e4787ff202 100644 --- a/include/AudioOss.h +++ b/include/AudioOss.h @@ -60,7 +60,7 @@ class AudioOss : public QThread, public AudioDevice setupWidget( QWidget * _parent ); virtual ~setupWidget(); - virtual void saveSettings(); + void saveSettings() override; private: QLineEdit * m_device; @@ -70,10 +70,10 @@ class AudioOss : public QThread, public AudioDevice private: - virtual void startProcessing(); - virtual void stopProcessing(); - virtual void applyQualitySettings(); - virtual void run(); + void startProcessing() override; + void stopProcessing() override; + void applyQualitySettings() override; + void run() override; int m_audioFD; diff --git a/include/AudioPort.h b/include/AudioPort.h index 2842c6a1768..146bbd192cd 100644 --- a/include/AudioPort.h +++ b/include/AudioPort.h @@ -100,8 +100,8 @@ class AudioPort : public ThreadableJob bool processEffects(); // ThreadableJob stuff - virtual void doProcessing(); - virtual bool requiresProcessing() const + void doProcessing() override; + bool requiresProcessing() const override { return true; } diff --git a/include/AudioPulseAudio.h b/include/AudioPulseAudio.h index 49674669134..e65180a74a3 100644 --- a/include/AudioPulseAudio.h +++ b/include/AudioPulseAudio.h @@ -62,7 +62,7 @@ class AudioPulseAudio : public QThread, public AudioDevice setupWidget( QWidget * _parent ); virtual ~setupWidget(); - virtual void saveSettings(); + void saveSettings() override; private: QLineEdit * m_device; @@ -80,10 +80,10 @@ class AudioPulseAudio : public QThread, public AudioDevice private: - virtual void startProcessing(); - virtual void stopProcessing(); - virtual void applyQualitySettings(); - virtual void run(); + void startProcessing() override; + void stopProcessing() override; + void applyQualitySettings() override; + void run() override; volatile bool m_quit; diff --git a/include/AudioSampleRecorder.h b/include/AudioSampleRecorder.h index 69ac1949047..0a82d2d9619 100644 --- a/include/AudioSampleRecorder.h +++ b/include/AudioSampleRecorder.h @@ -48,7 +48,7 @@ class AudioSampleRecorder : public AudioDevice private: virtual void writeBuffer( const surroundSampleFrame * _ab, const fpp_t _frames, - const float _master_gain ); + const float _master_gain ) override; typedef QList > BufferList; BufferList m_buffers; diff --git a/include/AudioSdl.h b/include/AudioSdl.h index fd8c544c264..93f23abed22 100644 --- a/include/AudioSdl.h +++ b/include/AudioSdl.h @@ -60,9 +60,9 @@ class AudioSdl : public AudioDevice { public: setupWidget( QWidget * _parent ); - virtual ~setupWidget(); + ~setupWidget() override; - virtual void saveSettings(); + void saveSettings() override; private: QLineEdit * m_device; @@ -71,9 +71,9 @@ class AudioSdl : public AudioDevice private: - virtual void startProcessing(); - virtual void stopProcessing(); - virtual void applyQualitySettings(); + void startProcessing() override; + void stopProcessing() override; + void applyQualitySettings() override; static void sdlAudioCallback( void * _udata, Uint8 * _buf, int _len ); void sdlAudioCallback( Uint8 * _buf, int _len ); diff --git a/include/AudioSndio.h b/include/AudioSndio.h index d2bc5c07430..f8cf56848a6 100644 --- a/include/AudioSndio.h +++ b/include/AudioSndio.h @@ -58,7 +58,7 @@ class AudioSndio : public QThread, public AudioDevice setupWidget( QWidget * _parent ); virtual ~setupWidget(); - virtual void saveSettings( void ); + void saveSettings( void ) override; private: QLineEdit * m_device; @@ -66,10 +66,10 @@ class AudioSndio : public QThread, public AudioDevice } ; private: - virtual void startProcessing( void ); - virtual void stopProcessing( void ); - virtual void applyQualitySettings( void ); - virtual void run( void ); + void startProcessing( void ) override; + void stopProcessing( void ) override; + void applyQualitySettings( void ) override; + void run( void ) override; struct sio_hdl *m_hdl; struct sio_par m_par; diff --git a/include/AutomatableButton.h b/include/AutomatableButton.h index 4b50655429f..d7859a10c15 100644 --- a/include/AutomatableButton.h +++ b/include/AutomatableButton.h @@ -48,7 +48,7 @@ class LMMS_EXPORT AutomatableButton : public QPushButton, public BoolModelView model()->setJournalling( _on ); } - virtual void modelChanged(); + void modelChanged() override; public slots: @@ -62,9 +62,9 @@ public slots: protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; private: @@ -92,7 +92,7 @@ class LMMS_EXPORT automatableButtonGroup : public QWidget, public IntModelView void activateButton( AutomatableButton * _btn ); - virtual void modelChanged(); + void modelChanged() override; private slots: diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 3e0b6143da3..c332858b7b6 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -148,7 +148,7 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject template inline T value( int frameOffset = 0 ) const { - if( unlikely( hasLinkedModels() || m_controllerConnection != NULL ) ) + if( hasLinkedModels() || m_controllerConnection != NULL ) { return castValue( controllerValue( frameOffset ) ); } @@ -236,6 +236,7 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject m_centerValue = centerVal; } + //! link @p m1 and @p m2, let @p m1 take the values of @p m2 static void linkModels( AutomatableModel* m1, AutomatableModel* m2 ); static void unlinkModels( AutomatableModel* m1, AutomatableModel* m2 ); @@ -255,7 +256,7 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject specified DOM element using as attribute/node name */ virtual void loadSettings( const QDomElement& element, const QString& name ); - virtual QString nodeName() const + QString nodeName() const override { return "automatablemodel"; } @@ -337,12 +338,12 @@ public slots: static bool mustQuoteName(const QString &name); - virtual void saveSettings( QDomDocument& doc, QDomElement& element ) + void saveSettings( QDomDocument& doc, QDomElement& element ) override { saveSettings( doc, element, "value" ); } - virtual void loadSettings( const QDomElement& element ) + void loadSettings( const QDomElement& element ) override { loadSettings( element, "value" ); } @@ -359,7 +360,7 @@ public slots: template void roundAt( T &value, const T &where ) const; - ScaleType m_scaleType; //! scale type, linear by default + ScaleType m_scaleType; //!< scale type, linear by default float m_value; float m_initValue; float m_minValue; diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index 964ffdc5d63..b3a935d39b1 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -49,7 +49,8 @@ class LMMS_EXPORT AutomatableModelView : public ModelView return castModel(); } - virtual void setModel( Model* model, bool isOldModelValid = true ); + void setModel( Model* model, bool isOldModelValid = true ) override; + void unsetModel() override; template inline T value() const diff --git a/include/AutomatableSlider.h b/include/AutomatableSlider.h index f58d4a05954..b51ef1e3ff2 100644 --- a/include/AutomatableSlider.h +++ b/include/AutomatableSlider.h @@ -51,12 +51,12 @@ class AutomatableSlider : public QSlider, public IntModelView protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void wheelEvent( QWheelEvent * _me ); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; + void wheelEvent( QWheelEvent * _me ) override; - virtual void modelChanged(); + void modelChanged() override; private: diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 9705c5efa6a..4813759697f 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -70,12 +70,12 @@ class AutomationEditor : public QWidget, public JournallingObject inline bool validPattern() const { - return m_pattern != nullptr; + return m_pattern != nullptr && m_pattern->hasAutomation(); } - virtual void saveSettings(QDomDocument & doc, QDomElement & parent); - virtual void loadSettings(const QDomElement & parent); - QString nodeName() const + void saveSettings(QDomDocument & doc, QDomElement & parent) override; + void loadSettings(const QDomElement & parent) override; + QString nodeName() const override { return "automationeditor"; } @@ -114,14 +114,14 @@ public slots: protected: typedef AutomationPattern::timeMap timeMap; - virtual void keyPressEvent(QKeyEvent * ke); - virtual void leaveEvent(QEvent * e); - virtual void mousePressEvent(QMouseEvent * mouseEvent); - virtual void mouseReleaseEvent(QMouseEvent * mouseEvent); - virtual void mouseMoveEvent(QMouseEvent * mouseEvent); - virtual void paintEvent(QPaintEvent * pe); - virtual void resizeEvent(QResizeEvent * re); - virtual void wheelEvent(QWheelEvent * we); + void keyPressEvent(QKeyEvent * ke) override; + void leaveEvent(QEvent * e) override; + void mousePressEvent(QMouseEvent * mouseEvent) override; + void mouseReleaseEvent(QMouseEvent * mouseEvent) override; + void mouseMoveEvent(QMouseEvent * mouseEvent) override; + void paintEvent(QPaintEvent * pe) override; + void resizeEvent(QResizeEvent * re) override; + void wheelEvent(QWheelEvent * we) override; float getLevel( int y ); int xCoordOfTick( int tick ); @@ -176,8 +176,8 @@ protected slots: static const int TOP_MARGIN = 16; static const int DEFAULT_Y_DELTA = 6; - static const int DEFAULT_STEPS_PER_TACT = 16; - static const int DEFAULT_PPT = 12 * DEFAULT_STEPS_PER_TACT; + static const int DEFAULT_STEPS_PER_BAR = 16; + static const int DEFAULT_PPB = 12 * DEFAULT_STEPS_PER_BAR; static const int VALUES_WIDTH = 64; @@ -209,6 +209,7 @@ protected slots: float m_bottomLevel; float m_topLevel; + void centerTopBottomScroll(); void updateTopBottomLevels(); QScrollBar * m_leftRightScroll; @@ -230,7 +231,7 @@ protected slots: float m_drawLastLevel; tick_t m_drawLastTick; - int m_ppt; + int m_ppb; int m_y_delta; bool m_y_auto; @@ -240,6 +241,7 @@ protected slots: EditModes m_editMode; + bool m_mouseDownLeft; bool m_mouseDownRight; //true if right click is being held down TimeLineWidget * m_timeLine; @@ -282,14 +284,14 @@ class AutomationEditorWindow : public Editor void setCurrentPattern(AutomationPattern* pattern); const AutomationPattern* currentPattern(); - virtual void dropEvent( QDropEvent * _de ); - virtual void dragEnterEvent( QDragEnterEvent * _dee ); + void dropEvent( QDropEvent * _de ) override; + void dragEnterEvent( QDragEnterEvent * _dee ) override; void open(AutomationPattern* pattern); AutomationEditor* m_editor; - QSize sizeHint() const; + QSize sizeHint() const override; public slots: void clearCurrentPattern(); @@ -297,9 +299,12 @@ public slots: signals: void currentPatternChanged(); +protected: + void focusInEvent(QFocusEvent * event) override; + protected slots: - void play(); - void stop(); + void play() override; + void stop() override; private slots: void updateWindowTitle(); diff --git a/include/AutomationPattern.h b/include/AutomationPattern.h index 070b6c669fe..cad9d0a1d00 100644 --- a/include/AutomationPattern.h +++ b/include/AutomationPattern.h @@ -140,13 +140,13 @@ class LMMS_EXPORT AutomationPattern : public TrackContentObject const QString name() const; // settings-management - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; static const QString classNodeName() { return "automationpattern"; } - QString nodeName() const { return classNodeName(); } + QString nodeName() const override { return classNodeName(); } - virtual TrackContentObjectView * createView( TrackView * _tv ); + TrackContentObjectView * createView( TrackView * _tv ) override; static bool isAutomated( const AutomatableModel * _m ); diff --git a/include/AutomationPatternView.h b/include/AutomationPatternView.h index 45aa9ef2a52..3f019483a10 100644 --- a/include/AutomationPatternView.h +++ b/include/AutomationPatternView.h @@ -44,7 +44,7 @@ class AutomationPatternView : public TrackContentObjectView public slots: /// Opens this view's pattern in the global automation editor void openInAutomationEditor(); - virtual void update(); + void update() override; protected slots: @@ -56,11 +56,11 @@ protected slots: void flipX(); protected: - virtual void constructContextMenu( QMenu * ); - virtual void mouseDoubleClickEvent(QMouseEvent * me ); - virtual void paintEvent( QPaintEvent * pe ); - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void dropEvent( QDropEvent * _de ); + void constructContextMenu( QMenu * ) override; + void mouseDoubleClickEvent(QMouseEvent * me ) override; + void paintEvent( QPaintEvent * pe ) override; + void dragEnterEvent( QDragEnterEvent * _dee ) override; + void dropEvent( QDropEvent * _de ) override; private: diff --git a/include/AutomationTrack.h b/include/AutomationTrack.h index 195c21e9d4b..92a50dd04a9 100644 --- a/include/AutomationTrack.h +++ b/include/AutomationTrack.h @@ -38,19 +38,19 @@ class AutomationTrack : public Track virtual ~AutomationTrack() = default; virtual bool play( const MidiTime & _start, const fpp_t _frames, - const f_cnt_t _frame_base, int _tco_num = -1 ); + const f_cnt_t _frame_base, int _tco_num = -1 ) override; - virtual QString nodeName() const + QString nodeName() const override { return "automationtrack"; } - virtual TrackView * createView( TrackContainerView* ); - virtual TrackContentObject * createTCO( const MidiTime & _pos ); + TrackView * createView( TrackContainerView* ) override; + TrackContentObject * createTCO( const MidiTime & _pos ) override; virtual void saveTrackSpecificSettings( QDomDocument & _doc, - QDomElement & _parent ); - virtual void loadTrackSpecificSettings( const QDomElement & _this ); + QDomElement & _parent ) override; + void loadTrackSpecificSettings( const QDomElement & _this ) override; private: friend class AutomationTrackView; @@ -65,8 +65,8 @@ class AutomationTrackView : public TrackView AutomationTrackView( AutomationTrack* at, TrackContainerView* tcv ); virtual ~AutomationTrackView() = default; - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void dropEvent( QDropEvent * _de ); + void dragEnterEvent( QDragEnterEvent * _dee ) override; + void dropEvent( QDropEvent * _de ) override; } ; diff --git a/include/BBEditor.h b/include/BBEditor.h index 59b7142f471..311ed570436 100644 --- a/include/BBEditor.h +++ b/include/BBEditor.h @@ -42,7 +42,7 @@ class BBEditor : public Editor BBEditor( BBTrackContainer * _tc ); ~BBEditor(); - QSize sizeHint() const; + QSize sizeHint() const override; const BBTrackContainerView* trackContainerView() const { return m_trackContainerView; @@ -54,8 +54,8 @@ class BBEditor : public Editor void removeBBView( int bb ); public slots: - void play(); - void stop(); + void play() override; + void stop() override; private: BBTrackContainerView* m_trackContainerView; @@ -70,15 +70,15 @@ class BBTrackContainerView : public TrackContainerView public: BBTrackContainerView(BBTrackContainer* tc); - bool fixedTCOs() const + bool fixedTCOs() const override { return true; } void removeBBView(int bb); - void saveSettings(QDomDocument& doc, QDomElement& element); - void loadSettings(const QDomElement& element); + void saveSettings(QDomDocument& doc, QDomElement& element) override; + void loadSettings(const QDomElement& element) override; public slots: void addSteps(); @@ -86,9 +86,10 @@ public slots: void removeSteps(); void addSampleTrack(); void addAutomationTrack(); + void clonePattern(); protected slots: - void dropEvent(QDropEvent * de ); + void dropEvent(QDropEvent * de ) override; void updatePosition(); private: diff --git a/include/BBTrack.h b/include/BBTrack.h index a906b54d259..70195f28de6 100644 --- a/include/BBTrack.h +++ b/include/BBTrack.h @@ -43,9 +43,9 @@ class BBTCO : public TrackContentObject BBTCO( Track * _track ); virtual ~BBTCO() = default; - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + inline QString nodeName() const override { return( "bbtco" ); } @@ -72,7 +72,7 @@ class BBTCO : public TrackContentObject int bbTrackIndex(); - virtual TrackContentObjectView * createView( TrackView * _tv ); + TrackContentObjectView * createView( TrackView * _tv ) override; private: QColor m_color; @@ -99,7 +99,7 @@ class BBTCOView : public TrackContentObjectView void setColor( QColor _new_color ); public slots: - virtual void update(); + void update() override; protected slots: void openInBBEditor(); @@ -110,9 +110,9 @@ protected slots: protected: - virtual void paintEvent( QPaintEvent * pe ); - virtual void mouseDoubleClickEvent( QMouseEvent * _me ); - virtual void constructContextMenu( QMenu * ); + void paintEvent( QPaintEvent * pe ) override; + void mouseDoubleClickEvent( QMouseEvent * _me ) override; + void constructContextMenu( QMenu * ) override; private: @@ -133,13 +133,13 @@ class LMMS_EXPORT BBTrack : public Track virtual ~BBTrack(); virtual bool play( const MidiTime & _start, const fpp_t _frames, - const f_cnt_t _frame_base, int _tco_num = -1 ); - virtual TrackView * createView( TrackContainerView* tcv ); - virtual TrackContentObject * createTCO( const MidiTime & _pos ); + const f_cnt_t _frame_base, int _tco_num = -1 ) override; + TrackView * createView( TrackContainerView* tcv ) override; + TrackContentObject * createTCO( const MidiTime & _pos ) override; virtual void saveTrackSpecificSettings( QDomDocument & _doc, - QDomElement & _parent ); - virtual void loadTrackSpecificSettings( const QDomElement & _this ); + QDomElement & _parent ) override; + void loadTrackSpecificSettings( const QDomElement & _this ) override; static BBTrack * findBBTrack( int _bb_num ); static void swapBBTracks( Track * _track1, Track * _track2 ); @@ -184,7 +184,7 @@ class LMMS_EXPORT BBTrack : public Track } protected: - inline virtual QString nodeName() const + inline QString nodeName() const override { return( "bbtrack" ); } @@ -211,7 +211,7 @@ class BBTrackView : public TrackView BBTrackView( BBTrack* bbt, TrackContainerView* tcv ); virtual ~BBTrackView(); - virtual bool close(); + bool close() override; const BBTrack * getBBTrack() const { diff --git a/include/BBTrackContainer.h b/include/BBTrackContainer.h index 2363251570b..17d6eb5fed1 100644 --- a/include/BBTrackContainer.h +++ b/include/BBTrackContainer.h @@ -41,15 +41,15 @@ class LMMS_EXPORT BBTrackContainer : public TrackContainer virtual bool play( MidiTime _start, const fpp_t _frames, const f_cnt_t _frame_base, int _tco_num = -1 ); - virtual void updateAfterTrackAdd() override; + void updateAfterTrackAdd() override; - inline virtual QString nodeName() const override + inline QString nodeName() const override { return "bbtrackcontainer"; } - tact_t lengthOfBB( int _bb ) const; - inline tact_t lengthOfCurrentBB() + bar_t lengthOfBB( int _bb ) const; + inline bar_t lengthOfCurrentBB() { return lengthOfBB( currentBB() ); } diff --git a/include/CPULoadWidget.h b/include/CPULoadWidget.h index 610403f5750..2bc41283b0d 100644 --- a/include/CPULoadWidget.h +++ b/include/CPULoadWidget.h @@ -43,7 +43,7 @@ class CPULoadWidget : public QWidget protected: - virtual void paintEvent( QPaintEvent * _ev ); + void paintEvent( QPaintEvent * _ev ) override; protected slots: diff --git a/include/ColorChooser.h b/include/ColorChooser.h new file mode 100644 index 00000000000..ac2a1b62d4a --- /dev/null +++ b/include/ColorChooser.h @@ -0,0 +1,59 @@ +/* ColorChooser.h - declaration and definition of ColorChooser class. + * + * Copyright (c) 2019 CYBERDEViLNL + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include + +class ColorChooser: public QColorDialog +{ +public: + ColorChooser(const QColor &initial, QWidget *parent): QColorDialog(initial, parent) {}; + ColorChooser(QWidget *parent): QColorDialog(parent) {}; + //! For getting a color without having to initialise a color dialog + ColorChooser() {}; + enum class Palette {Default, Track, Mixer}; + //! Set global palette via array, checking bounds + void setPalette (QVector); + //! Set global paletter via enum + void setPalette (Palette); + //! Set palette via enum, return self pointer for chaining + ColorChooser* withPalette (Palette); + //! Return a certain palette + static QVector getPalette (Palette); + +protected: + //! Forward key events to the parent to prevent stuck notes when the dialog gets focus + void keyReleaseEvent(QKeyEvent *event) override + { + QKeyEvent ke(*event); + QApplication::sendEvent(parentWidget(), &ke); + } +private: + //! Copy the current QColorDialog palette into an array + static QVector defaultPalette(); + //! Generate a nice palette, with adjustable value + static QVector nicePalette (int); +}; diff --git a/include/ComboBox.h b/include/ComboBox.h index 927c8762062..1ab1c240d80 100644 --- a/include/ComboBox.h +++ b/include/ComboBox.h @@ -32,8 +32,6 @@ #include "ComboBoxModel.h" #include "AutomatableModelView.h" - - class LMMS_EXPORT ComboBox : public QWidget, public IntModelView { Q_OBJECT @@ -51,16 +49,18 @@ class LMMS_EXPORT ComboBox : public QWidget, public IntModelView return castModel(); } + static constexpr int DEFAULT_HEIGHT = 22; + public slots: void selectNext(); void selectPrevious(); protected: - virtual void contextMenuEvent( QContextMenuEvent* event ); - virtual void mousePressEvent( QMouseEvent* event ); - virtual void paintEvent( QPaintEvent* event ); - virtual void wheelEvent( QWheelEvent* event ); + void contextMenuEvent( QContextMenuEvent* event ) override; + void mousePressEvent( QMouseEvent* event ) override; + void paintEvent( QPaintEvent* event ) override; + void wheelEvent( QWheelEvent* event ) override; private: diff --git a/include/ConfigManager.h b/include/ConfigManager.h index dc5b9f485cc..de22d22af11 100644 --- a/include/ConfigManager.h +++ b/include/ConfigManager.h @@ -36,6 +36,7 @@ #include "lmms_export.h" + class LmmsCore; @@ -49,7 +50,7 @@ const QString LADSPA_PATH ="plugins/ladspa/"; const QString DEFAULT_THEME_PATH = "themes/default/"; const QString TRACK_ICON_PATH = "track_icons/"; const QString LOCALE_PATH = "locale/"; - +const QString PORTABLE_MODE_FILE = "/portable_mode.txt"; class LMMS_EXPORT ConfigManager : public QObject { @@ -57,23 +58,51 @@ class LMMS_EXPORT ConfigManager : public QObject public: static inline ConfigManager * inst() { - if( s_instanceOfMe == NULL ) + if(s_instanceOfMe == NULL ) { s_instanceOfMe = new ConfigManager(); } return s_instanceOfMe; } + + const QString & workingDir() const + { + return m_workingDir; + } + + void initPortableWorkingDir(); + + void initInstalledWorkingDir(); + + void initDevelopmentWorkingDir(); + const QString & dataDir() const { return m_dataDir; } - const QString & workingDir() const + QString factoryProjectsDir() const { - return m_workingDir; + return dataDir() + PROJECTS_PATH; } + QString factoryTemplatesDir() const + { + return factoryProjectsDir() + TEMPLATE_PATH; + } + + QString factoryPresetsDir() const + { + return dataDir() + PRESETS_PATH; + } + + QString factorySamplesDir() const + { + return dataDir() + SAMPLES_PATH; + } + + QString userProjectsDir() const { return workingDir() + PROJECTS_PATH; @@ -94,155 +123,137 @@ class LMMS_EXPORT ConfigManager : public QObject return workingDir() + SAMPLES_PATH; } - QString userGigDir() const - { - return workingDir() + GIG_PATH; - } - - QString userSf2Dir() const - { - return workingDir() + SF2_PATH; - } - QString userLadspaDir() const + const QString & vstDir() const { - return workingDir() + LADSPA_PATH; + return m_vstDir; } - QString userVstDir() const + const QString & ladspaDir() const { - return m_vstDir; + return m_ladspaDir; } - QString factoryProjectsDir() const + const QString & sf2Dir() const { - return dataDir() + PROJECTS_PATH; + return m_sf2Dir; } - QString factoryTemplatesDir() const +#ifdef LMMS_HAVE_FLUIDSYNTH + const QString & sf2File() const { - return factoryProjectsDir() + TEMPLATE_PATH; + return m_sf2File; } +#endif - QString factoryPresetsDir() const +#ifdef LMMS_HAVE_STK + const QString & stkDir() const { - return dataDir() + PRESETS_PATH; + return m_stkDir; } +#endif - QString factorySamplesDir() const + const QString & gigDir() const { - return dataDir() + SAMPLES_PATH; + return m_gigDir; } - QString defaultVersion() const; - QString defaultArtworkDir() const + QString userVstDir() const { - return m_dataDir + DEFAULT_THEME_PATH; + return m_vstDir; } - QString artworkDir() const + QString userLadspaDir() const { - return m_artworkDir; + return workingDir() + LADSPA_PATH; } - QString trackIconsDir() const + QString userSf2Dir() const { - return m_dataDir + TRACK_ICON_PATH; + return workingDir() + SF2_PATH; } - QString localeDir() const + QString userGigDir() const { - return m_dataDir + LOCALE_PATH; + return workingDir() + GIG_PATH; } - const QString & gigDir() const + QString defaultThemeDir() const { - return m_gigDir; + return m_dataDir + DEFAULT_THEME_PATH; } - const QString & sf2Dir() const + QString themeDir() const { - return m_sf2Dir; + return m_themeDir; } - const QString & vstDir() const + const QString & backgroundPicFile() const { - return m_vstDir; + return m_backgroundPicFile; } - const QString & ladspaDir() const + QString trackIconsDir() const { - return m_ladDir; + return m_dataDir + TRACK_ICON_PATH; } const QString recoveryFile() const { return m_workingDir + "recover.mmp"; } - - const QString & version() const - { - return m_version; - } -#ifdef LMMS_HAVE_STK - const QString & stkDir() const + inline const QStringList & recentlyOpenedProjects() const { - return m_stkDir; + return m_recentlyOpenedProjects; } -#endif -#ifdef LMMS_HAVE_FLUIDSYNTH - const QString & defaultSoundfont() const + QString localeDir() const { - return m_defaultSoundfont; + return m_dataDir + LOCALE_PATH; } -#endif - const QString & backgroundArtwork() const + const QString & version() const { - return m_backgroundArtwork; + return m_version; } - inline const QStringList & recentlyOpenedProjects() const - { - return m_recentlyOpenedProjects; - } + QString defaultVersion() const; - static QStringList availabeVstEmbedMethods(); + + static QStringList availableVstEmbedMethods(); QString vstEmbedMethod() const; - // returns true if the working dir (e.g. ~/lmms) exists on disk + // Returns true if the working dir (e.g. ~/lmms) exists on disk. bool hasWorkingDir() const; - void addRecentlyOpenedProject( const QString & _file ); + void addRecentlyOpenedProject(const QString & _file); - const QString & value( const QString & cls, - const QString & attribute ) const; - const QString & value( const QString & cls, + const QString & value(const QString & cls, + const QString & attribute) const; + const QString & value(const QString & cls, const QString & attribute, - const QString & defaultVal ) const; - void setValue( const QString & cls, const QString & attribute, - const QString & value ); - void deleteValue( const QString & cls, const QString & attribute); + const QString & defaultVal) const; + void setValue(const QString & cls, const QString & attribute, + const QString & value); + void deleteValue(const QString & cls, const QString & attribute); - void loadConfigFile( const QString & configFile = "" ); + void loadConfigFile(const QString & configFile = ""); void saveConfigFile(); - void setWorkingDir( const QString & _wd ); - void setVSTDir( const QString & _vd ); - void setArtworkDir( const QString & _ad ); - void setLADSPADir( const QString & _fd ); - void setVersion( const QString & _cv ); - void setSTKDir( const QString & _fd ); - void setDefaultSoundfont( const QString & _sf ); - void setBackgroundArtwork( const QString & _ba ); - void setGIGDir( const QString & gd ); - void setSF2Dir( const QString & sfd ); + void setWorkingDir(const QString & workingDir); + void setVSTDir(const QString & vstDir); + void setLADSPADir(const QString & ladspaDir); + void setSF2Dir(const QString & sf2Dir); + void setSF2File(const QString & sf2File); + void setSTKDir(const QString & stkDir); + void setGIGDir(const QString & gigDir); + void setThemeDir(const QString & themeDir); + void setBackgroundPicFile(const QString & backgroundPicFile); - // creates the working directory & subdirectories on disk. + // Creates the working directory & subdirectories on disk. void createWorkingDir(); signals: @@ -252,29 +263,29 @@ class LMMS_EXPORT ConfigManager : public QObject static ConfigManager * s_instanceOfMe; ConfigManager(); - ConfigManager( const ConfigManager & _c ); + ConfigManager(const ConfigManager & _c); ~ConfigManager(); void upgrade_1_1_90(); void upgrade_1_1_91(); void upgrade(); - QString m_lmmsRcFile; QString m_workingDir; QString m_dataDir; - QString m_artworkDir; QString m_vstDir; - QString m_ladDir; - QString m_gigDir; + QString m_ladspaDir; QString m_sf2Dir; - QString m_version; +#ifdef LMMS_HAVE_FLUIDSYNTH + QString m_sf2File; +#endif #ifdef LMMS_HAVE_STK QString m_stkDir; #endif -#ifdef LMMS_HAVE_FLUIDSYNTH - QString m_defaultSoundfont; -#endif - QString m_backgroundArtwork; + QString m_gigDir; + QString m_themeDir; + QString m_backgroundPicFile; + QString m_lmmsRcFile; + QString m_version; QStringList m_recentlyOpenedProjects; typedef QVector > stringPairVector; @@ -283,7 +294,5 @@ class LMMS_EXPORT ConfigManager : public QObject friend class LmmsCore; - -} ; - +}; #endif diff --git a/include/ControlLayout.h b/include/ControlLayout.h new file mode 100644 index 00000000000..60182010792 --- /dev/null +++ b/include/ControlLayout.h @@ -0,0 +1,136 @@ +/* + * ControlLayout.h - layout for controls + * + * Copyright (c) 2019-2019 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CONTROLLAYOUT_H +#define CONTROLLAYOUT_H + +#include +#include +#include +class QLayoutItem; +class QRect; +class QString; + +/** + Layout for controls (models) + + Originally token from Qt's FlowLayout example. Modified. + + Features a search bar, as well as looking up widgets with string keys + Keys have to be provided in the widgets' objectNames +*/ +class ControlLayout : public QLayout +{ + Q_OBJECT + +public: + explicit ControlLayout(QWidget *parent, + int margin = -1, int hSpacing = -1, int vSpacing = -1); + ~ControlLayout() override; + + void addItem(QLayoutItem *item) override; + int horizontalSpacing() const; + int verticalSpacing() const; + Qt::Orientations expandingDirections() const override; + bool hasHeightForWidth() const override; + int heightForWidth(int) const override; + int count() const override; + QLayoutItem *itemAt(int index) const override; + QLayoutItem *itemByString(const QString& key) const; + QSize minimumSize() const override; + void setGeometry(const QRect &rect) override; + QSize sizeHint() const override; + QLayoutItem *takeAt(int index) override; + //! remove focus from QLineEdit search bar + //! this may be useful if the mouse is outside the layout + void removeFocusFromSearchBar(); + +private slots: + void onTextChanged(const QString&); + +private: + int doLayout(const QRect &rect, bool testOnly) const; + int smartSpacing(QStyle::PixelMetric pm) const; + QMap::const_iterator pairAt(int index) const; + + QMultiMap m_itemMap; + int m_hSpace; + int m_vSpace; + // relevant dimension is width, as later, heightForWidth() will be called + // 400 looks good and is ~4 knobs in a row + constexpr const static int m_minWidth = 400; + class QLineEdit* m_searchBar; + //! name of search bar, must be ASCII sorted before any alpha numerics + static constexpr const char* s_searchBarName = "!!searchBar!!"; +}; + +#endif // CONTROLLAYOUT_H diff --git a/include/Controller.h b/include/Controller.h index f1e71ad8f59..b60349463ad 100644 --- a/include/Controller.h +++ b/include/Controller.h @@ -101,9 +101,9 @@ class LMMS_EXPORT Controller : public Model, public JournallingObject } - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); - virtual QString nodeName() const; + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; + void loadSettings( const QDomElement & _this ) override; + QString nodeName() const override; static Controller * create( ControllerTypes _tt, Model * _parent ); static Controller * create( const QDomElement & _this, diff --git a/include/ControllerConnection.h b/include/ControllerConnection.h index 5c4d5f20ef1..e57cd4db2f5 100644 --- a/include/ControllerConnection.h +++ b/include/ControllerConnection.h @@ -85,15 +85,15 @@ class LMMS_EXPORT ControllerConnection : public QObject, public JournallingObjec static void finalizeConnections(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; + void loadSettings( const QDomElement & _this ) override; static inline const QString classNodeName() { return "connection"; } - virtual QString nodeName() const + QString nodeName() const override { return classNodeName(); } diff --git a/include/ControllerDialog.h b/include/ControllerDialog.h index 58a0a94b29d..05e8f3bfedb 100644 --- a/include/ControllerDialog.h +++ b/include/ControllerDialog.h @@ -47,7 +47,7 @@ class ControllerDialog : public QWidget, public ModelView protected: - virtual void closeEvent( QCloseEvent * _ce ); + void closeEvent( QCloseEvent * _ce ) override; } ; diff --git a/include/ControllerRackView.h b/include/ControllerRackView.h index cb393f5cacb..9ef2d9b7ff4 100644 --- a/include/ControllerRackView.h +++ b/include/ControllerRackView.h @@ -47,10 +47,10 @@ class ControllerRackView : public QWidget, public SerializingObject ControllerRackView(); virtual ~ControllerRackView(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; - inline virtual QString nodeName() const + inline QString nodeName() const override { return "ControllerRackView"; } @@ -62,7 +62,7 @@ public slots: void onControllerRemoved( Controller * ); protected: - virtual void closeEvent( QCloseEvent * _ce ); + void closeEvent( QCloseEvent * _ce ) override; private slots: void addController(); diff --git a/include/ControllerView.h b/include/ControllerView.h index 4b215feca9b..d1284845eee 100644 --- a/include/ControllerView.h +++ b/include/ControllerView.h @@ -68,9 +68,9 @@ public slots: protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void modelChanged(); - virtual void mouseDoubleClickEvent( QMouseEvent * event ); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void modelChanged() override; + void mouseDoubleClickEvent( QMouseEvent * event ) override; private: diff --git a/include/Controls.h b/include/Controls.h new file mode 100644 index 00000000000..236abbc1199 --- /dev/null +++ b/include/Controls.h @@ -0,0 +1,134 @@ +/* + * Controls.h - labeled control widgets + * + * Copyright (c) 2019-2019 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef CONTROLS_H +#define CONTROLS_H + + +#include "Model.h" + +// headers only required for covariance +#include "AutomatableModel.h" +#include "ComboBoxModel.h" + + +class QString; +class QWidget; +class AutomatableModel; + + +/** + These classes provide + - a control with a text label + - a type safe way to set a model + (justification: setting the wrong typed model to a widget will cause + hard-to-find runtime errors) +*/ +class Control +{ +public: + virtual QWidget* topWidget() = 0; + virtual void setText(const QString& text) = 0; + + virtual void setModel(AutomatableModel* model) = 0; + virtual AutomatableModel* model() = 0; + virtual class AutomatableModelView* modelView() = 0; + + virtual ~Control(); +}; + + +class KnobControl : public Control +{ + class Knob* m_knob; + +public: + void setText(const QString& text) override; + QWidget* topWidget() override; + + void setModel(AutomatableModel* model) override; + FloatModel* model() override; + class AutomatableModelView* modelView() override; + + KnobControl(QWidget* parent = nullptr); + ~KnobControl() override; +}; + + +class ComboControl : public Control +{ + QWidget* m_widget; + class ComboBox* m_combo; + class QLabel* m_label; + +public: + void setText(const QString& text) override; + QWidget* topWidget() override { return m_widget; } + + void setModel(AutomatableModel* model) override; + ComboBoxModel* model() override; + class AutomatableModelView* modelView() override; + + ComboControl(QWidget* parent = nullptr); + ~ComboControl() override; +}; + + +class LcdControl : public Control +{ + class LcdSpinBox* m_lcd; + +public: + void setText(const QString& text) override; + QWidget* topWidget() override; + + void setModel(AutomatableModel* model) override; + IntModel* model() override; + class AutomatableModelView* modelView() override; + + LcdControl(int numDigits, QWidget* parent = nullptr); + ~LcdControl() override; +}; + + +class CheckControl : public Control +{ + QWidget* m_widget; + class LedCheckBox* m_checkBox; + QLabel* m_label; + +public: + void setText(const QString& text) override; + QWidget* topWidget() override; + + void setModel(AutomatableModel* model) override; + BoolModel *model() override; + class AutomatableModelView* modelView() override; + + CheckControl(QWidget* parent = nullptr); + ~CheckControl() override; +}; + + +#endif // CONTROLS_H diff --git a/include/CustomTextKnob.h b/include/CustomTextKnob.h new file mode 100644 index 00000000000..baaf8820599 --- /dev/null +++ b/include/CustomTextKnob.h @@ -0,0 +1,30 @@ +/* Text customizable knob */ +#ifndef CUSTOM_TEXT_KNOB_H +#define CUSTOM_TEXT_KNOB_H + +#include "Knob.h" + +class LMMS_EXPORT CustomTextKnob : public Knob +{ +protected: + inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible +public: + CustomTextKnob( knobTypes _knob_num, QWidget * _parent = NULL, const QString & _name = QString(), const QString & _value_text = QString() ); + + CustomTextKnob( QWidget * _parent = NULL, const QString & _name = QString(), const QString & _value_text = QString() ); //!< default ctor + + CustomTextKnob( const Knob& other ) = delete; + + inline void setValueText(const QString & _value_text) + { + m_value_text = _value_text; + } + +private: + virtual QString displayValue() const; + +protected: + QString m_value_text; +} ; + +#endif diff --git a/include/DetuningHelper.h b/include/DetuningHelper.h index de0acc82603..2157b6ba828 100644 --- a/include/DetuningHelper.h +++ b/include/DetuningHelper.h @@ -43,17 +43,17 @@ class DetuningHelper : public InlineAutomation { } - virtual float defaultValue() const + float defaultValue() const override { return 0; } - virtual QString displayName() const + QString displayName() const override { return tr( "Note detuning" ); } - inline virtual QString nodeName() const + inline QString nodeName() const override { return "detuning"; } diff --git a/include/DummyEffect.h b/include/DummyEffect.h index 4f770af3ca3..5509131be73 100644 --- a/include/DummyEffect.h +++ b/include/DummyEffect.h @@ -53,25 +53,25 @@ class DummyEffectControls : public EffectControls { } - virtual int controlCount() + int controlCount() override { return 0; } - virtual void saveSettings( QDomDocument &, QDomElement & ) + void saveSettings( QDomDocument &, QDomElement & ) override { } - virtual void loadSettings( const QDomElement & ) + void loadSettings( const QDomElement & ) override { } - virtual QString nodeName() const + QString nodeName() const override { return "DummyControls"; } - virtual EffectControlDialog * createView() + EffectControlDialog * createView() override { return new DummyEffectControlDialog( this ); } @@ -95,12 +95,12 @@ class DummyEffect : public Effect { } - virtual EffectControls * controls() + EffectControls * controls() override { return &m_controls; } - bool processAudioBuffer( sampleFrame *, const fpp_t ) + bool processAudioBuffer( sampleFrame *, const fpp_t ) override { return false; } diff --git a/include/DummyInstrument.h b/include/DummyInstrument.h index b69594b0013..a37b089ae4f 100644 --- a/include/DummyInstrument.h +++ b/include/DummyInstrument.h @@ -47,28 +47,28 @@ class DummyInstrument : public Instrument { } - virtual void playNote( NotePlayHandle *, sampleFrame * buffer ) + void playNote( NotePlayHandle *, sampleFrame * buffer ) override { memset( buffer, 0, sizeof( sampleFrame ) * Engine::mixer()->framesPerPeriod() ); } - virtual void saveSettings( QDomDocument &, QDomElement & ) + void saveSettings( QDomDocument &, QDomElement & ) override { } - virtual void loadSettings( const QDomElement & ) + void loadSettings( const QDomElement & ) override { } - virtual QString nodeName() const + QString nodeName() const override { return "dummyinstrument"; } - virtual PluginView * instantiateView( QWidget * _parent ) + PluginView * instantiateView( QWidget * _parent ) override { - return new InstrumentView( this, _parent ); + return new InstrumentViewFixedSize( this, _parent ); } } ; diff --git a/include/DummyPlugin.h b/include/DummyPlugin.h index 49475a2ac4c..ec26da0a34c 100644 --- a/include/DummyPlugin.h +++ b/include/DummyPlugin.h @@ -42,22 +42,22 @@ class DummyPlugin : public Plugin { } - virtual void saveSettings( QDomDocument &, QDomElement & ) + void saveSettings( QDomDocument &, QDomElement & ) override { } - virtual void loadSettings( const QDomElement & ) + void loadSettings( const QDomElement & ) override { } - virtual QString nodeName() const + QString nodeName() const override { return "DummyPlugin"; } protected: - virtual PluginView * instantiateView( QWidget * _parent ) + PluginView * instantiateView( QWidget * _parent ) override { return new PluginView( this, _parent ); } diff --git a/include/Editor.h b/include/Editor.h index 26b70ec8791..d755608a6c9 100644 --- a/include/Editor.h +++ b/include/Editor.h @@ -28,6 +28,12 @@ #include #include +static const int Quantizations[] = { + 1, 2, 4, 8, 16, 32, 64, + 3, 6, 12, 24, 48, 96, 192 +}; + + class QAction; class DropToolBar; @@ -47,7 +53,7 @@ class Editor : public QMainWindow DropToolBar * addDropToolBar(Qt::ToolBarArea whereToAdd, QString const & windowTitle); DropToolBar * addDropToolBar(QWidget * parent, Qt::ToolBarArea whereToAdd, QString const & windowTitle); - virtual void closeEvent( QCloseEvent * _ce ); + void closeEvent( QCloseEvent * _ce ) override; protected slots: virtual void play() {} virtual void record() {} @@ -58,6 +64,11 @@ protected slots: private slots: /// Called by pressing the space key. Plays or stops. void togglePlayStop(); + + /// Called by pressing shift+space. Toggles pause state. + void togglePause(); + + void toggleMaximize(); signals: @@ -92,8 +103,8 @@ class DropToolBar : public QToolBar void dropped(QDropEvent* event); protected: - void dragEnterEvent(QDragEnterEvent* event); - void dropEvent(QDropEvent* event); + void dragEnterEvent(QDragEnterEvent* event) override; + void dropEvent(QDropEvent* event) override; }; diff --git a/include/Effect.h b/include/Effect.h index 4dc50e8a478..3874aa602ca 100644 --- a/include/Effect.h +++ b/include/Effect.h @@ -47,10 +47,10 @@ class LMMS_EXPORT Effect : public Plugin const Descriptor::SubPluginFeatures::Key * _key ); virtual ~Effect(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; - inline virtual QString nodeName() const + inline QString nodeName() const override { return "effect"; } @@ -170,7 +170,7 @@ class LMMS_EXPORT Effect : public Plugin */ void checkGate( double _out_sum ); - virtual PluginView * instantiateView( QWidget * ); + PluginView * instantiateView( QWidget * ) override; // some effects might not be capable of higher sample-rates so they can // sample it down before processing and back after processing diff --git a/include/EffectChain.h b/include/EffectChain.h index bc1e7df8c68..9ebc4d534b3 100644 --- a/include/EffectChain.h +++ b/include/EffectChain.h @@ -40,10 +40,10 @@ class LMMS_EXPORT EffectChain : public Model, public SerializingObject EffectChain( Model * _parent ); virtual ~EffectChain(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; - inline virtual QString nodeName() const + inline QString nodeName() const override { return "fxchain"; } diff --git a/include/EffectControlDialog.h b/include/EffectControlDialog.h index 712f3121792..4a59489da20 100644 --- a/include/EffectControlDialog.h +++ b/include/EffectControlDialog.h @@ -40,13 +40,15 @@ class LMMS_EXPORT EffectControlDialog : public QWidget, public ModelView EffectControlDialog( EffectControls * _controls ); virtual ~EffectControlDialog(); + virtual bool isResizable() const {return false;} + signals: void closed(); protected: - virtual void closeEvent( QCloseEvent * _ce ); + void closeEvent( QCloseEvent * _ce ) override; EffectControls * m_effectControls; diff --git a/include/EffectRackView.h b/include/EffectRackView.h index 0cfc04e15f6..698bad7fb25 100644 --- a/include/EffectRackView.h +++ b/include/EffectRackView.h @@ -60,7 +60,7 @@ private slots: private: - virtual void modelChanged(); + void modelChanged() override; inline EffectChain* fxChain() { diff --git a/include/EffectView.h b/include/EffectView.h index 71a0e7128cb..6e994dd7e5b 100644 --- a/include/EffectView.h +++ b/include/EffectView.h @@ -73,9 +73,9 @@ public slots: protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void paintEvent( QPaintEvent * _pe ); - virtual void modelChanged(); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void paintEvent( QPaintEvent * _pe ) override; + void modelChanged() override; private: diff --git a/include/Engine.h b/include/Engine.h index f4ff72fb2fb..8f988a1250e 100644 --- a/include/Engine.h +++ b/include/Engine.h @@ -30,6 +30,7 @@ #include +#include "lmmsconfig.h" #include "lmms_export.h" #include "lmms_basics.h" @@ -87,6 +88,13 @@ class LMMS_EXPORT LmmsCore : public QObject return s_projectJournal; } +#ifdef LMMS_HAVE_LV2 + static class Lv2Manager * getLv2Manager() + { + return s_lv2Manager; + } +#endif + static Ladspa2LMMS * getLADSPAManager() { return s_ladspaManager; @@ -143,6 +151,9 @@ class LMMS_EXPORT LmmsCore : public QObject static ProjectJournal * s_projectJournal; static DummyTrackContainer * s_dummyTC; +#ifdef LMMS_HAVE_LV2 + static class Lv2Manager* s_lv2Manager; +#endif static Ladspa2LMMS * s_ladspaManager; static void* s_dndPluginKey; diff --git a/include/EnvelopeAndLfoParameters.h b/include/EnvelopeAndLfoParameters.h index 4824062f3be..0f691adb0bb 100644 --- a/include/EnvelopeAndLfoParameters.h +++ b/include/EnvelopeAndLfoParameters.h @@ -91,9 +91,9 @@ class LMMS_EXPORT EnvelopeAndLfoParameters : public Model, public JournallingObj } - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - virtual QString nodeName() const + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + QString nodeName() const override { return "el"; } diff --git a/include/EnvelopeAndLfoView.h b/include/EnvelopeAndLfoView.h index 817b0a6ee18..f6d4fd0a8e7 100644 --- a/include/EnvelopeAndLfoView.h +++ b/include/EnvelopeAndLfoView.h @@ -52,12 +52,12 @@ class EnvelopeAndLfoView : public QWidget, public ModelView protected: - virtual void modelChanged(); + void modelChanged() override; - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void dropEvent( QDropEvent * _de ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void paintEvent( QPaintEvent * _pe ); + void dragEnterEvent( QDragEnterEvent * _dee ) override; + void dropEvent( QDropEvent * _de ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void paintEvent( QPaintEvent * _pe ) override; protected slots: diff --git a/include/ExportFilter.h b/include/ExportFilter.h index 950bacbcdaf..3124b477bfa 100644 --- a/include/ExportFilter.h +++ b/include/ExportFilter.h @@ -44,15 +44,15 @@ class LMMS_EXPORT ExportFilter : public Plugin int tempo, int masterPitch, const QString &filename ) = 0; protected: - virtual void saveSettings( QDomDocument &, QDomElement & ) + void saveSettings( QDomDocument &, QDomElement & ) override { } - virtual void loadSettings( const QDomElement & ) + void loadSettings( const QDomElement & ) override { } - virtual QString nodeName() const + QString nodeName() const override { return "import_filter"; } diff --git a/include/ExportProjectDialog.h b/include/ExportProjectDialog.h index 0eedb9722ce..06c1e3011d1 100644 --- a/include/ExportProjectDialog.h +++ b/include/ExportProjectDialog.h @@ -41,14 +41,14 @@ class ExportProjectDialog : public QDialog, public Ui::ExportProjectDialog ExportProjectDialog( const QString & _file_name, QWidget * _parent, bool multi_export ); protected: - virtual void reject( void ); - virtual void closeEvent( QCloseEvent * _ce ); + void reject( void ) override; + void closeEvent( QCloseEvent * _ce ) override; private slots: void startBtnClicked( void ); void updateTitleBar( int ); - void accept(); + void accept() override; void startExport(); void onFileFormatChanged(int); diff --git a/include/FadeButton.h b/include/FadeButton.h index 95753ecea90..54703d19476 100644 --- a/include/FadeButton.h +++ b/include/FadeButton.h @@ -35,8 +35,10 @@ class FadeButton : public QAbstractButton { Q_OBJECT public: - FadeButton( const QColor & _normal_color, const QColor & - _activated_color, QWidget * _parent ); + FadeButton( const QColor & _normal_color, + const QColor & _activated_color, + const QColor & _hold_color, + QWidget * _parent ); virtual ~FadeButton(); void setActiveColor( const QColor & activated_color ); @@ -44,22 +46,29 @@ class FadeButton : public QAbstractButton public slots: void activate(); + void activateOnce(); + void noteEnd(); protected: - virtual void customEvent( QEvent * ); - virtual void paintEvent( QPaintEvent * _pe ); + void paintEvent( QPaintEvent * _pe ) override; private: QTime m_stateTimer; + QTime m_releaseTimer; + + // the default color of the widget QColor m_normalColor; + // the color on note play QColor m_activatedColor; + // the color after the "play" fade is done but a note is still playing + QColor m_holdColor; + int activeNotes; - void signalUpdate(); + QColor fadeToColor(QColor, QColor, QTime, float); } ; #endif - diff --git a/include/Fader.h b/include/Fader.h index 018f66e0cc0..2072154459d 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -109,13 +109,13 @@ class LMMS_EXPORT Fader : public QWidget, public FloatModelView } private: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void mousePressEvent( QMouseEvent *ev ); - virtual void mouseDoubleClickEvent( QMouseEvent* mouseEvent ); - virtual void mouseMoveEvent( QMouseEvent *ev ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void wheelEvent( QWheelEvent *ev ); - virtual void paintEvent( QPaintEvent *ev ); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void mousePressEvent( QMouseEvent *ev ) override; + void mouseDoubleClickEvent( QMouseEvent* mouseEvent ) override; + void mouseMoveEvent( QMouseEvent *ev ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; + void wheelEvent( QWheelEvent *ev ) override; + void paintEvent( QPaintEvent *ev ) override; inline bool clips(float const & value) const { return value >= 1.0f; } diff --git a/include/FileBrowser.h b/include/FileBrowser.h index 4b92dd5496d..d36eacf0775 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -48,6 +48,14 @@ class FileBrowser : public SideBarWidget { Q_OBJECT public: + /** + Create a file browser side bar widget + @param directories '*'-separated list of directories to search for. + If a directory of factory files should be in the list it + must be the last one (for the factory files delimiter to work) + @param filter Filter as used in QDir::match + @param recurse *to be documented* + */ FileBrowser( const QString & directories, const QString & filter, const QString & title, const QPixmap & pm, QWidget * parent, bool dirs_as_items = false, bool recurse = false ); @@ -61,7 +69,7 @@ private slots: void giveFocusToFilter(); private: - virtual void keyPressEvent( QKeyEvent * ke ); + void keyPressEvent( QKeyEvent * ke ) override; void addItems( const QString & path ); @@ -69,8 +77,8 @@ private slots: QLineEdit * m_filterEdit; - QString m_directories; - QString m_filter; + QString m_directories; //!< Directories to search, split with '*' + QString m_filter; //!< Filter as used in QDir::match() bool m_dirsAsItems; bool m_recurse; @@ -93,10 +101,10 @@ class FileBrowserTreeWidget : public QTreeWidget protected: - virtual void contextMenuEvent( QContextMenuEvent * e ); - virtual void mousePressEvent( QMouseEvent * me ); - virtual void mouseMoveEvent( QMouseEvent * me ); - virtual void mouseReleaseEvent( QMouseEvent * me ); + void contextMenuEvent( QContextMenuEvent * e ) override; + void mousePressEvent( QMouseEvent * me ) override; + void mouseMoveEvent( QMouseEvent * me ) override; + void mouseReleaseEvent( QMouseEvent * me ) override; private: @@ -119,6 +127,7 @@ private slots: void openInNewInstrumentTrackSE( void ); void sendToActiveInstrumentTrack( void ); void updateDirectory( QTreeWidgetItem * item ); + void openContainingFolder(); } ; @@ -163,7 +172,14 @@ class Directory : public QTreeWidgetItem static QPixmap * s_folderOpenedPixmap; static QPixmap * s_folderLockedPixmap; + //! Directories that lead here + //! Initially, this is just set to the current path of a directory + //! If, however, you have e.g. 'TripleOscillator/xyz' in two of the + //! file browser's search directories 'a' and 'b', this will have two + //! entries 'a/TripleOscillator' and 'b/TripleOscillator' + //! and 'xyz' in the tree widget QStringList m_directories; + //! Filter as used in QDir::match() QString m_filter; int m_dirCount; diff --git a/include/FxLine.h b/include/FxLine.h index 6024026bdb3..e9ee248b811 100644 --- a/include/FxLine.h +++ b/include/FxLine.h @@ -26,10 +26,12 @@ #ifndef FX_LINE_H #define FX_LINE_H +#include #include #include #include +#include "ColorChooser.h" #include "Knob.h" #include "LcdWidget.h" #include "SendButtonIndicator.h" @@ -51,10 +53,10 @@ class FxLine : public QWidget FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex); ~FxLine(); - virtual void paintEvent( QPaintEvent * ); - virtual void mousePressEvent( QMouseEvent * ); - virtual void mouseDoubleClickEvent( QMouseEvent * ); - virtual void contextMenuEvent( QContextMenuEvent * ); + void paintEvent( QPaintEvent * ) override; + void mousePressEvent( QMouseEvent * ) override; + void mouseDoubleClickEvent( QMouseEvent * ) override; + void contextMenuEvent( QContextMenuEvent * ) override; inline int channelIndex() { return m_channelIndex; } void setChannelIndex(int index); @@ -79,9 +81,7 @@ class FxLine : public QWidget static const int FxLineHeight; - void renameChannel(); - - bool eventFilter (QObject *dist, QEvent *event); + bool eventFilter (QObject *dist, QEvent *event) override; private: void drawFxLine( QPainter* p, const FxLine *fxLine, bool isActive, bool sendToThis, bool receiveFromThis ); @@ -101,6 +101,12 @@ class FxLine : public QWidget QLineEdit * m_renameLineEdit; QGraphicsView * m_view; +public slots: + void renameChannel(); + void resetColor(); + void changeColor(); + void randomColor(); + private slots: void renameFinished(); void removeChannel(); diff --git a/include/FxLineLcdSpinBox.h b/include/FxLineLcdSpinBox.h index fa001b2bbe8..eeb104c5c41 100644 --- a/include/FxLineLcdSpinBox.h +++ b/include/FxLineLcdSpinBox.h @@ -42,8 +42,8 @@ class FxLineLcdSpinBox : public LcdSpinBox void setTrackView(TrackView * tv); protected: - virtual void mouseDoubleClickEvent(QMouseEvent* event); - virtual void contextMenuEvent(QContextMenuEvent* event); + void mouseDoubleClickEvent(QMouseEvent* event) override; + void contextMenuEvent(QContextMenuEvent* event) override; private: TrackView * m_tv; diff --git a/include/FxMixer.h b/include/FxMixer.h index 2c7ef3c5ae5..920d4e27bc3 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -32,6 +32,8 @@ #include +#include + class FxRoute; typedef QVector FxRouteVector; @@ -67,16 +69,21 @@ class FxChannel : public ThreadableJob // pointers to other channels that send to this one FxRouteVector m_receives; - virtual bool requiresProcessing() const { return true; } + bool requiresProcessing() const override { return true; } void unmuteForSolo(); + + // TODO C++17 and above: use std::optional insteads + QColor m_color; + bool m_hasColor; + std::atomic_int m_dependenciesMet; void incrementDeps(); void processed(); private: - virtual void doProcessing(); + void doProcessing() override; }; @@ -133,10 +140,10 @@ class LMMS_EXPORT FxMixer : public Model, public JournallingObject void prepareMasterMix(); void masterMix( sampleFrame * _buf ); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; - virtual QString nodeName() const + QString nodeName() const override { return "fxmixer"; } diff --git a/include/FxMixerView.h b/include/FxMixerView.h index 9b07637edef..a7662321ac7 100644 --- a/include/FxMixerView.h +++ b/include/FxMixerView.h @@ -64,10 +64,10 @@ class LMMS_EXPORT FxMixerView : public QWidget, public ModelView, FxMixerView(); virtual ~FxMixerView(); - virtual void keyPressEvent(QKeyEvent * e); + void keyPressEvent(QKeyEvent * e) override; - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; + void loadSettings( const QDomElement & _this ) override; inline FxLine * currentFxLine() { @@ -110,7 +110,7 @@ public slots: int addNewChannel(); protected: - virtual void closeEvent( QCloseEvent * _ce ); + void closeEvent( QCloseEvent * _ce ) override; private slots: void updateFaders(); diff --git a/include/Graph.h b/include/Graph.h index 1bee05c4118..2a6fc4f8a15 100644 --- a/include/Graph.h +++ b/include/Graph.h @@ -87,19 +87,19 @@ class LMMS_EXPORT Graph : public QWidget, public ModelView signals: void drawn(); protected: - virtual void paintEvent( QPaintEvent * _pe ); - virtual void dropEvent( QDropEvent * _de ); - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseMoveEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); + void paintEvent( QPaintEvent * _pe ) override; + void dropEvent( QDropEvent * _de ) override; + void dragEnterEvent( QDragEnterEvent * _dee ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseMoveEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; protected slots: void updateGraph( int _startPos, int _endPos ); void updateGraph(); private: - virtual void modelChanged(); + void modelChanged() override; void changeSampleAt( int _x, int _y ); void drawLineAt( int _x, int _y, int _lastx ); diff --git a/include/GroupBox.h b/include/GroupBox.h index 8a857199fac..88428b1aaef 100644 --- a/include/GroupBox.h +++ b/include/GroupBox.h @@ -42,7 +42,7 @@ class GroupBox : public QWidget, public BoolModelView GroupBox( const QString & _caption, QWidget * _parent = NULL ); virtual ~GroupBox(); - virtual void modelChanged(); + void modelChanged() override; PixmapButton * ledButton() { @@ -56,8 +56,8 @@ class GroupBox : public QWidget, public BoolModelView protected: - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void paintEvent( QPaintEvent * _pe ); + void mousePressEvent( QMouseEvent * _me ) override; + void paintEvent( QPaintEvent * _pe ) override; private: diff --git a/include/IPCHelper.h b/include/IPCHelper.h new file mode 100644 index 00000000000..ff83b261446 --- /dev/null +++ b/include/IPCHelper.h @@ -0,0 +1,744 @@ +/* + * IPC.h - Inter-Process Communication helpers + * + * Copyright (c) 2008-2014 Tobias Doerffel + * Copyright (c) 2016 Javier Serrano Polo + * Copyright (c) 2020 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef IPCHELPER_H +#define IPCHELPER_H + +#include "lmmsconfig.h" + +#include +#include +#include +#include + +// Common headers +#ifdef LMMS_HAVE_LOCALE_H +#include +#endif + +#ifdef LMMS_HAVE_PTHREAD_H +#include +#endif + + +#ifdef LMMS_HAVE_PROCESS_H +#include +#endif + +// Conditionals +#if !defined(LMMS_HAVE_SEMAPHORE_H) || defined(LMMS_BUILD_WIN32) +#define USE_QT_SEMAPHORES +#endif + +#if !(defined(LMMS_HAVE_SYS_IPC_H) && defined(LMMS_HAVE_SYS_SHM_H)) +#define USE_QT_SHMEM +#endif + +#if !(defined(LMMS_HAVE_SYS_SOCKET_H) && defined(LMMS_HAVE_SYS_UN_H)) +#define SYNC_WITH_SHM_FIFO +#endif + +// Error: POSIX semaphores break interoperability between 32bit and 64bit +#if defined(SYNC_WITH_SHM_FIFO) && !defined(USE_QT_SEMAPHORES) +#error "Trying to use POSIX semaphores which breaks interoperability!" +#endif + +// TODO: check if we're mixing POSIX/SysV APIs and Qt APIs + +// Semaphores +#ifdef USE_QT_SEMAPHORES // Qt semaphores +#include +#include +typedef QSystemSemaphore IPCSemaphore; +#else // POSIX semaphores +// Not used because of interoperability issues between 32bit and 64bit +// https://sourceware.org/bugzilla/show_bug.cgi?id=17980 +#if 0 +class IPCSemaphorePOSIX +{ + // TODO fill this once we use it + ; +}; + +typedef IPCSemaphorePOSIX IPCSemaphore; +#endif +#endif // end semaphores + + + +// Shared memory +// TODO add POSIX shared memory +#if !defined(LMMS_HAVE_SYS_TYPES_H) || defined(LMMS_BUILD_WIN32) +typedef int32_t key_t; +#else +#include +#endif + +#ifndef USE_QT_SHMEM // System-V shm +#include +#include +#ifdef LMMS_HAVE_UNISTD_H +#include +#endif + +class SharedMemorySysV +{ +public: + SharedMemorySysV(key_t key = 1) : + m_key(key), m_shmID(-1), m_data(nullptr), m_size(0), m_isMaster(false) + {} + ~SharedMemorySysV() + { + this->detach(); + } + + inline key_t key() const { return m_key; } + inline void setKey(key_t key) { this->detach(); m_key = key; } + inline void* get() { return m_data; } + inline size_t size() const { return m_size; } + + inline void* attach(bool readOnly = false) + { + if (!m_isMaster) + { + m_shmID = shmget(m_key, 0, readOnly ? 0400 : 0600); + } + if (m_shmID == -1) + { + return nullptr; + } + m_data = shmat(m_shmID, 0, readOnly ? SHM_RDONLY : 0); + if (m_data == reinterpret_cast(-1)) + { + m_size = 0; + m_data = nullptr; + } + if (!m_isMaster) + { + // get size + shmid_ds shmid_ds; + if (shmctl(m_shmID, IPC_STAT, &shmid_ds) != -1) + { + m_size = static_cast(shmid_ds.shm_segsz); + } + } + return m_data; + } + + inline bool detach() + { + if (m_shmID == -1) + { + return false; + } + m_size = 0; + if (shmdt(m_data) != -1) + { + return false; + } + m_data = nullptr; + if (m_isMaster) + { + if (shmctl(m_shmID, IPC_RMID, nullptr) == -1 && errno != EINVAL) + { + return false; + } + } + m_shmID = -1; + return true; + } + + inline void* create(size_t size, bool readOnly = false) + { + m_shmID = shmget(m_key, size, IPC_CREAT | IPC_EXCL | 0600); + if (m_shmID == -1) + { + return nullptr; + } + fprintf(stderr, "CREAT %d\n", m_key); + m_isMaster = true; + m_size = size; + return this->attach(); + } + + std::string errorMessage() + { + return std::string(strerror(errno)); + } + +private: + key_t m_key; + int m_shmID; + void *m_data; + size_t m_size; + bool m_isMaster; +}; + +typedef SharedMemorySysV SharedMemory; + +#else // Qt shm +#include +#include + +class SharedMemoryQt +{ +public: + SharedMemoryQt(key_t key = 1) : + m_shm() + { + setKey(key); + } + ~SharedMemoryQt() = default; + + inline key_t key() const { return m_key; } + inline void setKey(key_t key) { m_key = key; m_shm.setKey(QString::number(key)); } + inline void* get() { return m_shm.data(); } + inline size_t size() const { return m_shm.size(); } + + inline void* attach(bool readOnly = false) + { + if (!m_shm.attach(readOnly ? QSharedMemory::ReadOnly : QSharedMemory::ReadWrite)) + { + return nullptr; + } + return m_shm.data(); + } + + inline bool detach() + { + return m_shm.detach(); + } + + inline void* create(size_t size) + { + if (!m_shm.create(size, QSharedMemory::ReadWrite)) + { + return nullptr; + } + return m_shm.data(); + } + + std::string errorMessage() + { + return m_shm.errorString().toStdString(); + } + +private: + key_t m_key; + QSharedMemory m_shm; +}; + +typedef SharedMemoryQt SharedMemory; + +#endif // End shared memory + +// TODO move to a namespace or SharedMemory class? +inline static void *createShmWithFreeKey(SharedMemory &shm, size_t size, key_t &key) +{ + do + { + shm.setKey(++key); + } while (!shm.create(size)); + return shm.get(); +} + + +// Communication channel: shm FIFO vs. socket +#ifdef SYNC_WITH_SHM_FIFO +// sometimes we need to exchange bigger messages (e.g. for VST parameter dumps) +// so set a usable value here +const int SHM_FIFO_SIZE = 512*1024; + +// TODO: reformat and refactor +// Don't rely on QSystemSemaphore +// implements a FIFO inside a shared memory segment +class ShmFifo +{ + // need this union to handle different sizes of sem_t on 32 bit + // and 64 bit platforms + union sem32_t + { + int semKey; + char fill[32]; + }; + struct ShmData + { + sem32_t dataSem; // semaphore for locking this + // FIFO management data + sem32_t messageSem; // semaphore for incoming messages + volatile int32_t startPtr; // current start of FIFO in memory + volatile int32_t endPtr; // current end of FIFO in memory + char data[SHM_FIFO_SIZE]; // actual data + }; + +public: + // constructor for master-side + ShmFifo() : + m_invalid(false), + m_master(true), + m_shmKey(0), + m_shmObj(), + m_data(nullptr), + m_dataSem(QString()), + m_messageSem(QString()), + m_lockDepth(0) + { + m_data = (ShmData *)createShmWithFreeKey(m_shmObj, sizeof(ShmData), m_shmKey); + + assert(m_data != NULL); + m_data->startPtr = m_data->endPtr = 0; + static int k = 0; + m_data->dataSem.semKey = (getpid()<<10) + ++k; + m_data->messageSem.semKey = (getpid()<<10) + ++k; + m_dataSem.setKey(QString::number(m_data->dataSem.semKey), + 1, QSystemSemaphore::Create); + m_messageSem.setKey(QString::number( + m_data->messageSem.semKey), + 0, QSystemSemaphore::Create); + } + + // constructor for remote-/client-side - use shmKey for making up + // the connection to master + ShmFifo(key_t shmKey) : + m_invalid(false), + m_master(false), + m_shmKey(0), + m_shmObj(shmKey), + m_data(NULL), + m_dataSem(QString()), + m_messageSem(QString()), + m_lockDepth(0) + { + m_data = (ShmData*)m_shmObj.attach(); + assert(m_data != NULL); + m_dataSem.setKey(QString::number(m_data->dataSem.semKey)); + m_messageSem.setKey(QString::number( + m_data->messageSem.semKey)); + } + + ~ShmFifo() + { + } + + inline bool isInvalid() const + { + return m_invalid; + } + + void invalidate() + { + m_invalid = true; + } + + // do we act as master (i.e. not as remote-process?) + inline bool isMaster() const + { + return m_master; + } + + // recursive lock + inline void lock() + { + if (!isInvalid() && m_lockDepth.fetch_add(1) == 0) + { + m_dataSem.acquire(); + } + } + + // recursive unlock + inline void unlock() + { + if (m_lockDepth.fetch_sub(1) <= 1) + { + m_dataSem.release(); + } + } + + // wait until message-semaphore is available + inline void waitForMessage() + { + if (!isInvalid()) + { + m_messageSem.acquire(); + } + } + + // increase message-semaphore + inline void messageSent() + { + m_messageSem.release(); + } + + + inline int32_t readInt() + { + int32_t i; + read(&i, sizeof(i)); + return i; + } + + inline void writeInt(const int32_t &i) + { + write(&i, sizeof(i)); + } + + inline std::string readString() + { + const int len = readInt(); + if (len) + { + char * sc = new char[len + 1]; + read(sc, len); + sc[len] = 0; + std::string s(sc); + delete[] sc; + return s; + } + return std::string(); + } + + + inline void writeString(const std::string &s) + { + const int len = s.size(); + writeInt(len); + write(s.c_str(), len); + } + + + inline bool messagesLeft() + { + if (isInvalid()) + { + return false; + } + lock(); + const bool empty = (m_data->startPtr == m_data->endPtr); + unlock(); + return !empty; + } + + + inline int shmKey() const + { + return m_shmKey; + } + + +private: + static inline void fastMemCpy(void * dest, const void * src, + const int len) + { + // calling memcpy() for just an integer is obsolete overhead + if (len == 4) + { + *((int32_t *) dest) = *((int32_t *) src); + } + else + { + memcpy(dest, src, len); + } + } + + void read(void * buf, int len) + { + if (isInvalid()) + { + memset(buf, 0, len); + return; + } + lock(); + while (isInvalid() == false && + len > m_data->endPtr - m_data->startPtr) + { + unlock(); +#ifndef LMMS_BUILD_WIN32 + usleep(5); +#endif + lock(); + } + fastMemCpy(buf, m_data->data + m_data->startPtr, len); + m_data->startPtr += len; + // nothing left? + if (m_data->startPtr == m_data->endPtr) + { + // then reset to 0 + m_data->startPtr = m_data->endPtr = 0; + } + unlock(); + } + + void write(const void * buf, int len) + { + if (isInvalid() || len > SHM_FIFO_SIZE) + { + return; + } + lock(); + while (len > SHM_FIFO_SIZE - m_data->endPtr) + { + // if no space is left, try to move data to front + if (m_data->startPtr > 0) + { + memmove(m_data->data, + m_data->data + m_data->startPtr, + m_data->endPtr - m_data->startPtr); + m_data->endPtr = m_data->endPtr - + m_data->startPtr; + m_data->startPtr = 0; + } + unlock(); +#ifndef LMMS_BUILD_WIN32 + usleep(5); +#endif + lock(); + } + fastMemCpy(m_data->data + m_data->endPtr, buf, len); + m_data->endPtr += len; + unlock(); + } + + volatile bool m_invalid; + bool m_master; + key_t m_shmKey; + SharedMemory m_shmObj; + ShmData * m_data; + QSystemSemaphore m_dataSem; + QSystemSemaphore m_messageSem; + std::atomic_int m_lockDepth; +}; +#else +#include +#include +#include +#include + +/* +// ================================ + struct sockaddr_un sa; + sa.sun_family = AF_LOCAL; + + m_socketFile = QDir::tempPath() + QDir::separator() + + QUuid::createUuid().toString(); + auto path = m_socketFile.toUtf8(); + size_t length = path.length(); + if (length >= sizeof sa.sun_path) + { + length = sizeof sa.sun_path - 1; + qWarning("Socket path too long."); + } + memcpy(sa.sun_path, path.constData(), length); + sa.sun_path[length] = '\0'; + + m_server = socket(PF_LOCAL, SOCK_STREAM, 0); + if (m_server == -1) + { + qWarning("Unable to start the server."); + } + remove(path.constData()); + int ret = bind(m_server, (struct sockaddr *) &sa, sizeof sa); + if (ret == -1 || listen(m_server, 1) == -1) + { + qWarning("Unable to start the server."); + } + +// ================================ + if (close(m_server) == -1) + { + qWarning("Error freeing resources."); + } + remove(m_socketFile.toUtf8().constData()); +// =============================== + + struct pollfd pollin; + pollin.fd = m_server; + pollin.events = POLLIN; + + int retryCount = 0; + int result; + do + { + if (retryCount > 0) + { + qWarning("Retrying to connect to the remote plugin..."); + } + result = poll(&pollin, 1, 30000); + switch (result) + { + case -1: + qWarning("Unexpected poll error."); + break; + + case 0: + qWarning("Remote plugin did not connect."); + break; + + default: + m_socket = accept(m_server, NULL, NULL); + if (m_socket == -1) + { + qWarning("Unexpected socket error."); + } + } + ++retryCount; + } while (result == -1 && retryCount <= 3); +// ================================= + + inline int32_t readInt() + { + int32_t i; + read(&i, sizeof(i)); + return i; + } + + inline void writeInt(const int32_t & _i) + { + write(&_i, sizeof(_i)); + } + + inline std::string readString() + { + const int len = readInt(); + if (len) + { + char * sc = new char[len + 1]; + read(sc, len); + sc[len] = 0; + std::string s(sc); + delete[] sc; + return s; + } + return std::string(); + } + + + inline void writeString(const std::string & _s) + { + const int len = _s.size(); + writeInt(len); + write(_s.c_str(), len); + } +// ============================== + + struct pollfd pollin; + pollin.fd = m_socket; + pollin.events = POLLIN; + + if (poll(&pollin, 1, 0) == -1) + { + qWarning("Unexpected poll error."); + } + return pollin.revents & POLLIN; +// ================================ + + int m_socket; +//================ + + + void read(void * buf, int len) + { + if (isInvalid()) + { + memset(buf, 0, len); + return; + } + char * buf = (char *) buf; + int remaining = len; + while (remaining) + { + ssize_t nread = ::read(m_socket, buf, remaining); + switch (nread) + { + case -1: + fprintf(stderr, + "Error while reading.\n"); + case 0: + invalidate(); + memset(buf, 0, len); + return; + } + buf += nread; + remaining -= nread; + } + } + + void write(const void * buf, int len) + { + if (isInvalid()) + { + return; + } + const char * buf = (const char *) buf; + int remaining = len; + while (remaining) + { + ssize_t nwritten = ::write(m_socket, buf, remaining); + switch (nwritten) + { + case -1: + fprintf(stderr, + "Error while writing.\n"); + case 0: + invalidate(); + return; + } + buf += nwritten; + remaining -= nwritten; + } + } + + + bool m_invalid; + + pthread_mutex_t m_receiveMutex; + pthread_mutex_t m_sendMutex; +// ========================= + + struct sockaddr_un sa; + sa.sun_family = AF_LOCAL; + + size_t length = strlen(socketPath); + if (length >= sizeof sa.sun_path) + { + length = sizeof sa.sun_path - 1; + fprintf(stderr, "Socket path too long.\n"); + } + memcpy(sa.sun_path, socketPath, length); + sa.sun_path[length] = '\0'; + + m_socket = socket(PF_LOCAL, SOCK_STREAM, 0); + if (m_socket == -1) + { + fprintf(stderr, "Could not connect to local server.\n"); + } + if (::connect(m_socket, (struct sockaddr *) &sa, sizeof sa) == -1) + { + fprintf(stderr, "Could not connect to local server.\n"); + } +*/ +#endif // SYNC_WITH_SHM_FIFO + +#endif // IPCHELPER_H diff --git a/include/ImportFilter.h b/include/ImportFilter.h index 166c1bfda88..3b1cab33769 100644 --- a/include/ImportFilter.h +++ b/include/ImportFilter.h @@ -26,12 +26,14 @@ #ifndef IMPORT_FILTER_H #define IMPORT_FILTER_H -#include +#include +#include #include "Plugin.h" class TrackContainer; +class QJsonValue; class LMMS_EXPORT ImportFilter : public Plugin @@ -44,12 +46,13 @@ class LMMS_EXPORT ImportFilter : public Plugin // tries to import given file to given track-container by having all // available import-filters to try to import the file - static void import( const QString & _file_to_import, - TrackContainer* tc ); + static void import(const QString & fileToImport, + TrackContainer* tc, + QJsonValue config = QJsonValue()); protected: - virtual bool tryImport( TrackContainer* tc ) = 0; + virtual bool tryImport(TrackContainer* tc, QJsonValue config = QJsonValue()) = 0; const QFile & file() const { @@ -89,15 +92,15 @@ class LMMS_EXPORT ImportFilter : public Plugin m_file.ungetChar( _ch ); } - virtual void saveSettings( QDomDocument &, QDomElement & ) + void saveSettings( QDomDocument &, QDomElement & ) override { } - virtual void loadSettings( const QDomElement & ) + void loadSettings( const QDomElement & ) override { } - virtual QString nodeName() const + QString nodeName() const override { return "import_filter"; } diff --git a/include/InlineAutomation.h b/include/InlineAutomation.h index d70121a45c9..431ecbc81be 100644 --- a/include/InlineAutomation.h +++ b/include/InlineAutomation.h @@ -79,8 +79,8 @@ class InlineAutomation : public FloatModel, public sharedObject return m_autoPattern; } - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; private: diff --git a/include/Instrument.h b/include/Instrument.h index 2179a1f721f..1dbf1ba5816 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -110,7 +110,7 @@ class LMMS_EXPORT Instrument : public Plugin return true; } - virtual QString fullDisplayName() const; + QString fullDisplayName() const override; // -------------------------------------------------------------------- // provided functions: @@ -132,6 +132,9 @@ class LMMS_EXPORT Instrument : public Plugin protected: + // fade in to prevent clicks + void applyFadeIn(sampleFrame * buf, NotePlayHandle * n); + // instruments may use this to apply a soft fade out at the end of // notes - method does this only if really less or equal // desiredReleaseFrames() frames are left diff --git a/include/InstrumentFunctionViews.h b/include/InstrumentFunctionViews.h index 8ac13e1b9da..58f915b15ba 100644 --- a/include/InstrumentFunctionViews.h +++ b/include/InstrumentFunctionViews.h @@ -49,7 +49,7 @@ class InstrumentFunctionNoteStackingView : public QWidget, public ModelView private: - virtual void modelChanged(); + void modelChanged() override; InstrumentFunctionNoteStacking * m_cc; @@ -72,7 +72,7 @@ class InstrumentFunctionArpeggioView : public QWidget, public ModelView private: - virtual void modelChanged(); + void modelChanged() override; InstrumentFunctionArpeggio * m_a; GroupBox * m_arpGroupBox; diff --git a/include/InstrumentFunctions.h b/include/InstrumentFunctions.h index 0055c6c97ce..b45484e7193 100644 --- a/include/InstrumentFunctions.h +++ b/include/InstrumentFunctions.h @@ -54,10 +54,10 @@ class InstrumentFunctionNoteStacking : public Model, public JournallingObject void processNote( NotePlayHandle* n ); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; - inline virtual QString nodeName() const + inline QString nodeName() const override { return "chordcreator"; } @@ -176,10 +176,10 @@ class InstrumentFunctionArpeggio : public Model, public JournallingObject void processNote( NotePlayHandle* n ); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; - inline virtual QString nodeName() const + inline QString nodeName() const override { return "arpeggiator"; } diff --git a/include/InstrumentMidiIOView.h b/include/InstrumentMidiIOView.h index 38f4419425e..e63b4842575 100644 --- a/include/InstrumentMidiIOView.h +++ b/include/InstrumentMidiIOView.h @@ -47,7 +47,7 @@ class InstrumentMidiIOView : public QWidget, public ModelView private: - virtual void modelChanged(); + void modelChanged() override; GroupBox * m_midiInputGroupBox; LcdSpinBox * m_inputChannelSpinBox; diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h index 426b413ce34..ac5fc322240 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -40,7 +40,7 @@ class LMMS_EXPORT InstrumentPlayHandle : public PlayHandle } - virtual void play( sampleFrame * _working_buffer ) + void play( sampleFrame * _working_buffer ) override { // ensure that all our nph's have been processed first ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack( m_instrument->instrumentTrack(), true ); @@ -65,12 +65,12 @@ class LMMS_EXPORT InstrumentPlayHandle : public PlayHandle m_instrument->play( _working_buffer ); } - virtual bool isFinished() const + bool isFinished() const override { return false; } - virtual bool isFromTrack( const Track* _track ) const + bool isFromTrack( const Track* _track ) const override { return m_instrument->isFromTrack( _track ); } diff --git a/include/InstrumentSoundShaping.h b/include/InstrumentSoundShaping.h index a159f838048..1b8df38d3f1 100644 --- a/include/InstrumentSoundShaping.h +++ b/include/InstrumentSoundShaping.h @@ -57,9 +57,9 @@ class InstrumentSoundShaping : public Model, public JournallingObject float volumeLevel( NotePlayHandle * _n, const f_cnt_t _frame ); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + inline QString nodeName() const override { return "eldata"; } diff --git a/include/InstrumentSoundShapingView.h b/include/InstrumentSoundShapingView.h index a409e8446b2..06d53232ce3 100644 --- a/include/InstrumentSoundShapingView.h +++ b/include/InstrumentSoundShapingView.h @@ -50,7 +50,7 @@ class InstrumentSoundShapingView : public QWidget, public ModelView private: - virtual void modelChanged(); + void modelChanged() override; InstrumentSoundShaping * m_ss; diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index c487438d0f8..4363fc82177 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -38,6 +38,8 @@ #include "Pitch.h" #include "Plugin.h" #include "Track.h" +#include "Midi.h" +#include "MidiCCRackView.h" @@ -80,8 +82,8 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor MidiEvent applyMasterKey( const MidiEvent& event ); - virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); - virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); + void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) override; + void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) override; // silence all running notes played by this track void silenceAllNotes( bool removeIPH = false ); @@ -111,7 +113,7 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor void deleteNotePluginData( NotePlayHandle * _n ); // name-stuff - virtual void setName( const QString & _new_name ); + void setName( const QString & _new_name ) override; // translate given key of a note-event to absolute key (i.e. // add global master-pitch and base-note of this instrument track) @@ -131,18 +133,18 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor // play everything in given frame-range - creates note-play-handles virtual bool play( const MidiTime & _start, const fpp_t _frames, - const f_cnt_t _frame_base, int _tco_num = -1 ); + const f_cnt_t _frame_base, int _tco_num = -1 ) override; // create new view for me - virtual TrackView * createView( TrackContainerView* tcv ); + TrackView * createView( TrackContainerView* tcv ) override; // create new track-content-object = pattern - virtual TrackContentObject * createTCO( const MidiTime & _pos ); + TrackContentObject * createTCO( const MidiTime & _pos ) override; // called by track virtual void saveTrackSpecificSettings( QDomDocument & _doc, - QDomElement & _parent ); - virtual void loadTrackSpecificSettings( const QDomElement & _this ); + QDomElement & _parent ) override; + void loadTrackSpecificSettings( const QDomElement & _this ) override; using Track::setJournalling; @@ -214,6 +216,15 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor void setPreviewMode( const bool ); + bool isPreviewMode() const + { + return m_previewMode; + } + + void autoAssignMidiDevice( bool ); + + BoolModel *m_midiCCEnable; + FloatModel *m_midiCCModel[MidiControllerCount]; signals: void instrumentChanged(); @@ -221,14 +232,20 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor void midiNoteOff( const Note& ); void nameChanged(); void newNote(); + void endNote(); +public slots: + void processCCEvent(int controller); protected: - virtual QString nodeName() const + QString nodeName() const override { return "instrumenttrack"; } + // get the name of the instrument in the saved data + QString getSavedInstrumentName(const QDomElement & thisElement) const; + protected slots: void updateBaseNote(); @@ -252,6 +269,9 @@ protected slots: bool m_previewMode; + bool m_hasAutoMidiDev; + static InstrumentTrack *s_autoAssignedTrack; + IntModel m_baseNoteModel; NotePlayHandleList m_processHandles; @@ -316,23 +336,23 @@ class InstrumentTrackView : public TrackView static void cleanupWindowCache(); // Create a menu for assigning/creating channels for this track - QMenu * createFxMenu( QString title, QString newFxLabel ); + QMenu * createFxMenu( QString title, QString newFxLabel ) override; protected: - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void dropEvent( QDropEvent * _de ); + void dragEnterEvent( QDragEnterEvent * _dee ) override; + void dropEvent( QDropEvent * _de ) override; private slots: void toggleInstrumentWindow( bool _on ); + void toggleMidiCCRack(); void activityIndicatorPressed(); void activityIndicatorReleased(); void midiInSelected(); void midiOutSelected(); void midiConfigChanged(); - void muteChanged(); void assignFxLine( int channelIndex ); void createFxLine(); @@ -354,8 +374,14 @@ private slots: QAction * m_midiInputAction; QAction * m_midiOutputAction; + MidiCCRackView * m_midiCCRackView; + QPoint m_lastPos; + FadeButton * getActivityIndicator() + { + return m_activityIndicator; + } friend class InstrumentTrackWindow; @@ -403,8 +429,8 @@ class InstrumentTrackWindow : public QWidget, public ModelView, static void dragEnterEventGeneric( QDragEnterEvent * _dee ); - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void dropEvent( QDropEvent * _de ); + void dragEnterEvent( QDragEnterEvent * _dee ) override; + void dropEvent( QDropEvent * _de ) override; public slots: @@ -416,11 +442,11 @@ public slots: protected: // capture close-events for toggling instrument-track-button - virtual void closeEvent( QCloseEvent * _ce ); - virtual void focusInEvent( QFocusEvent * _fe ); + void closeEvent( QCloseEvent * _ce ) override; + void focusInEvent( QFocusEvent * _fe ) override; - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; + void loadSettings( const QDomElement & _this ) override; protected slots: @@ -429,7 +455,7 @@ protected slots: void viewPrevInstrument(); private: - virtual void modelChanged(); + void modelChanged() override; void viewInstrumentInDirection(int d); //! adjust size of any child widget of the main tab //! required to keep the old look when using a variable sized tab widget diff --git a/include/InstrumentView.h b/include/InstrumentView.h index 9c6081a775d..838ed2d9121 100644 --- a/include/InstrumentView.h +++ b/include/InstrumentView.h @@ -32,11 +32,12 @@ class InstrumentTrackWindow; +//! Instrument view with variable size class LMMS_EXPORT InstrumentView : public PluginView { public: InstrumentView( Instrument * _instrument, QWidget * _parent ); - virtual ~InstrumentView(); + ~InstrumentView() override; Instrument * model() { @@ -48,11 +49,25 @@ class LMMS_EXPORT InstrumentView : public PluginView return( castModel() ); } - virtual void setModel( Model * _model, bool = false ); + void setModel( Model * _model, bool = false ) override; InstrumentTrackWindow * instrumentTrackWindow(); } ; + + +//! Instrument view with fixed LMMS-default size +class LMMS_EXPORT InstrumentViewFixedSize : public InstrumentView +{ + QSize sizeHint() const override { return QSize(250, 250); } + QSize minimumSizeHint() const override { return sizeHint(); } + +public: + using InstrumentView::InstrumentView; + ~InstrumentViewFixedSize() override; +} ; + + #endif diff --git a/include/JournallingObject.h b/include/JournallingObject.h index 6974bef84da..f4755994b9e 100644 --- a/include/JournallingObject.h +++ b/include/JournallingObject.h @@ -59,9 +59,9 @@ class LMMS_EXPORT JournallingObject : public SerializingObject void addJournalCheckPoint(); virtual QDomElement saveState( QDomDocument & _doc, - QDomElement & _parent ); + QDomElement & _parent ) override; - virtual void restoreState( const QDomElement & _this ); + void restoreState( const QDomElement & _this ) override; inline bool isJournalling() const { diff --git a/include/JsonDataFile.h b/include/JsonDataFile.h new file mode 100644 index 00000000000..d439e58203f --- /dev/null +++ b/include/JsonDataFile.h @@ -0,0 +1,62 @@ +/* + * JsonDataFile.h - a convenient wrapper of QJsonDocument, + * used for managing JSON data files + * + * Copyright (c) 2019 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef JSONDATAFILE_H +#define JSONDATAFILE_H + +#include "lmms_export.h" + +#include +#include +#include + + +class LMMS_EXPORT JsonDataFile : public QJsonDocument +{ +public: + JsonDataFile(); + JsonDataFile(const QString& fileName); + JsonDataFile(const JsonDataFile& other); + JsonDataFile(JsonDataFile&& other); + JsonDataFile(const QJsonDocument& other); + JsonDataFile(QJsonDocument&& other); + JsonDataFile(const QJsonArray& array); + JsonDataFile(const QJsonObject& object); + + JsonDataFile& operator=(const JsonDataFile& other); + JsonDataFile& operator=(JsonDataFile&& other); + JsonDataFile& operator=(const QJsonDocument& other); + JsonDataFile& operator=(QJsonDocument&& other); + + static JsonDataFile fromFile(const QString& fileName); + void readFile(const QString& fileName); + void writeFile(const QString& fileName); + + QJsonValue value(); +}; + + +#endif // #ifndef JSONDATAFILE_H + diff --git a/include/Knob.h b/include/Knob.h index b8d460f4593..b129bc8d690 100644 --- a/include/Knob.h +++ b/include/Knob.h @@ -124,16 +124,16 @@ class LMMS_EXPORT Knob : public QWidget, public FloatModelView protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void dropEvent( QDropEvent * _de ); - virtual void focusOutEvent( QFocusEvent * _fe ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void mouseMoveEvent( QMouseEvent * _me ); - virtual void mouseDoubleClickEvent( QMouseEvent * _me ); - virtual void paintEvent( QPaintEvent * _me ); - virtual void wheelEvent( QWheelEvent * _me ); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void dragEnterEvent( QDragEnterEvent * _dee ) override; + void dropEvent( QDropEvent * _de ) override; + void focusOutEvent( QFocusEvent * _fe ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; + void mouseMoveEvent( QMouseEvent * _me ) override; + void mouseDoubleClickEvent( QMouseEvent * _me ) override; + void paintEvent( QPaintEvent * _me ) override; + void wheelEvent( QWheelEvent * _me ) override; virtual float getValue( const QPoint & _p ); @@ -143,9 +143,9 @@ private slots: void toggleScale(); private: - QString displayValue() const; + virtual QString displayValue() const; - virtual void doConnections(); + void doConnections() override; QLineF calculateLine( const QPointF & _mid, float _radius, float _innerRadius = 1) const; @@ -173,8 +173,7 @@ private slots: BoolModel m_volumeKnob; FloatModel m_volumeRatio; - QPoint m_mouseOffset; - QPoint m_origMousePos; + QPoint m_lastMousePos; //!< mouse position in last mouseMoveEvent float m_leftOver; bool m_buttonPressed; diff --git a/include/LadspaControl.h b/include/LadspaControl.h index 2ad895b3f5a..34f6c9ae218 100644 --- a/include/LadspaControl.h +++ b/include/LadspaControl.h @@ -74,7 +74,7 @@ class LMMS_EXPORT LadspaControl : public Model, public JournallingObject virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent, const QString & _name ); virtual void loadSettings( const QDomElement & _this, const QString & _name ); - inline virtual QString nodeName() const + inline QString nodeName() const override { return "port"; } @@ -92,13 +92,13 @@ protected slots: void linkStateChanged(); protected: - virtual void saveSettings( QDomDocument& doc, QDomElement& element ) + void saveSettings( QDomDocument& doc, QDomElement& element ) override { Q_UNUSED(doc) Q_UNUSED(element) } - virtual void loadSettings( const QDomElement& element ) + void loadSettings( const QDomElement& element ) override { Q_UNUSED(element) } diff --git a/include/LcdSpinBox.h b/include/LcdSpinBox.h index b63dfaa4037..91ac8b4a78c 100644 --- a/include/LcdSpinBox.h +++ b/include/LcdSpinBox.h @@ -40,7 +40,7 @@ class LMMS_EXPORT LcdSpinBox : public LcdWidget, public IntModelView virtual ~LcdSpinBox() = default; - virtual void modelChanged() + void modelChanged() override { ModelView::modelChanged(); update(); @@ -65,16 +65,17 @@ public slots: protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseMoveEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void wheelEvent( QWheelEvent * _we ); - virtual void mouseDoubleClickEvent( QMouseEvent * _me ); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseMoveEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; + void wheelEvent( QWheelEvent * _we ) override; + void mouseDoubleClickEvent( QMouseEvent * _me ) override; private: + float m_remainder; //!< floating offset of spinbox in [-0.5, 0.5] bool m_mouseMoving; - QPoint m_origMousePos; + QPoint m_lastMousePos; //!< mouse position in last mouseMoveEvent int m_displayOffset; void enterValue(); diff --git a/include/LcdWidget.h b/include/LcdWidget.h index db969dd33fd..bdad5cb302b 100644 --- a/include/LcdWidget.h +++ b/include/LcdWidget.h @@ -71,7 +71,7 @@ public slots: protected: - virtual void paintEvent( QPaintEvent * pe ); + void paintEvent( QPaintEvent * pe ) override; virtual void updateSize(); @@ -100,7 +100,7 @@ public slots: int m_numDigits; int m_marginWidth; - void initUi( const QString& name, const QString &style = QString("19green") ); //!< to be called by ctors + void initUi( const QString& name, const QString &style ); //!< to be called by ctors } ; diff --git a/include/LedCheckbox.h b/include/LedCheckbox.h index 723bae6a901..66d7ce07e7e 100644 --- a/include/LedCheckbox.h +++ b/include/LedCheckbox.h @@ -64,7 +64,7 @@ class LMMS_EXPORT LedCheckBox : public AutomatableButton Q_PROPERTY( QString text READ text WRITE setText ) protected: - virtual void paintEvent( QPaintEvent * _pe ); + void paintEvent( QPaintEvent * _pe ) override; private: diff --git a/include/LfoController.h b/include/LfoController.h index 9dfbba6715a..8fc35fd0903 100644 --- a/include/LfoController.h +++ b/include/LfoController.h @@ -49,18 +49,18 @@ class LfoController : public Controller virtual ~LfoController(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); - virtual QString nodeName() const; + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; + void loadSettings( const QDomElement & _this ) override; + QString nodeName() const override; public slots: - virtual ControllerDialog * createDialog( QWidget * _parent ); + ControllerDialog * createDialog( QWidget * _parent ) override; protected: // The internal per-controller value updating function - virtual void updateValueBuffer(); + void updateValueBuffer() override; FloatModel m_baseModel; TempoSyncKnobModel m_speedModel; @@ -98,8 +98,8 @@ class LfoControllerDialog : public ControllerDialog protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void modelChanged(); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void modelChanged() override; LfoController * m_lfo; diff --git a/include/LinkedModelGroupViews.h b/include/LinkedModelGroupViews.h new file mode 100644 index 00000000000..390d2556890 --- /dev/null +++ b/include/LinkedModelGroupViews.h @@ -0,0 +1,107 @@ +/* + * LinkedModelGroupViews.h - view for groups of linkable models + * + * Copyright (c) 2019-2019 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LINKEDMODELGROUPVIEWS_H +#define LINKEDMODELGROUPVIEWS_H + + +#include +#include +#include +#include + + +/** + @file LinkedModelGroupViews.h + See Lv2ViewBase.h for example usage +*/ + + +/** + View for a representative processor + + Features: + * Remove button for removable models + * Simple handling of adding, removing and model changing + + @note Neither this class, nor any inheriting classes, shall inherit + ModelView. The "view" in the name is just for consistency + with LinkedModelGroupsView. +*/ +class LinkedModelGroupView : public QWidget +{ +public: + /** + @param colNum numbers of columns for the controls + (link LEDs not counted) + */ + LinkedModelGroupView(QWidget *parent, class LinkedModelGroup* model, + std::size_t colNum); + ~LinkedModelGroupView(); + + //! Reconnect models if model changed + void modelChanged(class LinkedModelGroup *linkedModelGroup); + +protected: + //! Add a control to this widget + //! @warning This widget will own this control, do not free it + void addControl(class Control *ctrl, const std::string &id, + const std::string& display, bool removable); + + void removeControl(const QString &key); + + void removeFocusFromSearchBar(); + +private: + class LinkedModelGroup* m_model; + + //! column number in surrounding grid in LinkedModelGroupsView + std::size_t m_colNum; + class ControlLayout* m_layout; + std::map> m_widgets; +}; + + +/** + Container class for one LinkedModelGroupView + + @note It's intended this class does not inherit from ModelView. + Inheriting classes need to do that, see e.g. Lv2Instrument.h +*/ +class LinkedModelGroupsView +{ +protected: + ~LinkedModelGroupsView() = default; + + //! Reconnect models if model changed; to be called by child virtuals + void modelChanged(class LinkedModelGroups* ctrlBase); + +private: + //! The base class must return the adressed group view, + //! which has the same value as "this" + virtual LinkedModelGroupView* getGroupView() = 0; +}; + + +#endif // LINKEDMODELGROUPVIEWS_H diff --git a/include/LinkedModelGroups.h b/include/LinkedModelGroups.h new file mode 100644 index 00000000000..355290d9aee --- /dev/null +++ b/include/LinkedModelGroups.h @@ -0,0 +1,175 @@ +/* + * LinkedModelGroups.h - base classes for groups of linked models + * + * Copyright (c) 2019-2019 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LINKEDMODELGROUPS_H +#define LINKEDMODELGROUPS_H + + +#include +#include +#include + +#include "Model.h" + + +/** + @file LinkedModelGroups.h + See Lv2ControlBase.h and Lv2Proc.h for example usage +*/ + + +/** + Base class for a group of linked models + + See the LinkedModelGroup class for explenations + + Features: + * Models are stored by their QObject::objectName + * Models are linked automatically +*/ +class LinkedModelGroup : public Model +{ + Q_OBJECT +public: + /* + Initialization + */ + //! @param parent model of the LinkedModelGroups class + LinkedModelGroup(Model* parent) : Model(parent) {} + + /* + Linking (initially only) + */ + void linkControls(LinkedModelGroup *other); + + /* + Models + */ + struct ModelInfo + { + QString m_name; + class AutomatableModel* m_model; + ModelInfo() { /* hopefully no one will use this */ } // TODO: remove? + ModelInfo(const QString& name, AutomatableModel* model) + : m_name(name), m_model(model) {} + }; + + // TODO: refactor those 2 + template + void foreach_model(const Functor& ftor) + { + for (auto itr = m_models.begin(); itr != m_models.end(); ++itr) + { + ftor(itr->first, itr->second); + } + } + + template + void foreach_model(const Functor& ftor) const + { + for (auto itr = m_models.cbegin(); itr != m_models.cend(); ++itr) + { + ftor(itr->first, itr->second); + } + } + + std::size_t modelNum() const { return m_models.size(); } + bool containsModel(const QString& name) const; + void removeControl(AutomatableModel *); + + /* + Load/Save + */ + void saveValues(class QDomDocument& doc, class QDomElement& that); + void loadValues(const class QDomElement& that); + +signals: + // NOTE: when separating core from UI, this will need to be removed + // (who would kno if the client is Qt, i.e. it may not have slots at all) + // In this case you'd e.g. send the UI something like + // "/added " + void modelAdded(AutomatableModel* added); + void modelRemoved(AutomatableModel* removed); + +public: + AutomatableModel* getModel(const std::string& s) + { + auto itr = m_models.find(s); + return (itr == m_models.end()) ? nullptr : itr->second.m_model; + } + + //! Register a further model + void addModel(class AutomatableModel* model, const QString& name); + //! Unregister a model, return true if a model was erased + bool eraseModel(const QString& name); + + //! Remove all models + void clearModels(); + +private: + //! models for the controls + std::map m_models; +}; + + +/** + Container for a group of linked models + + Each group contains the same models and model types. The models are + numbered, and equal numbered models are associated and always linked. + + A typical application are two mono plugins making a stereo plugin. + + @note Though this class can contain multiple model groups, a corresponding + view ("LinkedModelGroupViews") will only display one group, as they all have + the same values + + @note Though called "container", this class does not contain, but only + know the single groups. The inheriting classes are responsible for storage. +*/ +class LinkedModelGroups +{ +public: + virtual ~LinkedModelGroups(); + + void linkAllModels(); + + /* + Load/Save + */ + void saveSettings(class QDomDocument& doc, class QDomElement& that); + void loadSettings(const class QDomElement& that); + + /* + General + */ + //! Derived classes must return the group with index @p idx, + //! or nullptr if @p is out of range + virtual LinkedModelGroup* getGroup(std::size_t idx) = 0; + //! @see getGroup + virtual const LinkedModelGroup* getGroup(std::size_t idx) const = 0; +}; + + +#endif // LINKEDMODELGROUPS_H diff --git a/include/LmmsPalette.h b/include/LmmsPalette.h index 49b831346db..a8ee5d1c8ab 100644 --- a/include/LmmsPalette.h +++ b/include/LmmsPalette.h @@ -43,8 +43,6 @@ class LMMS_EXPORT LmmsPalette : public QWidget Q_PROPERTY( QColor brightText READ brightText WRITE setBrightText ) Q_PROPERTY( QColor highlight READ highlight WRITE setHighlight ) Q_PROPERTY( QColor highlightedText READ highlightedText WRITE setHighlightedText ) - Q_PROPERTY( QColor toolTipText READ toolTipText WRITE setToolTipText ) - Q_PROPERTY( QColor toolTipBase READ toolTipBase WRITE setToolTipBase ) public: LmmsPalette( QWidget * parent, QStyle * stylearg ); @@ -65,8 +63,6 @@ class LMMS_EXPORT LmmsPalette : public QWidget ACCESSMET( brightText, setBrightText ) ACCESSMET( highlight, setHighlight ) ACCESSMET( highlightedText, setHighlightedText ) - ACCESSMET( toolTipText, setToolTipText ) - ACCESSMET( toolTipBase, setToolTipBase ) #undef ACCESSMET @@ -83,8 +79,6 @@ class LMMS_EXPORT LmmsPalette : public QWidget QColor m_brightText; QColor m_highlight; QColor m_highlightedText; - QColor m_toolTipText; - QColor m_toolTipBase; }; diff --git a/include/LmmsStyle.h b/include/LmmsStyle.h index 88b8a21124f..ccf14396c8f 100644 --- a/include/LmmsStyle.h +++ b/include/LmmsStyle.h @@ -67,21 +67,21 @@ class LmmsStyle : public QProxyStyle { } - virtual QPalette standardPalette( void ) const; + QPalette standardPalette( void ) const override; virtual void drawComplexControl( ComplexControl control, const QStyleOptionComplex * option, QPainter *painter, - const QWidget *widget ) const; + const QWidget *widget ) const override; virtual void drawPrimitive( PrimitiveElement element, const QStyleOption *option, QPainter *painter, - const QWidget *widget = 0 ) const; + const QWidget *widget = 0 ) const override; virtual int pixelMetric( PixelMetric metric, const QStyleOption * option = 0, - const QWidget * widget = 0 ) const; + const QWidget * widget = 0 ) const override; static QPalette * s_palette; diff --git a/include/LocklessRingBuffer.h b/include/LocklessRingBuffer.h new file mode 100644 index 00000000000..d313fd72288 --- /dev/null +++ b/include/LocklessRingBuffer.h @@ -0,0 +1,133 @@ +/* + * LocklessRingBuffer.h - LMMS wrapper for a lockless ringbuffer library + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LOCKLESSRINGBUFFER_H +#define LOCKLESSRINGBUFFER_H + +#include +#include + +#include "lmms_basics.h" +#include "lmms_export.h" +#include "../src/3rdparty/ringbuffer/include/ringbuffer/ringbuffer.h" + + +//! A convenience layer for a realtime-safe and thread-safe multi-reader ring buffer library. +template +class LocklessRingBufferBase +{ + template + friend class LocklessRingBufferReader; +public: + LocklessRingBufferBase(std::size_t sz) : m_buffer(sz) + { + m_buffer.touch(); // reserve storage space before realtime operation starts + } + ~LocklessRingBufferBase() {}; + + std::size_t capacity() const {return m_buffer.maximum_eventual_write_space();} + std::size_t free() const {return m_buffer.write_space();} + void wakeAll() {m_notifier.wakeAll();} + +protected: + ringbuffer_t m_buffer; + QWaitCondition m_notifier; +}; + + +// The SampleFrameCopier is required because sampleFrame is just a two-element +// array and therefore does not have a copy constructor needed by std::copy. +class SampleFrameCopier +{ + const sampleFrame* m_src; +public: + SampleFrameCopier(const sampleFrame* src) : m_src(src) {} + void operator()(std::size_t src_offset, std::size_t count, sampleFrame* dest) + { + for (std::size_t i = src_offset; i < src_offset + count; i++, dest++) + { + (*dest)[0] = m_src[i][0]; + (*dest)[1] = m_src[i][1]; + } + } +}; + + +//! Standard ring buffer template for data types with copy constructor. +template +class LocklessRingBuffer : public LocklessRingBufferBase +{ +public: + LocklessRingBuffer(std::size_t sz) : LocklessRingBufferBase(sz) {}; + + std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false) + { + std::size_t written = LocklessRingBufferBase::m_buffer.write(src, cnt); + // Let all waiting readers know new data are available. + if (notify) {LocklessRingBufferBase::m_notifier.wakeAll();} + return written; + } +}; + + +//! Specialized ring buffer template with write function modified to support sampleFrame. +template <> +class LocklessRingBuffer : public LocklessRingBufferBase +{ +public: + LocklessRingBuffer(std::size_t sz) : LocklessRingBufferBase(sz) {}; + + std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false) + { + SampleFrameCopier copier(src); + std::size_t written = LocklessRingBufferBase::m_buffer.write_func(copier, cnt); + // Let all waiting readers know new data are available. + if (notify) {LocklessRingBufferBase::m_notifier.wakeAll();} + return written; + } +}; + + +//! Wrapper for lockless ringbuffer reader +template +class LocklessRingBufferReader : public ringbuffer_reader_t +{ +public: + LocklessRingBufferReader(LocklessRingBuffer &rb) : + ringbuffer_reader_t(rb.m_buffer), + m_notifier(&rb.m_notifier) {}; + + bool empty() const {return !this->read_space();} + void waitForData() + { + QMutex useless_lock; + useless_lock.lock(); + m_notifier->wait(&useless_lock); + useless_lock.unlock(); + } +private: + QWaitCondition *m_notifier; +}; + +#endif //LOCKLESSRINGBUFFER_H diff --git a/include/Lv2Basics.h b/include/Lv2Basics.h new file mode 100644 index 00000000000..0003f83e814 --- /dev/null +++ b/include/Lv2Basics.h @@ -0,0 +1,67 @@ +/* + * Lv2Basics.h - basic Lv2 utils + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef LV2BASICS_H +#define LV2BASICS_H + + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_LV2 + +#include +#include +#include +#include + +struct LilvNodeDeleter +{ + void operator()(LilvNode* n) { lilv_node_free(n); } +}; + +struct LilvNodesDeleter +{ + void operator()(LilvNodes* n) { lilv_nodes_free(n); } +}; + +using AutoLilvNode = std::unique_ptr; +using AutoLilvNodes = std::unique_ptr; + +/** + Return QString from a plugin's node, everything will be freed automatically + @param plug The plugin where the node is + @param getFunc The function to return the node from the plugin +*/ +QString qStringFromPluginNode(const LilvPlugin* plug, + LilvNode * (*getFunc)(const LilvPlugin*)); + +//! Return port name as QString, everything will be freed automatically +QString qStringFromPortName(const LilvPlugin* plug, const LilvPort* port); + +//! Return port name as std::string, everything will be freed automatically +std::string stdStringFromPortName(const LilvPlugin* plug, const LilvPort* port); + +#endif // LMMS_HAVE_LV2 +#endif // LV2BASICS_H diff --git a/include/Lv2ControlBase.h b/include/Lv2ControlBase.h new file mode 100644 index 00000000000..9f1b54992cd --- /dev/null +++ b/include/Lv2ControlBase.h @@ -0,0 +1,146 @@ +/* + * Lv2ControlBase.h - Lv2 control base class + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2_CONTROL_BASE_H +#define LV2_CONTROL_BASE_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_LV2 + +#include + +#include "DataFile.h" +#include "LinkedModelGroups.h" +#include "Plugin.h" + +class Lv2Proc; +class PluginIssue; + +/** + Common base class for Lv2 plugins + + This class contains a vector of Lv2Proc, usually 1 (for stereo plugins) or + 2 (for mono plugins). Most of the logic is done there, this class primarily + forwards work to the Lv2Proc and collects the results. + + This class provides everything Lv2 plugins have in common. It's not + named Lv2Plugin, because + * it does not inherit Instrument + * the Plugin subclass Effect does not inherit this class + + This class would usually be a Model subclass. However, Qt doesn't allow + this: + * inhertiting only from Model will cause diamond inheritance for QObject, + which will cause errors with Q_OBJECT + * making this a direct subclass of Instrument resp. EffectControls would + require CRTP, which would make this class a template class, which would + conflict with Q_OBJECT + + The consequence is that this class can neither inherit QObject or Model, nor + Instrument or EffectControls, which means in fact: + * this class contains no signals or slots, but it offers stubs for slots + that shall be called by child classes + * this class can not override virtuals of Instrument or EffectControls, so + it will offer functions that must be called by virtuals in its child class +*/ +class Lv2ControlBase : public LinkedModelGroups +{ +public: + static Plugin::PluginTypes check(const LilvPlugin* m_plugin, + std::vector &issues, bool printIssues = false); + + const LilvPlugin* getPlugin() const { return m_plugin; } + + Lv2Proc *control(std::size_t idx) { return m_procs[idx].get(); } + const Lv2Proc *control(std::size_t idx) const { return m_procs[idx].get(); } + + bool hasGui() const { return m_hasGUI; } + void setHasGui(bool val) { m_hasGUI = val; } + +protected: + /* + ctor/dtor + */ + //! @param that the class inheriting this class and inheriting Model; + //! this is the same pointer as this, but a different type + //! @param uri the Lv2 URI telling this class what plugin to construct + Lv2ControlBase(class Model *that, const QString& uri); + ~Lv2ControlBase() override; + //! Must be checked after ctor or reload + bool isValid() const { return m_valid; } + + /* + overrides + */ + LinkedModelGroup* getGroup(std::size_t idx) override; + const LinkedModelGroup* getGroup(std::size_t idx) const override; + + /* + utils for the run thread + */ + //! Copy values from all connected models into the respective ports + void copyModelsFromLmms(); + //! Copy buffer passed by LMMS into our ports + void copyBuffersFromLmms(const sampleFrame *buf, fpp_t frames); + //! Copy our ports into buffers passed by LMMS + void copyBuffersToLmms(sampleFrame *buf, fpp_t frames) const; + //! Run the Lv2 plugin instance for @param frames frames + void run(fpp_t frames); + + /* + load/save, must be called from virtuals + */ + void saveSettings(QDomDocument &doc, QDomElement &that); + void loadSettings(const QDomElement &that); + void loadFile(const QString &file); + //! TODO: not implemented + void reloadPlugin(); + + /* + more functions that must be called from virtuals + */ + std::size_t controlCount() const; + QString nodeName() const { return "lv2controls"; } + +private: + //! Return the DataFile settings type + virtual DataFile::Types settingsType() = 0; + //! Inform the plugin about a file name change + virtual void setNameFromFile(const QString &fname) = 0; + + //! Independent processors + //! If this is a mono effect, the vector will have size 2 in order to + //! fulfill LMMS' requirement of having stereo input and output + std::vector> m_procs; + + bool m_valid = true; + bool m_hasGUI = false; + unsigned m_channelsPerProc; + + const LilvPlugin* m_plugin; +}; + +#endif // LMMS_HAVE_LV2 +#endif // LV2_CONTROL_BASE_H diff --git a/include/Lv2Features.h b/include/Lv2Features.h new file mode 100644 index 00000000000..f036c6d1f67 --- /dev/null +++ b/include/Lv2Features.h @@ -0,0 +1,81 @@ +/* + * Lv2Features.h - Lv2Features class + * + * Copyright (c) 2020-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2FEATURES_H +#define LV2FEATURES_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_LV2 + +#include +#include +#include +#include "Lv2Manager.h" + +/** + Feature container + + References all available features for a plugin and maps them to their URIs. + + The public member functions should be called in descending order: + + 1. initCommon: map plugin-common features + 2. operator[]: map plugin-specific features + 3. createFeatureVectors: create the feature vectors required for + lilv_plugin_instantiate + 4. access the latter +*/ +class Lv2Features +{ +public: + //! Return if a feature is supported by LMMS + static bool isFeatureSupported(const char *featName); + + Lv2Features(); + + //! Register only plugin-common features + void initCommon(); + //! Return reference to feature data with given URI featName + void*& operator[](const char* featName); + //! Fill m_features and m_featurePointers with all features + void createFeatureVectors(); + //! Return LV2_Feature pointer vector, suited for lilv_plugin_instantiate + const LV2_Feature* const* featurePointers() const + { + return m_featurePointers.data(); + } + +private: + //! feature storage + std::vector m_features; + //! pointers to m_features, required for lilv_plugin_instantiate + std::vector m_featurePointers; + //! features + data, ordered by URI + std::map m_featureByUri; +}; + +#endif // LMMS_HAVE_LV2 + +#endif // LV2FEATURES_H diff --git a/include/Lv2Manager.h b/include/Lv2Manager.h new file mode 100644 index 00000000000..0b5fc692354 --- /dev/null +++ b/include/Lv2Manager.h @@ -0,0 +1,149 @@ +/* + * Lv2Manager.h - Implementation of Lv2Manager class + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2MANAGER_H +#define LV2MANAGER_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_LV2 + +#include +#include +#include + +#include "Lv2Basics.h" +#include "Lv2UridMap.h" +#include "Plugin.h" + + +/* + all Lv2 classes in relation (use our "4 spaces per tab rule" to view): + + explanation: + "x = {y z}" means class "x" consists of classes "y" and "z" + (and probably other classes not mentioned) + "x = {y*}" means class "x" references/uses class "y" + + core: + Lv2Proc = {LilvInstance} + Lv2ControlBase = {Lv2Proc, Lv2Proc... (2 for mono, 1 for stereo)} + Lv2Manager = {LilvPlugin*, LilvPlugin* ...} + (creates Lv2ControlBase, Lv2ControlBase...) + + Lv2FxControls = {Lv2ControlBase} + Lv2Effect = {Effect + Lv2FxControls} + (takes Lv2SubPluginFeatures in ctor) + Lv2Instrument = {Instrument + Lv2ControlBase} + (takes Lv2SubPluginFeatures in ctor) + + gui: + Lv2ViewProc = {Lv2Proc*} + Lv2ViewBase = {Lv2ViewProc, Lv2ViewProc... + (2 for mono, 1 for stereo)} + Lv2FxControlDialog = {EffectControlDialog + Lv2ViewBase} + Lv2InsView = {InstrumentView + Lv2ViewBase} + + Lv2SubPluginFeatures: + Lv2SubPluginFeatures = {Lv2Manager*} + Lv2Effect::Descriptor = {Lv2SubPluginFeatures} + Lv2Instrument::Descriptor = {Lv2SubPluginFeatures} +*/ + + +//! Class to keep track of all LV2 plugins +class Lv2Manager +{ +public: + void initPlugins(); + + Lv2Manager(); + ~Lv2Manager(); + + + AutoLilvNode uri(const char* uriStr); + + //! Class representing info for one plugin + struct Lv2Info + { + public: + //! use only for std::map internals + Lv2Info() : m_plugin(nullptr) {} + //! ctor used inside Lv2Manager + Lv2Info(const LilvPlugin* plug, Plugin::PluginTypes type, bool valid) : + m_plugin(plug), m_type(type), m_valid(valid) {} + Lv2Info(Lv2Info&& other) = default; + Lv2Info& operator=(Lv2Info&& other) = default; + + const LilvPlugin* plugin() const { return m_plugin; } + Plugin::PluginTypes type() const { return m_type; } + bool isValid() const { return m_valid; } + + private: + const LilvPlugin* m_plugin; + Plugin::PluginTypes m_type; + bool m_valid = false; + }; + + //! Return descriptor with URI @p uri or nullptr if none exists + const LilvPlugin *getPlugin(const std::string &uri); + //! Return descriptor with URI @p uri or nullptr if none exists + const LilvPlugin *getPlugin(const QString& uri); + + using Lv2InfoMap = std::map; + using Iterator = Lv2InfoMap::iterator; + Iterator begin() { return m_lv2InfoMap.begin(); } + Iterator end() { return m_lv2InfoMap.end(); } + + //! strcmp based key comparator for std::set and std::map + struct CmpStr + { + bool operator()(char const *a, char const *b) const; + }; + + UridMap& uridMap() { return m_uridMap; } + //! Return all + const std::set& supportedFeatureURIs() const + { + return m_supportedFeatureURIs; + } + bool isFeatureSupported(const char* featName) const; + +private: + // general data + bool m_debug; //!< if set, debug output will be printed + LilvWorld* m_world; + Lv2InfoMap m_lv2InfoMap; + std::set m_supportedFeatureURIs; + + // feature data that are common for all Lv2Proc + UridMap m_uridMap; + + // functions + bool isSubclassOf(const LilvPluginClass *clvss, const char *uriStr); +}; + +#endif // LMMS_HAVE_LV2 + +#endif // LV2MANAGER_H diff --git a/include/Lv2Ports.h b/include/Lv2Ports.h new file mode 100644 index 00000000000..c9e6c16c855 --- /dev/null +++ b/include/Lv2Ports.h @@ -0,0 +1,237 @@ +/* + * Lv2Ports.h - Lv2 port classes definitions + * + * Copyright (c) 2019-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2PORTS_H +#define LV2PORTS_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_LV2 + +#include +#include +#include + +#include "lmms_basics.h" +#include "PluginIssue.h" + +struct ConnectPortVisitor; + +namespace Lv2Ports { + +/* + port structs +*/ +enum class Flow { + Unknown, + Input, + Output +}; + +enum class Type { + Unknown, + Control, + Audio, + Event, //!< TODO: unused, describe + Cv //!< TODO: unused, describe +}; + +//! Port visualization +//! @note All Lv2 audio ports are float, this is only the visualisation +enum class Vis { + None, + Integer, + Enumeration, + Toggled +}; + +const char* toStr(Lv2Ports::Flow pf); +const char* toStr(Lv2Ports::Type pt); +const char* toStr(Lv2Ports::Vis pv); + +struct ControlPortBase; +struct Control; +struct Audio; +struct Cv; +struct Unknown; + +struct ConstVisitor +{ + virtual void visit(const Lv2Ports::ControlPortBase& ) {} + virtual void visit(const Lv2Ports::Control& ) {} + virtual void visit(const Lv2Ports::Audio& ) {} + virtual void visit(const Lv2Ports::Cv& ) {} + virtual void visit(const Lv2Ports::Unknown& ) {} + + virtual ~ConstVisitor(); +}; + +struct Visitor +{ + virtual void visit(Lv2Ports::ControlPortBase& ) {} + virtual void visit(Lv2Ports::Control& ) {} + virtual void visit(Lv2Ports::Audio& ) {} + virtual void visit(Lv2Ports::Cv& ) {} + virtual void visit(Lv2Ports::Unknown& ) {} + + virtual ~Visitor(); +}; + +struct Meta +{ + Type m_type = Type::Unknown; + Flow m_flow = Flow::Unknown; + Vis m_vis = Vis::None; + + float m_def = .0f, m_min = .0f, m_max = .0f; + bool m_optional = false; + bool m_used = true; + + std::vector get(const LilvPlugin* plugin, std::size_t portNum); +}; + +struct PortBase : public Meta +{ + const LilvPort* m_port = nullptr; + const LilvPlugin* m_plugin = nullptr; + + virtual void accept(Visitor& v) = 0; + virtual void accept(ConstVisitor& v) const = 0; + + QString name() const; + QString uri() const; + + virtual ~PortBase(); +}; + +template +struct VisitablePort : public Base +{ + void accept(Visitor& v) override { v.visit(static_cast(*this)); } + void accept(ConstVisitor& v) const override { v.visit(static_cast(*this)); } +}; + +struct ControlPortBase : public VisitablePort +{ + //! LMMS models + //! Always up-to-date, except during runs + std::unique_ptr m_connectedModel; + + //! Enumerate float values + //! lv2 defines scale points as + //! "single float Points (for control inputs)" + std::vector m_scalePointMap; +}; + +struct Control : public VisitablePort +{ + //! Data location which Lv2 plugins see + //! Model values are being copied here every run + //! Between runs, this data is not up-to-date + float m_val; +}; + +struct Cv : public VisitablePort +{ + //! Data location which Lv2 plugins see + //! Model values are being copied here every run + //! Between runs, this data is not up-to-date + std::vector m_buffer; +}; + +struct Audio : public VisitablePort +{ + Audio(std::size_t bufferSize, bool isSidechain, bool isOptional); + + //! Copy buffer passed by LMMS into our ports + //! @param channel channel index into each sample frame + void copyBuffersFromCore(const sampleFrame *lmmsBuf, + unsigned channel, fpp_t frames); + //! Add buffer passed by LMMS into our ports, and halve the result + //! @param channel channel index into each sample frame + void averageWithBuffersFromCore(const sampleFrame *lmmsBuf, + unsigned channel, fpp_t frames); + //! Copy our ports into buffers passed by LMMS + //! @param channel channel index into each sample frame + void copyBuffersToCore(sampleFrame *lmmsBuf, + unsigned channel, fpp_t frames) const; + + bool isSideChain() const { return m_sidechain; } + bool isOptional() const { return m_optional; } + bool mustBeUsed() const { return !isSideChain() && !isOptional(); } + std::size_t bufferSize() const { return m_buffer.size(); } + +private: + //! the buffer where Lv2 reads/writes the data from/to + std::vector m_buffer; + bool m_sidechain; + bool m_optional; + + // the only case when data of m_buffer may be referenced: + friend struct ::ConnectPortVisitor; +}; + +struct Unknown : public VisitablePort +{ +}; + +/* + port casts +*/ +template +struct DCastVisitor : public Visitor +{ + Target* m_result = nullptr; + void visit(Target& tar) { m_result = &tar; } +}; + +template +struct ConstDCastVisitor : public ConstVisitor +{ + const Target* m_result = nullptr; + void visit(const Target& tar) { m_result = &tar; } +}; + +//! If you don't want to use a whole visitor, you can use dcast +template +Target* dcast(PortBase* base) +{ + DCastVisitor vis; + base->accept(vis); + return vis.m_result; +} + +//! const overload +template +const Target* dcast(const PortBase* base) +{ + ConstDCastVisitor vis; + base->accept(vis); + return vis.m_result; +} + +} // namespace Lv2Ports + +#endif // LMMS_HAVE_LV2 +#endif // LV2PORTS_H diff --git a/include/Lv2Proc.h b/include/Lv2Proc.h new file mode 100644 index 00000000000..1c1cc11d8ac --- /dev/null +++ b/include/Lv2Proc.h @@ -0,0 +1,187 @@ +/* + * Lv2Proc.h - Lv2 processor class + * + * Copyright (c) 2019-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2PROC_H +#define LV2PROC_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_LV2 + +#include +#include +#include + +#include "Lv2Basics.h" +#include "Lv2Features.h" +#include "LinkedModelGroups.h" +#include "Plugin.h" +#include "PluginIssue.h" + + +// forward declare port structs/enums +namespace Lv2Ports +{ + struct Audio; + struct PortBase; + + enum class Type; + enum class Flow; + enum class Vis; +} + + +//! Class representing one Lv2 processor, i.e. one Lv2 handle +//! For Mono effects, 1 Lv2ControlBase references 2 Lv2Proc +class Lv2Proc : public LinkedModelGroup +{ +public: + static Plugin::PluginTypes check(const LilvPlugin* plugin, + std::vector &issues, bool printIssues = false); + + /* + ctor/dtor + */ + Lv2Proc(const LilvPlugin* plugin, Model *parent); + ~Lv2Proc() override; + //! Must be checked after ctor or reload + bool isValid() const { return m_valid; } + + /* + port access + */ + struct StereoPortRef + { + //! mono port or left port in case of stereo + Lv2Ports::Audio* m_left = nullptr; + //! unused, or right port in case of stereo + Lv2Ports::Audio* m_right = nullptr; + }; + + StereoPortRef& inPorts() { return m_inPorts; } + const StereoPortRef& inPorts() const { return m_inPorts; } + StereoPortRef& outPorts() { return m_outPorts; } + const StereoPortRef& outPorts() const { return m_outPorts; } + template + void foreach_port(const Functor& ftor) + { + for (std::unique_ptr& port : m_ports) + { + ftor(port.get()); + } + } + template + void foreach_port(const Functor& ftor) const + { + for (const std::unique_ptr& port : m_ports) + { + ftor(port.get()); + } + } + + //! Debug function to print ports to stdout + void dumpPorts(); + + /* + utils for the run thread + */ + //! Copy values from all connected models into the respective ports + void copyModelsFromCore(); + /** + * Copy buffer passed by the core into our ports + * @param buf buffer of sample frames, each sample frame is something like + * a `float[ * ]` array. + * @param firstChan The offset for @p buf where we have to read our + * first channel. + * This marks the first sample in each sample frame where we read from. + * If we are the 2nd of 2 mono procs, this can be greater than 0. + * @param num Number of channels we must read from @param buf (starting at + * @p offset) + */ + void copyBuffersFromCore(const sampleFrame *buf, + unsigned firstChan, unsigned num, fpp_t frames); + /** + * Copy our ports into buffers passed by the core + * @param buf buffer of sample frames, each sample frame is something like + * a `float[ * ]` array. + * @param firstChan The offset for @p buf where we have to write our + * first channel. + * This marks the first sample in each sample frame where we write to. + * If we are the 2nd of 2 mono procs, this can be greater than 0. + * @param num Number of channels we must write to @param buf (starting at + * @p offset) + */ + void copyBuffersToCore(sampleFrame *buf, unsigned firstChan, unsigned num, + fpp_t frames) const; + //! Run the Lv2 plugin instance for @param frames frames + void run(fpp_t frames); + + /* + misc + */ + class AutomatableModel *modelAtPort(const QString &uri); // unused currently + std::size_t controlCount() const { return LinkedModelGroup::modelNum(); } + +protected: + /* + load and save + */ + //! Create ports and instance, connect ports, activate plugin + void initPlugin(); + //! Deactivate instance + void shutdownPlugin(); + +private: + bool m_valid = true; + + const LilvPlugin* m_plugin; + LilvInstance* m_instance; + Lv2Features m_features; + + std::vector> m_ports; + StereoPortRef m_inPorts, m_outPorts; + + //! models for the controls, sorted by port symbols + std::map m_connectedModels; + + void initPluginSpecificFeatures(); + + //! load a file in the plugin, but don't do anything in LMMS + void loadFileInternal(const QString &file); + //! allocate m_ports, fill all with metadata, and assign meaning of ports + void createPorts(); + //! fill m_ports[portNum] with metadata + void createPort(std::size_t portNum); + //! connect m_ports[portNum] with Lv2 + void connectPort(std::size_t num); + + void dumpPort(std::size_t num); + + static bool portIsSideChain(const LilvPlugin* plugin, const LilvPort *port); + static bool portIsOptional(const LilvPlugin* plugin, const LilvPort *port); + static AutoLilvNode uri(const char* uriStr); +}; + +#endif // LMMS_HAVE_LV2 +#endif // LV2PROC_H diff --git a/include/Lv2SubPluginFeatures.h b/include/Lv2SubPluginFeatures.h new file mode 100644 index 00000000000..33c29c3ef26 --- /dev/null +++ b/include/Lv2SubPluginFeatures.h @@ -0,0 +1,61 @@ +/* + * Lv2SubPluginFeatures.h - derivation from + * Plugin::Descriptor::SubPluginFeatures for + * hosting LV2 plugins + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2_SUBPLUGIN_FEATURES_H +#define LV2_SUBPLUGIN_FEATURES_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_LV2 + +#include + +#include "Plugin.h" + +class Lv2SubPluginFeatures : public Plugin::Descriptor::SubPluginFeatures +{ +private: + static const LilvPlugin *getPlugin(const Key &k); + static QString pluginName(const LilvPlugin *plug); + +public: + Lv2SubPluginFeatures(Plugin::PluginTypes type); + + void fillDescriptionWidget( + QWidget *parent, const Key *k) const override; + + QString additionalFileExtensions(const Key &k) const override; + QString displayName(const Key &k) const override; + QString description(const Key &k) const override; + const PixmapLoader *logo(const Key &k) const override; + + void listSubPluginKeys( + const Plugin::Descriptor *desc, KeyList &kl) const override; +}; + +#endif // LMMS_HAVE_LV2 + +#endif diff --git a/include/Lv2UridMap.h b/include/Lv2UridMap.h new file mode 100644 index 00000000000..f1ddb6253b7 --- /dev/null +++ b/include/Lv2UridMap.h @@ -0,0 +1,69 @@ +/* + * Lv2UridMap.cpp - Lv2UridMap class + * + * Copyright (c) 2019 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2URIDMAP_H +#define LV2URIDMAP_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_LV2 + +#include +#include // TODO: use semaphore, even though this is not realtime critical +#include +#include + +/** + * Complete implementation of the Lv2 Urid Map extension + */ +class UridMap +{ + std::unordered_map m_map; + std::vector m_unMap; + + //! mutex for both m_map and m_unMap + //! the URID map is global, which is why a mutex is required here + std::mutex m_MapMutex; + + LV2_URID_Map m_mapFeature; + LV2_URID_Unmap m_unmapFeature; + + LV2_URID m_lastUrid = 0; + +public: + //! constructor; will set up the features + UridMap(); + + //! map feature function + LV2_URID map(const char* uri); + //! unmap feature function + const char* unmap(LV2_URID urid); + + // access the features + LV2_URID_Map* mapFeature() { return &m_mapFeature; } + LV2_URID_Unmap* unmapFeature() { return &m_unmapFeature; } +}; + +#endif // LMMS_HAVE_LV2 +#endif // LV2URIDMAP_H diff --git a/include/Lv2ViewBase.h b/include/Lv2ViewBase.h new file mode 100644 index 00000000000..980e1f7efcf --- /dev/null +++ b/include/Lv2ViewBase.h @@ -0,0 +1,97 @@ +/* + * Lv2ViewBase.h - base class for Lv2 plugin views + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2VIEWBASE_H +#define LV2VIEWBASE_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_LV2 + + +#include +#include + +#include "LinkedModelGroupViews.h" +#include "Lv2Basics.h" + +class Lv2Proc; +class Lv2ControlBase; + + +//! View for one processor, Lv2ViewBase contains 2 of those for mono plugins +class Lv2ViewProc : public LinkedModelGroupView +{ +public: + //! @param colNum numbers of columns for the controls + Lv2ViewProc(QWidget *parent, Lv2Proc *ctrlBase, int colNum); + ~Lv2ViewProc(); + +private: + static AutoLilvNode uri(const char *uriStr); +}; + + +//! Base class for view for one Lv2 plugin +class Lv2ViewBase : public LinkedModelGroupsView +{ +protected: + //! @param pluginWidget A child class which inherits QWidget + Lv2ViewBase(class QWidget *pluginWidget, Lv2ControlBase *ctrlBase); + ~Lv2ViewBase(); + + // these widgets must be connected by child widgets + class QPushButton *m_reloadPluginButton = nullptr; + class QPushButton *m_toggleUIButton = nullptr; + class QPushButton *m_helpButton = nullptr; + + void toggleUI(); + void toggleHelp(bool visible); + + // to be called by child virtuals + //! Reconnect models if model changed + void modelChanged(Lv2ControlBase* ctrlBase); + +private: + enum Rows + { + ButtonRow, + ProcRow, + LinkChannelsRow + }; + + static AutoLilvNode uri(const char *uriStr); + LinkedModelGroupView* getGroupView() override { return m_procView; } + + Lv2ViewProc* m_procView; + + //! Numbers of controls per row; must be multiple of 2 for mono effects + const int m_colNum = 6; + class QMdiSubWindow* m_helpWindow = nullptr; + class LedCheckBox *m_multiChannelLink; +}; + + +#endif // LMMS_HAVE_LV2 +#endif // LV2VIEWBASE_H diff --git a/include/MainApplication.h b/include/MainApplication.h index 41d6704192d..d28900213c9 100644 --- a/include/MainApplication.h +++ b/include/MainApplication.h @@ -42,7 +42,7 @@ class MainApplication : public QApplication { public: MainApplication(int& argc, char** argv); - bool event(QEvent* event); + bool event(QEvent* event) override; #ifdef LMMS_BUILD_WIN32 bool winEventFilter(MSG* msg, long* result); bool nativeEventFilter(const QByteArray& eventType, void* message, diff --git a/include/MainWindow.h b/include/MainWindow.h index 531cdfd528b..15112456853 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -125,21 +125,13 @@ class MainWindow : public QMainWindow void clearKeyModifiers(); - bool isCtrlPressed() - { - return m_keyMods.m_ctrl; - } - + // TODO Remove this function, since m_shift can get stuck down. + // [[deprecated]] bool isShiftPressed() { return m_keyMods.m_shift; } - bool isAltPressed() - { - return m_keyMods.m_alt; - } - static void saveWidgetState( QWidget * _w, QDomElement & _de ); static void restoreWidgetState( QWidget * _w, const QDomElement & _de ); @@ -148,7 +140,6 @@ public slots: void emptySlot(); void createNewProject(); - void createNewProjectFromTemplate( QAction * _idx ); void openProject(); bool saveProject(); bool saveProjectAs(); @@ -164,6 +155,7 @@ public slots: void toggleFxMixerWin(); void togglePianoRollWin(); void toggleControllerRack(); + void toggleFullscreen(); void updatePlayPauseIcons(); @@ -177,11 +169,11 @@ private slots: void onExportProjectMidi(); protected: - virtual void closeEvent( QCloseEvent * _ce ); - virtual void focusOutEvent( QFocusEvent * _fe ); - virtual void keyPressEvent( QKeyEvent * _ke ); - virtual void keyReleaseEvent( QKeyEvent * _ke ); - virtual void timerEvent( QTimerEvent * _ev ); + void closeEvent( QCloseEvent * _ce ) override; + void focusOutEvent( QFocusEvent * _fe ) override; + void keyPressEvent( QKeyEvent * _ke ) override; + void keyReleaseEvent( QKeyEvent * _ke ) override; + void timerEvent( QTimerEvent * _ev ) override; private: @@ -204,10 +196,6 @@ private slots: QWidget * m_toolBar; QGridLayout * m_toolBarLayout; - QMenu * m_templatesMenu; - QMenu * m_recentlyOpenedProjectsMenu; - int m_custom_templates_count; - struct keyModifiers { keyModifiers() : @@ -237,13 +225,12 @@ private slots: ToolButton * m_metronomeToggle; SessionState m_session; + + bool maximized; private slots: void browseHelp(); - void fillTemplatesMenu(); - void openRecentlyOpenedProject( QAction * _action ); void showTool( QAction * _idx ); - void updateRecentlyOpenedProjectsMenu(); void updateViewMenu( void ); void updateConfig( QAction * _who ); void onToggleMetronome(); diff --git a/include/MeterDialog.h b/include/MeterDialog.h index 5399c4a9a59..da254c7c7cb 100644 --- a/include/MeterDialog.h +++ b/include/MeterDialog.h @@ -40,7 +40,7 @@ class MeterDialog : public QWidget, public ModelView MeterDialog( QWidget * _parent, bool _simple = false ); virtual ~MeterDialog(); - virtual void modelChanged(); + void modelChanged() override; private: diff --git a/include/MidiAlsaRaw.h b/include/MidiAlsaRaw.h index 81f288c2214..69f9366f161 100644 --- a/include/MidiAlsaRaw.h +++ b/include/MidiAlsaRaw.h @@ -62,8 +62,8 @@ class MidiAlsaRaw : public QThread, public MidiClientRaw protected: - virtual void sendByte( const unsigned char c ); - virtual void run(); + void sendByte( const unsigned char c ) override; + void run() override; private: diff --git a/include/MidiAlsaSeq.h b/include/MidiAlsaSeq.h index 0406b42b944..b6e4987210b 100644 --- a/include/MidiAlsaSeq.h +++ b/include/MidiAlsaSeq.h @@ -67,44 +67,44 @@ class MidiAlsaSeq : public QThread, public MidiClient virtual void processOutEvent( const MidiEvent & _me, const MidiTime & _time, - const MidiPort * _port ); + const MidiPort * _port ) override; - virtual void applyPortMode( MidiPort * _port ); - virtual void applyPortName( MidiPort * _port ); + void applyPortMode( MidiPort * _port ) override; + void applyPortName( MidiPort * _port ) override; - virtual void removePort( MidiPort * _port ); + void removePort( MidiPort * _port ) override; // list seq-ports from ALSA - virtual QStringList readablePorts() const + QStringList readablePorts() const override { return m_readablePorts; } - virtual QStringList writablePorts() const + QStringList writablePorts() const override { return m_writablePorts; } // return name of port which specified MIDI event came from - virtual QString sourcePortName( const MidiEvent & ) const; + QString sourcePortName( const MidiEvent & ) const override; // (un)subscribe given MidiPort to/from destination-port virtual void subscribeReadablePort( MidiPort * _port, const QString & _dest, - bool _subscribe = true ); + bool _subscribe = true ) override; virtual void subscribeWritablePort( MidiPort * _port, const QString & _dest, - bool _subscribe = true ); + bool _subscribe = true ) override; virtual void connectRPChanged( QObject * _receiver, - const char * _member ) + const char * _member ) override { connect( this, SIGNAL( readablePortsChanged() ), _receiver, _member ); } virtual void connectWPChanged( QObject * _receiver, - const char * _member ) + const char * _member ) override { connect( this, SIGNAL( writablePortsChanged() ), _receiver, _member ); @@ -117,7 +117,7 @@ private slots: private: - virtual void run(); + void run() override; #ifdef LMMS_HAVE_ALSA QMutex m_seqMutex; diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h new file mode 100644 index 00000000000..943bb422fb0 --- /dev/null +++ b/include/MidiCCRackView.h @@ -0,0 +1,50 @@ +#ifndef MIDI_CC_RACK_VIEW_H +#define MIDI_CC_RACK_VIEW_H + +#include +#include +#include + +#include "SerializingObject.h" +#include "lmms_basics.h" +#include "ComboBox.h" +#include "ComboBoxModel.h" +#include "Knob.h" +#include "TrackContainer.h" +#include "GroupBox.h" +#include "Midi.h" + +class InstrumentTrack; + +class MidiCCRackView : public QWidget, public SerializingObject +{ + Q_OBJECT +public: + MidiCCRackView( InstrumentTrack * track ); + virtual ~MidiCCRackView(); + + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + + inline QString nodeName() const override + { + return "MidiCCRackView"; + } + +public slots: + void unsetModels(); + void destroyRack(); + void renameLabel(); + +private: + QLabel *m_trackLabel; + + InstrumentTrack *m_track; + + GroupBox *m_midiCCGroupBox; // MIDI CC GroupBox (used to enable disable MIDI CC) + + Knob *m_controllerKnob[MidiControllerCount]; // Holds the knob widgets for each controller + +}; + +#endif diff --git a/include/MidiClient.h b/include/MidiClient.h index 293f2b3daa9..f06cac89394 100644 --- a/include/MidiClient.h +++ b/include/MidiClient.h @@ -124,7 +124,7 @@ class MidiClientRaw : public MidiClient virtual ~MidiClientRaw(); // we are raw-clients for sure! - virtual bool isRaw() const + bool isRaw() const override { return true; } @@ -141,7 +141,7 @@ class MidiClientRaw : public MidiClient private: // this does MIDI-event-process void processParsedEvent(); - virtual void processOutEvent( const MidiEvent& event, const MidiTime& time, const MidiPort* port ); + void processOutEvent( const MidiEvent& event, const MidiTime& time, const MidiPort* port ) override; // small helper function returning length of a certain event - this // is necessary for parsing raw-MIDI-data diff --git a/include/MidiController.h b/include/MidiController.h index d661b8d0f36..43f928a25cb 100644 --- a/include/MidiController.h +++ b/include/MidiController.h @@ -44,30 +44,30 @@ class MidiController : public Controller, public MidiEventProcessor virtual ~MidiController(); virtual void processInEvent( const MidiEvent & _me, - const MidiTime & _time, f_cnt_t offset = 0 ); + const MidiTime & _time, f_cnt_t offset = 0 ) override; virtual void processOutEvent( const MidiEvent& _me, - const MidiTime & _time, f_cnt_t offset = 0 ) + const MidiTime & _time, f_cnt_t offset = 0 ) override { // No output yet } - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); - virtual QString nodeName() const; + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; + void loadSettings( const QDomElement & _this ) override; + QString nodeName() const override; // Used by controllerConnectionDialog to copy void subscribeReadablePorts( const MidiPort::Map & _map ); public slots: - virtual ControllerDialog * createDialog( QWidget * _parent ); + ControllerDialog * createDialog( QWidget * _parent ) override; void updateName(); protected: // The internal per-controller get-value function - virtual void updateValueBuffer(); + void updateValueBuffer() override; MidiPort m_midiPort; diff --git a/include/MidiDummy.h b/include/MidiDummy.h index dffd1ce5110..f809d3c3630 100644 --- a/include/MidiDummy.h +++ b/include/MidiDummy.h @@ -56,7 +56,7 @@ class MidiDummy : public MidiClientRaw protected: - virtual void sendByte( const unsigned char ) + void sendByte( const unsigned char ) override { } diff --git a/include/MidiEvent.h b/include/MidiEvent.h index 907314b4866..2d68ee614b0 100644 --- a/include/MidiEvent.h +++ b/include/MidiEvent.h @@ -37,23 +37,26 @@ class MidiEvent int8_t channel = 0, int16_t param1 = 0, int16_t param2 = 0, - const void* sourcePort = NULL ) : + const void* sourcePort = NULL, + bool fromHardware = true ) : m_type( type ), m_metaEvent( MidiMetaInvalid ), m_channel( channel ), m_sysExData( NULL ), - m_sourcePort( sourcePort ) + m_sourcePort( sourcePort ), + m_fromHardware( fromHardware ) { m_data.m_param[0] = param1; m_data.m_param[1] = param2; } - MidiEvent( MidiEventTypes type, const char* sysExData, int dataLen ) : + MidiEvent( MidiEventTypes type, const char* sysExData, int dataLen, bool fromHardware = true ) : m_type( type ), m_metaEvent( MidiMetaInvalid ), m_channel( 0 ), m_sysExData( sysExData ), - m_sourcePort( NULL ) + m_sourcePort( NULL ), + m_fromHardware( fromHardware ) { m_data.m_sysExDataLen = dataLen; } @@ -64,7 +67,8 @@ class MidiEvent m_channel( other.m_channel ), m_data( other.m_data ), m_sysExData( other.m_sysExData ), - m_sourcePort( other.m_sourcePort ) + m_sourcePort( other.m_sourcePort ), + m_fromHardware( other.m_fromHardware ) { } @@ -190,6 +194,16 @@ class MidiEvent setParam( 0, pitchBend ); } + bool fromHardware() const + { + return m_fromHardware; + } + + void setHardware( bool value ) + { + m_fromHardware = value; + } + private: MidiEventTypes m_type; // MIDI event type @@ -204,6 +218,7 @@ class MidiEvent const char* m_sysExData; const void* m_sourcePort; + bool m_fromHardware; // Should the event be treated as originated from a physical controller? } ; diff --git a/include/MidiOss.h b/include/MidiOss.h index 27ebf077154..7e1f179efd6 100644 --- a/include/MidiOss.h +++ b/include/MidiOss.h @@ -58,8 +58,8 @@ class MidiOss : public QThread, public MidiClientRaw } protected: - virtual void sendByte( const unsigned char c ); - virtual void run(); + void sendByte( const unsigned char c ) override; + void run() override; private: diff --git a/include/MidiPort.h b/include/MidiPort.h index 07c61d788a6..acf95992fad 100644 --- a/include/MidiPort.h +++ b/include/MidiPort.h @@ -96,17 +96,20 @@ class MidiPort : public Model, public SerializingObject int realOutputChannel() const { - return outputChannel() - 1; + // There's a possibility of outputChannel being 0 ("--"), which is used to keep all + // midi channels when forwarding. In that case, realOutputChannel will return the + // default channel 1 (whose value is 0). + return outputChannel() ? outputChannel() - 1 : 0; } void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ); void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ); - virtual void saveSettings( QDomDocument& doc, QDomElement& thisElement ); - virtual void loadSettings( const QDomElement& thisElement ); + void saveSettings( QDomDocument& doc, QDomElement& thisElement ) override; + void loadSettings( const QDomElement& thisElement ) override; - virtual QString nodeName() const + QString nodeName() const override { return "midiport"; } diff --git a/include/MidiPortMenu.h b/include/MidiPortMenu.h index b963a7bd99a..ce39c4aace0 100644 --- a/include/MidiPortMenu.h +++ b/include/MidiPortMenu.h @@ -51,7 +51,7 @@ protected slots: private: - virtual void modelChanged(); + void modelChanged() override; MidiPort::Modes m_mode; diff --git a/include/MidiSndio.h b/include/MidiSndio.h index d115993fe99..14ecfa0e94a 100644 --- a/include/MidiSndio.h +++ b/include/MidiSndio.h @@ -59,8 +59,8 @@ class MidiSndio : public QThread, public MidiClientRaw protected: - virtual void sendByte(const unsigned char c); - virtual void run(void); + void sendByte(const unsigned char c) override; + void run(void) override; private: struct mio_hdl *m_hdl; diff --git a/include/MidiTime.h b/include/MidiTime.h index 7aaacf96344..952b4b6d596 100644 --- a/include/MidiTime.h +++ b/include/MidiTime.h @@ -32,10 +32,10 @@ #include "lmms_export.h" #include "lmms_basics.h" -// note: 1 "Tact" = 1 Measure -const int DefaultTicksPerTact = 192; -const int DefaultStepsPerTact = 16; -const int DefaultBeatsPerTact = DefaultTicksPerTact / DefaultStepsPerTact; +// note: a bar was erroneously called "tact" in older versions of LMMS +const int DefaultTicksPerBar = 192; +const int DefaultStepsPerBar = 16; +const int DefaultBeatsPerBar = DefaultTicksPerBar / DefaultStepsPerBar; class MeterModel; @@ -60,19 +60,19 @@ class LMMS_EXPORT TimeSig class LMMS_EXPORT MidiTime { public: - MidiTime( const tact_t tact, const tick_t ticks ); + MidiTime( const bar_t bar, const tick_t ticks ); MidiTime( const tick_t ticks = 0 ); - MidiTime toNearestTact() const; - MidiTime toAbsoluteTact() const; + MidiTime quantize(float) const; + MidiTime toAbsoluteBar() const; MidiTime& operator+=( const MidiTime& time ); MidiTime& operator-=( const MidiTime& time ); - // return the tact, rounded down and 0-based - tact_t getTact() const; - // return the tact, rounded up and 0-based - tact_t nextFullTact() const; + // return the bar, rounded down and 0-based + bar_t getBar() const; + // return the bar, rounded up and 0-based + bar_t nextFullBar() const; void setTicks( tick_t ticks ); tick_t getTicks() const; @@ -90,24 +90,23 @@ class LMMS_EXPORT MidiTime // calculate number of frame that are needed this time f_cnt_t frames( const float framesPerTick ) const; - double getTimeInMilliseconds(bpm_t beatsPerMinute) const; + double getTimeInMilliseconds( bpm_t beatsPerMinute ) const; static MidiTime fromFrames( const f_cnt_t frames, const float framesPerTick ); - static tick_t ticksPerTact(); - static tick_t ticksPerTact( const TimeSig &sig ); - static int stepsPerTact(); - static void setTicksPerTact( tick_t tpt ); + static tick_t ticksPerBar(); + static tick_t ticksPerBar( const TimeSig &sig ); + static int stepsPerBar(); + static void setTicksPerBar( tick_t tpt ); static MidiTime stepPosition( int step ); - static double ticksToMilliseconds(tick_t ticks, bpm_t beatsPerMinute); - static double ticksToMilliseconds(double ticks, bpm_t beatsPerMinute); + static double ticksToMilliseconds( tick_t ticks, bpm_t beatsPerMinute ); + static double ticksToMilliseconds( double ticks, bpm_t beatsPerMinute ); private: tick_t m_ticks; - static tick_t s_ticksPerTact; + static tick_t s_ticksPerBar; } ; #endif - diff --git a/include/Mixer.h b/include/Mixer.h index cea592905a3..32eeb8977bf 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -315,6 +315,7 @@ class LMMS_EXPORT Mixer : public QObject inline bool isMetronomeActive() const { return m_metronomeActive; } inline void setMetronomeActive(bool value = true) { m_metronomeActive = value; } + //! Block until a change in model can be done (i.e. wait for audio thread) void requestChangeInModel(); void doneChangeInModel(); @@ -344,7 +345,7 @@ class LMMS_EXPORT Mixer : public QObject fifo * m_fifo; volatile bool m_writing; - virtual void run(); + void run() override; void write( surroundSampleFrame * buffer ); @@ -366,6 +367,8 @@ class LMMS_EXPORT Mixer : public QObject void clearInternal(); + //! Called by the audio thread to give control to other threads, + //! such that they can do changes in the model (like e.g. removing effects) void runChangesInModel(); bool m_renderOnly; diff --git a/include/MixerWorkerThread.h b/include/MixerWorkerThread.h index 7c3792392fb..2d49dce09f2 100644 --- a/include/MixerWorkerThread.h +++ b/include/MixerWorkerThread.h @@ -106,7 +106,7 @@ class MixerWorkerThread : public QThread private: - virtual void run(); + void run() override; static JobQueue globalJobQueue; static QWaitCondition * queueReadyWaitCond; diff --git a/include/ModelView.h b/include/ModelView.h index 907cd14efdf..04229ed0d2f 100644 --- a/include/ModelView.h +++ b/include/ModelView.h @@ -36,6 +36,7 @@ class LMMS_EXPORT ModelView virtual ~ModelView(); virtual void setModel( Model* model, bool isOldModelValid = true ); + virtual void unsetModel(); Model* model() { diff --git a/include/NStateButton.h b/include/NStateButton.h index d9e56b892f1..95d36c253db 100644 --- a/include/NStateButton.h +++ b/include/NStateButton.h @@ -61,7 +61,7 @@ public slots: protected: - virtual void mousePressEvent( QMouseEvent * _me ); + void mousePressEvent( QMouseEvent * _me ) override; private: diff --git a/include/Note.h b/include/Note.h index 0eae8f6b05c..4f66c86d2a2 100644 --- a/include/Note.h +++ b/include/Note.h @@ -28,6 +28,8 @@ #include +#include + #include "volume.h" #include "panning.h" #include "MidiTime.h" @@ -187,7 +189,7 @@ class LMMS_EXPORT Note : public SerializingObject int midiVelocity( int midiBaseVelocity ) const { - return qMin( MidiMaxVelocity, getVolume() * midiBaseVelocity / DefaultVolume ); + return qMin(MidiMaxVelocity, std::round(static_cast(getVolume()) * midiBaseVelocity / DefaultVolume)); } inline panning_t getPanning() const @@ -200,7 +202,7 @@ class LMMS_EXPORT Note : public SerializingObject return "note"; } - inline virtual QString nodeName() const + inline QString nodeName() const override { return classNodeName(); } @@ -218,8 +220,8 @@ class LMMS_EXPORT Note : public SerializingObject protected: - virtual void saveSettings( QDomDocument & doc, QDomElement & parent ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & doc, QDomElement & parent ) override; + void loadSettings( const QDomElement & _this ) override; private: diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index ae55c9ebb6a..de5eeda1953 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -49,6 +49,9 @@ class LMMS_EXPORT NotePlayHandle : public PlayHandle, public Note void * m_pluginData; std::unique_ptr> m_filter; + // length of the declicking fade in + fpp_t m_fadeInLength; + // specifies origin of NotePlayHandle enum Origins { @@ -74,8 +77,8 @@ class LMMS_EXPORT NotePlayHandle : public PlayHandle, public Note return p; } - virtual void setVolume( volume_t volume ); - virtual void setPanning( panning_t panning ); + void setVolume( volume_t volume ) override; + void setPanning( panning_t panning ) override; int midiKey() const; int midiChannel() const @@ -105,10 +108,10 @@ class LMMS_EXPORT NotePlayHandle : public PlayHandle, public Note } /*! Renders one chunk using the attached instrument into the buffer */ - virtual void play( sampleFrame* buffer ); + void play( sampleFrame* buffer ) override; /*! Returns whether playback of note is finished and thus handle can be deleted */ - virtual bool isFinished() const + bool isFinished() const override { return m_released && framesLeft() <= 0; } @@ -120,7 +123,7 @@ class LMMS_EXPORT NotePlayHandle : public PlayHandle, public Note fpp_t framesLeftForCurrentPeriod() const; /*! Returns whether the play handle plays on a certain track */ - virtual bool isFromTrack( const Track* _track ) const; + bool isFromTrack( const Track* _track ) const override; /*! Releases the note (and plays release frames */ void noteOff( const f_cnt_t offset = 0 ); @@ -182,6 +185,8 @@ class LMMS_EXPORT NotePlayHandle : public PlayHandle, public Note return m_instrumentTrack; } + bool shouldDelayRelease() const; + /*! Returns whether note has a parent, e.g. is not part of an arpeggio or a chord */ bool hasParent() const { diff --git a/include/VisualizationWidget.h b/include/Oscilloscope.h similarity index 70% rename from include/VisualizationWidget.h rename to include/Oscilloscope.h index a178b1ad8c3..45e04832a02 100644 --- a/include/VisualizationWidget.h +++ b/include/Oscilloscope.h @@ -1,5 +1,5 @@ /* - * VisualizationWidget.h - widget for visualization of sound-data + * Oscilloscope.h * * Copyright (c) 2005-2008 Tobias Doerffel * @@ -23,8 +23,8 @@ */ -#ifndef _VISUALIZATION_WIDGET -#define _VISUALIZATION_WIDGET +#ifndef _OSCILLOSCOPE +#define _OSCILLOSCOPE #include #include @@ -32,37 +32,28 @@ #include "lmms_basics.h" -class VisualizationWidget : public QWidget +class Oscilloscope : public QWidget { Q_OBJECT public: Q_PROPERTY( QColor normalColor READ normalColor WRITE setNormalColor ) - Q_PROPERTY( QColor warningColor READ warningColor WRITE setWarningColor ) Q_PROPERTY( QColor clippingColor READ clippingColor WRITE setClippingColor ) - enum visualizationTypes - { - Simple // add more here - } ; - VisualizationWidget( const QPixmap & _bg, QWidget * _parent, - visualizationTypes _vtype = Simple ); - virtual ~VisualizationWidget(); + Oscilloscope( QWidget * _parent ); + virtual ~Oscilloscope(); void setActive( bool _active ); QColor const & normalColor() const; void setNormalColor(QColor const & normalColor); - QColor const & warningColor() const; - void setWarningColor(QColor const & warningColor); - QColor const & clippingColor() const; void setClippingColor(QColor const & clippingColor); protected: - virtual void paintEvent( QPaintEvent * _pe ); - virtual void mousePressEvent( QMouseEvent * _me ); + void paintEvent( QPaintEvent * _pe ) override; + void mousePressEvent( QMouseEvent * _me ) override; protected slots: @@ -72,14 +63,13 @@ protected slots: QColor const & determineLineColor(float level) const; private: - QPixmap s_background; + QPixmap m_background; QPointF * m_points; sampleFrame * m_buffer; bool m_active; QColor m_normalColor; - QColor m_warningColor; QColor m_clippingColor; } ; diff --git a/include/PathUtil.h b/include/PathUtil.h new file mode 100644 index 00000000000..cc6b982a114 --- /dev/null +++ b/include/PathUtil.h @@ -0,0 +1,41 @@ +#ifndef PATHUTIL_H +#define PATHUTIL_H + +#include "lmms_export.h" + +#include + +namespace PathUtil +{ + enum class Base { Absolute, ProjectDir, FactorySample, UserSample, UserVST, Preset, + UserLADSPA, DefaultLADSPA, UserSoundfont, DefaultSoundfont, UserGIG, DefaultGIG }; + + //! Return the directory associated with a given base as a QString + QString LMMS_EXPORT baseLocation(const Base base); + //! Return the directory associated with a given base as a QDir + QDir LMMS_EXPORT baseQDir (const Base base); + //! Return the prefix used to denote this base in path strings + QString LMMS_EXPORT basePrefix(const Base base); + //! Check the prefix of a path and return the base it corresponds to + //! Defaults to Base::Absolute + Base LMMS_EXPORT baseLookup(const QString & path); + + //! Remove the prefix from a path, iff there is one + QString LMMS_EXPORT stripPrefix(const QString & path); + //! Get the filename for a path, handling prefixed paths correctly + QString LMMS_EXPORT cleanName(const QString & path); + + //! Upgrade prefix-less relative paths to the new format + QString LMMS_EXPORT oldRelativeUpgrade(const QString & input); + + //! Make this path absolute + QString LMMS_EXPORT toAbsolute(const QString & input); + //! Make this path relative to a given base, return an absolute path if that fails + QString LMMS_EXPORT relativeOrAbsolute(const QString & input, const Base base); + //! Make this path relative to any base, choosing the shortest if there are + //! multiple options. Defaults to an absolute path if all bases fail. + QString LMMS_EXPORT toShortestRelative(const QString & input); + +} + +#endif diff --git a/include/Pattern.h b/include/Pattern.h index 3a1cc941c3a..5192da9faf8 100644 --- a/include/Pattern.h +++ b/include/Pattern.h @@ -94,9 +94,9 @@ class LMMS_EXPORT Pattern : public TrackContentObject Pattern * nextPattern() const; // settings-management - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + inline QString nodeName() const override { return "pattern"; } @@ -109,7 +109,7 @@ class LMMS_EXPORT Pattern : public TrackContentObject bool empty(); - virtual TrackContentObjectView * createView( TrackView * _tv ); + TrackContentObjectView * createView( TrackView * _tv ) override; using Model::dataChanged; @@ -182,7 +182,7 @@ class PatternView : public TrackContentObjectView void setMutedNoteBorderColor(QColor const & color) { m_mutedNoteBorderColor = color; } public slots: - virtual void update(); + void update() override; protected slots: @@ -194,11 +194,11 @@ protected slots: protected: - virtual void constructContextMenu( QMenu * ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseDoubleClickEvent( QMouseEvent * _me ); - virtual void paintEvent( QPaintEvent * pe ); - virtual void wheelEvent( QWheelEvent * _we ); + void constructContextMenu( QMenu * ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseDoubleClickEvent( QMouseEvent * _me ) override; + void paintEvent( QPaintEvent * pe ) override; + void wheelEvent( QWheelEvent * _we ) override; private: diff --git a/include/PeakController.h b/include/PeakController.h index b2824f0ac55..74a3aab5926 100644 --- a/include/PeakController.h +++ b/include/PeakController.h @@ -46,9 +46,9 @@ class LMMS_EXPORT PeakController : public Controller virtual ~PeakController(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); - virtual QString nodeName() const; + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; + void loadSettings( const QDomElement & _this ) override; + QString nodeName() const override; static void initGetControllerBySetting(); static PeakController * getControllerBySetting( const QDomElement & _this ); @@ -57,13 +57,13 @@ class LMMS_EXPORT PeakController : public Controller public slots: - virtual ControllerDialog * createDialog( QWidget * _parent ); + ControllerDialog * createDialog( QWidget * _parent ) override; void handleDestroyedEffect( ); void updateCoeffs(); protected: // The internal per-controller get-value function - virtual void updateValueBuffer(); + void updateValueBuffer() override; PeakControllerEffect * m_peakEffect; @@ -91,9 +91,9 @@ class PeakControllerDialog : public ControllerDialog virtual ~PeakControllerDialog(); protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void paintEvent( QPaintEvent * _pe ); - virtual void modelChanged(); + void contextMenuEvent( QContextMenuEvent * _me ) override; + void paintEvent( QPaintEvent * _pe ) override; + void modelChanged() override; PeakController * m_peakController; diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 4451a07c5c4..7a99e7b1f80 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -40,13 +40,13 @@ #include "ToolTip.h" #include "StepRecorder.h" #include "StepRecorderWidget.h" +#include "PositionLine.h" class QPainter; class QPixmap; class QScrollBar; class QString; class QMenu; -class QSignalMapper; class ComboBox; class NotePlayHandle; @@ -56,25 +56,38 @@ class TimeLineWidget; class PianoRoll : public QWidget { Q_OBJECT - Q_PROPERTY( QColor barLineColor READ barLineColor WRITE setBarLineColor ) - Q_PROPERTY( QColor beatLineColor READ beatLineColor WRITE setBeatLineColor ) - Q_PROPERTY( QColor lineColor READ lineColor WRITE setLineColor ) - Q_PROPERTY( QColor noteModeColor READ noteModeColor WRITE setNoteModeColor ) - Q_PROPERTY( QColor noteColor READ noteColor WRITE setNoteColor ) - Q_PROPERTY( QColor ghostNoteColor READ ghostNoteColor WRITE setGhostNoteColor ) - Q_PROPERTY( QColor noteTextColor READ noteTextColor WRITE setNoteTextColor ) - Q_PROPERTY( QColor ghostNoteTextColor READ ghostNoteTextColor WRITE setGhostNoteTextColor ) - Q_PROPERTY( QColor barColor READ barColor WRITE setBarColor ) - Q_PROPERTY( QColor selectedNoteColor READ selectedNoteColor WRITE setSelectedNoteColor ) - Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor ) - Q_PROPERTY( QColor textColorLight READ textColorLight WRITE setTextColorLight ) - Q_PROPERTY( QColor textShadow READ textShadow WRITE setTextShadow ) - Q_PROPERTY( QColor markedSemitoneColor READ markedSemitoneColor WRITE setMarkedSemitoneColor ) - Q_PROPERTY( int noteOpacity READ noteOpacity WRITE setNoteOpacity ) - Q_PROPERTY( bool noteBorders READ noteBorders WRITE setNoteBorders ) - Q_PROPERTY( int ghostNoteOpacity READ ghostNoteOpacity WRITE setGhostNoteOpacity ) - Q_PROPERTY( bool ghostNoteBorders READ ghostNoteBorders WRITE setGhostNoteBorders ) - Q_PROPERTY( QColor backgroundShade READ backgroundShade WRITE setBackgroundShade ) + Q_PROPERTY(QColor barLineColor MEMBER m_barLineColor) + Q_PROPERTY(QColor beatLineColor MEMBER m_beatLineColor) + Q_PROPERTY(QColor lineColor MEMBER m_lineColor) + Q_PROPERTY(QColor noteModeColor MEMBER m_noteModeColor) + Q_PROPERTY(QColor noteColor MEMBER m_noteColor) + Q_PROPERTY(QColor ghostNoteColor MEMBER m_ghostNoteColor) + Q_PROPERTY(QColor noteTextColor MEMBER m_noteTextColor) + Q_PROPERTY(QColor ghostNoteTextColor MEMBER m_ghostNoteTextColor) + Q_PROPERTY(QColor barColor MEMBER m_barColor) + Q_PROPERTY(QColor selectedNoteColor MEMBER m_selectedNoteColor) + Q_PROPERTY(QColor textColor MEMBER m_textColor) + Q_PROPERTY(QColor textColorLight MEMBER m_textColorLight) + Q_PROPERTY(QColor textShadow MEMBER m_textShadow) + Q_PROPERTY(QColor markedSemitoneColor MEMBER m_markedSemitoneColor) + Q_PROPERTY(int noteOpacity MEMBER m_noteOpacity) + Q_PROPERTY(bool noteBorders MEMBER m_noteBorders) + Q_PROPERTY(int ghostNoteOpacity MEMBER m_ghostNoteOpacity) + Q_PROPERTY(bool ghostNoteBorders MEMBER m_ghostNoteBorders) + Q_PROPERTY(QColor backgroundShade MEMBER m_backgroundShade) + + /* white key properties */ + Q_PROPERTY(int whiteKeyWidth MEMBER m_whiteKeyWidth) + Q_PROPERTY(QColor whiteKeyInactiveTextColor MEMBER m_whiteKeyInactiveTextColor) + Q_PROPERTY(QColor whiteKeyInactiveTextShadow MEMBER m_whiteKeyInactiveTextShadow) + Q_PROPERTY(QBrush whiteKeyInactiveBackground MEMBER m_whiteKeyInactiveBackground) + Q_PROPERTY(QColor whiteKeyActiveTextColor MEMBER m_whiteKeyActiveTextColor) + Q_PROPERTY(QColor whiteKeyActiveTextShadow MEMBER m_whiteKeyActiveTextShadow) + Q_PROPERTY(QBrush whiteKeyActiveBackground MEMBER m_whiteKeyActiveBackground) + /* black key properties */ + Q_PROPERTY(int blackKeyWidth MEMBER m_blackKeyWidth) + Q_PROPERTY(QBrush blackKeyInactiveBackground MEMBER m_blackKeyInactiveBackground) + Q_PROPERTY(QBrush blackKeyActiveBackground MEMBER m_blackKeyActiveBackground) public: enum EditModes { @@ -95,6 +108,7 @@ class PianoRoll : public QWidget void setCurrentPattern( Pattern* newPattern ); void setGhostPattern( Pattern* newPattern ); void loadGhostNotes( const QDomElement & de ); + void loadMarkedSemiTones(const QDomElement & de); inline void stopRecording() { @@ -125,73 +139,34 @@ class PianoRoll : public QWidget int quantization() const; - // qproperty access functions - QColor barLineColor() const; - void setBarLineColor( const QColor & c ); - QColor beatLineColor() const; - void setBeatLineColor( const QColor & c ); - QColor lineColor() const; - void setLineColor( const QColor & c ); - QColor noteModeColor() const; - void setNoteModeColor( const QColor & c ); - QColor noteColor() const; - void setNoteColor( const QColor & c ); - QColor noteTextColor() const; - void setNoteTextColor( const QColor & c ); - QColor barColor() const; - void setBarColor( const QColor & c ); - QColor selectedNoteColor() const; - void setSelectedNoteColor( const QColor & c ); - QColor textColor() const; - void setTextColor( const QColor & c ); - QColor textColorLight() const; - void setTextColorLight( const QColor & c ); - QColor textShadow() const; - void setTextShadow( const QColor & c ); - QColor markedSemitoneColor() const; - void setMarkedSemitoneColor( const QColor & c ); - int noteOpacity() const; - void setNoteOpacity( const int i ); - bool noteBorders() const; - void setNoteBorders( const bool b ); - QColor ghostNoteColor() const; - void setGhostNoteColor( const QColor & c ); - QColor ghostNoteTextColor() const; - void setGhostNoteTextColor( const QColor & c ); - int ghostNoteOpacity() const; - void setGhostNoteOpacity( const int i ); - bool ghostNoteBorders() const; - void setGhostNoteBorders( const bool b ); - QColor backgroundShade() const; - void setBackgroundShade( const QColor & c ); - - protected: - virtual void keyPressEvent( QKeyEvent * ke ); - virtual void keyReleaseEvent( QKeyEvent * ke ); - virtual void leaveEvent( QEvent * e ); - virtual void mousePressEvent( QMouseEvent * me ); - virtual void mouseDoubleClickEvent( QMouseEvent * me ); - virtual void mouseReleaseEvent( QMouseEvent * me ); - virtual void mouseMoveEvent( QMouseEvent * me ); - virtual void paintEvent( QPaintEvent * pe ); - virtual void resizeEvent( QResizeEvent * re ); - virtual void wheelEvent( QWheelEvent * we ); - virtual void focusOutEvent( QFocusEvent * ); + void keyPressEvent( QKeyEvent * ke ) override; + void keyReleaseEvent( QKeyEvent * ke ) override; + void leaveEvent( QEvent * e ) override; + void mousePressEvent( QMouseEvent * me ) override; + void mouseDoubleClickEvent( QMouseEvent * me ) override; + void mouseReleaseEvent( QMouseEvent * me ) override; + void mouseMoveEvent( QMouseEvent * me ) override; + void paintEvent( QPaintEvent * pe ) override; + void resizeEvent( QResizeEvent * re ) override; + void wheelEvent( QWheelEvent * we ) override; + void focusOutEvent( QFocusEvent * ) override; + void focusInEvent( QFocusEvent * ) override; int getKey( int y ) const; - static void drawNoteRect( QPainter & p, int x, int y, + void drawNoteRect( QPainter & p, int x, int y, int width, const Note * n, const QColor & noteCol, const QColor & noteTextColor, const QColor & selCol, const int noteOpc, const bool borderless, bool drawNoteName ); void removeSelection(); void selectAll(); - NoteVector getSelectedNotes(); + NoteVector getSelectedNotes() const; void selectNotesOnKey(); - int xCoordOfTick( int tick ); // for entering values with dblclick in the vol/pan bars void enterValue( NoteVector* nv ); + void updateYScroll(); + protected slots: void play(); void record(); @@ -210,13 +185,14 @@ protected slots: void copySelectedNotes(); void cutSelectedNotes(); void pasteNotes(); - void deleteSelectedNotes(); + bool deleteSelectedNotes(); void updatePosition(const MidiTime & t ); void updatePositionAccompany(const MidiTime & t ); void updatePositionStepRecording(const MidiTime & t ); void zoomingChanged(); + void zoomingYChanged(); void quantizeChanged(); void noteLengthChanged(); void quantizeNotes(); @@ -275,11 +251,14 @@ protected slots: PR_BLACK_KEY }; + PositionLine * m_positionLine; + QVector m_nemStr; // gui names of each edit mode QMenu * m_noteEditMenu; // when you right click below the key area QList m_markedSemiTones; QMenu * m_semiToneMarkerMenu; // when you right click on the key area + int m_pianoKeySelected; PianoRoll(); PianoRoll( const PianoRoll & ); @@ -290,7 +269,9 @@ protected slots: MidiTime newNoteLen() const; void shiftPos(int amount); + void shiftPos(NoteVector notes, int amount); void shiftSemiTone(int amount); + void shiftSemiTone(NoteVector notes, int amount); bool isSelection() const; int selectionCount() const; void testPlayNote( Note * n ); @@ -299,6 +280,9 @@ protected slots: void playChordNotes(int key, int velocity=-1); void pauseChordNotes(int key); + void updateScrollbars(); + void updatePositionLineHeight(); + QList getAllOctavesForKey( int keyToMirror ) const; int noteEditTop() const; @@ -313,12 +297,6 @@ protected slots: static const int cm_scrollAmtHoriz = 10; static const int cm_scrollAmtVert = 1; - static QPixmap * s_whiteKeyBigPm; - static QPixmap * s_whiteKeyBigPressedPm; - static QPixmap * s_whiteKeySmallPm; - static QPixmap * s_whiteKeySmallPressedPm; - static QPixmap * s_blackKeyPm; - static QPixmap * s_blackKeyPressedPm; static QPixmap * s_toolDraw; static QPixmap * s_toolErase; static QPixmap * s_toolSelect; @@ -330,12 +308,14 @@ protected slots: static TextFloat * s_textFloat; ComboBoxModel m_zoomingModel; + ComboBoxModel m_zoomingYModel; ComboBoxModel m_quantizeModel; ComboBoxModel m_noteLenModel; ComboBoxModel m_scaleModel; ComboBoxModel m_chordModel; static const QVector m_zoomLevels; + static const QVector m_zoomYLevels; Pattern* m_pattern; NoteVector m_ghostNotes; @@ -380,10 +360,17 @@ protected slots: int m_moveStartX; int m_moveStartY; - int m_oldNotesEditHeight; int m_notesEditHeight; - int m_ppt; // pixels per tact + int m_userSetNotesEditHeight; + int m_ppb; // pixels per bar int m_totalKeysToScroll; + int m_pianoKeysVisible; + + int m_keyLineHeight; + int m_octaveHeight; + int m_whiteKeySmallHeight; + int m_whiteKeyBigHeight; + int m_blackKeyHeight; // remember these values to use them // for the next note that is set @@ -391,6 +378,9 @@ protected slots: volume_t m_lastNoteVolume; panning_t m_lastNotePanning; + //When resizing several notes, we want to calculate a common minimum length + MidiTime m_minResizeLen; + int m_startKey; // first key when drawing int m_lastKey; @@ -440,6 +430,18 @@ protected slots: bool m_noteBorders; bool m_ghostNoteBorders; QColor m_backgroundShade; + /* white key properties */ + int m_whiteKeyWidth; + QColor m_whiteKeyActiveTextColor; + QColor m_whiteKeyActiveTextShadow; + QBrush m_whiteKeyActiveBackground; + QColor m_whiteKeyInactiveTextColor; + QColor m_whiteKeyInactiveTextShadow; + QBrush m_whiteKeyInactiveBackground; + /* black key properties */ + int m_blackKeyWidth; + QBrush m_blackKeyActiveBackground; + QBrush m_blackKeyInactiveBackground; signals: void positionChanged( const MidiTime & ); @@ -460,11 +462,11 @@ class PianoRollWindow : public Editor, SerializingObject int quantization() const; - void play(); - void stop(); - void record(); - void recordAccompany(); - void toggleStepRecording(); + void play() override; + void stop() override; + void record() override; + void recordAccompany() override; + void toggleStepRecording() override; void stopRecording(); bool isRecording() const; @@ -474,15 +476,16 @@ class PianoRollWindow : public Editor, SerializingObject using SerializingObject::saveState; using SerializingObject::restoreState; - virtual void saveSettings(QDomDocument & doc, QDomElement & de ); - virtual void loadSettings( const QDomElement & de ); + void saveSettings(QDomDocument & doc, QDomElement & de ) override; + void loadSettings( const QDomElement & de ) override; - inline virtual QString nodeName() const + inline QString nodeName() const override { return "pianoroll"; } - QSize sizeHint() const; + QSize sizeHint() const override; + bool hasFocus() const; signals: void currentPatternChanged(); @@ -494,13 +497,14 @@ private slots: private: void patternRenamed(); - void focusInEvent(QFocusEvent * event); + void focusInEvent(QFocusEvent * event) override; void stopStepRecording(); void updateStepRecordingIcon(); PianoRoll* m_editor; ComboBox * m_zoomingComboBox; + ComboBox * m_zoomingYComboBox; ComboBox * m_quantizeComboBox; ComboBox * m_noteLenComboBox; ComboBox * m_scaleComboBox; diff --git a/include/PianoView.h b/include/PianoView.h index 2a362c5843f..2f2fea2c935 100644 --- a/include/PianoView.h +++ b/include/PianoView.h @@ -44,19 +44,20 @@ class PianoView : public QWidget, public ModelView public: - virtual void keyPressEvent( QKeyEvent * ke ); - virtual void keyReleaseEvent( QKeyEvent * ke ); + void keyPressEvent( QKeyEvent * ke ) override; + void keyReleaseEvent( QKeyEvent * ke ) override; protected: - virtual void modelChanged(); - virtual void contextMenuEvent( QContextMenuEvent * _me ); - virtual void paintEvent( QPaintEvent * ); - virtual void mousePressEvent( QMouseEvent * me ); - virtual void mouseReleaseEvent( QMouseEvent * me ); - virtual void mouseMoveEvent( QMouseEvent * me ); - virtual void focusOutEvent( QFocusEvent * _fe ); - virtual void resizeEvent( QResizeEvent * _event ); + void modelChanged() override; + void contextMenuEvent( QContextMenuEvent * _me ) override; + void paintEvent( QPaintEvent * ) override; + void mousePressEvent( QMouseEvent * me ) override; + void mouseReleaseEvent( QMouseEvent * me ) override; + void mouseMoveEvent( QMouseEvent * me ) override; + void focusOutEvent( QFocusEvent * _fe ) override; + void focusInEvent( QFocusEvent * fe ) override; + void resizeEvent( QResizeEvent * _event ) override; private: diff --git a/include/Pitch.h b/include/Pitch.h index 5ef1c3d62c8..2f866a1c594 100644 --- a/include/Pitch.h +++ b/include/Pitch.h @@ -25,8 +25,7 @@ #ifndef PITCH_H #define PITCH_H -#include "lmms_basics.h" -#include "Midi.h" +#include typedef int16_t pitch_t; diff --git a/include/PixmapButton.h b/include/PixmapButton.h index 6ee7bcdc89c..e2fb5888508 100644 --- a/include/PixmapButton.h +++ b/include/PixmapButton.h @@ -42,17 +42,17 @@ class LMMS_EXPORT PixmapButton : public AutomatableButton void setActiveGraphic( const QPixmap & _pm ); void setInactiveGraphic( const QPixmap & _pm, bool _update = true ); - QSize sizeHint() const; + QSize sizeHint() const override; signals: void doubleClicked(); protected: - virtual void paintEvent( QPaintEvent * _pe ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void mouseDoubleClickEvent( QMouseEvent * _me ); + void paintEvent( QPaintEvent * _pe ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; + void mouseDoubleClickEvent( QMouseEvent * _me ) override; private: diff --git a/include/PlayHandle.h b/include/PlayHandle.h index 1760e1ec7c1..1ddd632d1c3 100644 --- a/include/PlayHandle.h +++ b/include/PlayHandle.h @@ -87,9 +87,9 @@ class LMMS_EXPORT PlayHandle : public ThreadableJob } // required for ThreadableJob - virtual void doProcessing(); + void doProcessing() override; - virtual bool requiresProcessing() const + bool requiresProcessing() const override { return !isFinished(); } diff --git a/include/Plugin.h b/include/Plugin.h index af42b0f1028..86721290409 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -75,6 +75,7 @@ class LMMS_EXPORT Plugin : public Model, public JournallingObject Tool, // additional tool (level-meter etc) Library, // simple library holding a code-base for // several other plugins (e.g. VST-support) + Scripting, // scripting service providers Other, Undefined = 255 } ; @@ -239,7 +240,7 @@ class LMMS_EXPORT Plugin : public Model, public JournallingObject virtual ~Plugin(); //! Return display-name out of sub plugin or descriptor - virtual QString displayName() const; + QString displayName() const override; //! Return logo out of sub plugin or descriptor const PixmapLoader *logo() const; @@ -269,6 +270,9 @@ class LMMS_EXPORT Plugin : public Model, public JournallingObject //! loaded/processed with the help of this plugin virtual void loadFile( const QString & file ); + //! Load plugin-specific preset file, ex. .xpf files for VSTs + virtual void loadPluginPresetFile(const QString & file); + //! Called if external source needs to change something but we cannot //! reference the class header. Should return null if not key not found. virtual AutomatableModel* childModel( const QString & modelName ); @@ -294,12 +298,12 @@ class LMMS_EXPORT Plugin : public Model, public JournallingObject virtual PluginView* instantiateView( QWidget * ) = 0; void collectErrorForUI( QString errMsg ); + Descriptor::SubPluginFeatures::Key m_key; + private: const Descriptor * m_descriptor; - Descriptor::SubPluginFeatures::Key m_key; - // pointer to instantiation-function in plugin typedef Plugin * ( * InstantiationHook )( Model * , void * ); diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.cpp b/include/PositionLine.h similarity index 50% rename from plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.cpp rename to include/PositionLine.h index 4a59b3c0a8a..d48fd3df1cb 100644 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.cpp +++ b/include/PositionLine.h @@ -1,8 +1,9 @@ /* - * SpectrumAnalyzerControls.cpp - controls for spectrum analyzer + * PositionLine.h - declaration of class PositionLine, a simple widget that + * draws a line, mainly works with TimeLineWidget + * + * Copyright (c) 2004-2014 Tobias Doerffel * - * Copyright (c) 2008-2014 Tobias Doerffel - * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -22,40 +23,27 @@ * */ +#ifndef POSITION_LINE_H +#define POSITION_LINE_H -#include "SpectrumAnalyzer.h" -#include "SpectrumAnalyzerControls.h" - - - -SpectrumAnalyzerControls::SpectrumAnalyzerControls( SpectrumAnalyzer* effect ) : - EffectControls( effect ), - m_effect( effect ), - m_linearSpec( false, this, tr( "Linear spectrum" ) ), - m_linearYAxis( false, this, tr( "Linear Y axis" ) ), - m_channelMode( SpectrumAnalyzer::MergeChannels, - SpectrumAnalyzer::MergeChannels, - SpectrumAnalyzer::RightChannel, - this, tr( "Channel mode" ) ) -{ -} - - +#include - -void SpectrumAnalyzerControls::loadSettings( const QDomElement & _this ) +class PositionLine : public QWidget { -} - - - - -void SpectrumAnalyzerControls::saveSettings( QDomDocument & _doc, - QDomElement & _this ) -{ -} - + Q_OBJECT + Q_PROPERTY(bool tailGradient MEMBER m_hasTailGradient) + Q_PROPERTY(QColor lineColor MEMBER m_lineColor) +public: + PositionLine(QWidget* parent); +public slots: + void zoomChange(double zoom); +private: + void paintEvent(QPaintEvent* pe) override; + bool m_hasTailGradient; + QColor m_lineColor; +}; +#endif \ No newline at end of file diff --git a/include/PresetPreviewPlayHandle.h b/include/PresetPreviewPlayHandle.h index 57996fa1714..a95b680abb1 100644 --- a/include/PresetPreviewPlayHandle.h +++ b/include/PresetPreviewPlayHandle.h @@ -38,15 +38,15 @@ class LMMS_EXPORT PresetPreviewPlayHandle : public PlayHandle PresetPreviewPlayHandle( const QString& presetFile, bool loadByPlugin = false, DataFile *dataFile = 0 ); virtual ~PresetPreviewPlayHandle(); - virtual inline bool affinityMatters() const + inline bool affinityMatters() const override { return true; } - virtual void play( sampleFrame* buffer ); - virtual bool isFinished() const; + void play( sampleFrame* buffer ) override; + bool isFinished() const override; - virtual bool isFromTrack( const Track * _track ) const; + bool isFromTrack( const Track * _track ) const override; static void init(); static void cleanup(); diff --git a/include/ProjectNotes.h b/include/ProjectNotes.h index ab82e4eeb8b..fc97a8844e7 100644 --- a/include/ProjectNotes.h +++ b/include/ProjectNotes.h @@ -47,17 +47,17 @@ class LMMS_EXPORT ProjectNotes : public QMainWindow, public SerializingObject void clear(); void setText( const QString & _text ); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; - inline virtual QString nodeName() const + inline QString nodeName() const override { return "projectnotes"; } protected: - virtual void closeEvent( QCloseEvent * _ce ); + void closeEvent( QCloseEvent * _ce ) override; void setupActions(); diff --git a/include/ProjectRenderer.h b/include/ProjectRenderer.h index 4f932ad3495..1af9d422d99 100644 --- a/include/ProjectRenderer.h +++ b/include/ProjectRenderer.h @@ -86,7 +86,7 @@ public slots: private: - virtual void run(); + void run() override; AudioFileDevice * m_fileDev; Mixer::qualitySettings m_qualitySettings; diff --git a/include/RecentProjectsMenu.h b/include/RecentProjectsMenu.h new file mode 100644 index 00000000000..b3837ee2e31 --- /dev/null +++ b/include/RecentProjectsMenu.h @@ -0,0 +1,17 @@ +#ifndef RECENTPROJECTSMENU_H +#define RECENTPROJECTSMENU_H + +#include + +class RecentProjectsMenu : public QMenu +{ + Q_OBJECT +public: + RecentProjectsMenu(QWidget *parent = nullptr); + +private slots: + void fillMenu(); + void openProject(QAction * _action ); +}; + +#endif // RECENTPROJECTSMENU_H diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index 27c658a3d91..c905368319f 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -27,8 +27,8 @@ #include "MidiEvent.h" #include "VstSyncData.h" +#include "IPCHelper.h" -#include #include #include #include @@ -37,379 +37,21 @@ #include -#if !(defined(LMMS_HAVE_SYS_IPC_H) && defined(LMMS_HAVE_SEMAPHORE_H)) -#define SYNC_WITH_SHM_FIFO -#define USE_QT_SEMAPHORES - -#ifdef LMMS_HAVE_PROCESS_H -#include -#endif - -#include -#include -#endif - - -#ifdef LMMS_HAVE_SYS_SHM_H -#include - -#ifdef LMMS_HAVE_UNISTD_H -#include -#endif -#else -#define USE_QT_SHMEM - -#include -#include - -#if !defined(LMMS_HAVE_SYS_TYPES_H) || defined(LMMS_BUILD_WIN32) -typedef int32_t key_t; -#endif -#endif - - -#ifdef LMMS_HAVE_LOCALE_H -#include -#endif - -#ifdef LMMS_HAVE_PTHREAD_H -#include -#endif - - +// Are we building remote plugin? #ifdef BUILD_REMOTE_PLUGIN_CLIENT +// Remote plugin side #undef LMMS_EXPORT #define LMMS_EXPORT #define COMPILE_REMOTE_PLUGIN_BASE -#ifndef SYNC_WITH_SHM_FIFO -#include -#include -#endif - -#else +#else // BUILD_REMOTE_PLUGIN_CLIENT +// LMMS/local plugin side #include "lmms_export.h" -#include -#include -#include - -#ifndef SYNC_WITH_SHM_FIFO -#include -#include -#endif - -#endif - -#ifdef SYNC_WITH_SHM_FIFO -// sometimes we need to exchange bigger messages (e.g. for VST parameter dumps) -// so set a usable value here -const int SHM_FIFO_SIZE = 512*1024; - - -// implements a FIFO inside a shared memory segment -class shmFifo -{ - // need this union to handle different sizes of sem_t on 32 bit - // and 64 bit platforms - union sem32_t - { - int semKey; - char fill[32]; - } ; - struct shmData - { - sem32_t dataSem; // semaphore for locking this - // FIFO management data - sem32_t messageSem; // semaphore for incoming messages - volatile int32_t startPtr; // current start of FIFO in memory - volatile int32_t endPtr; // current end of FIFO in memory - char data[SHM_FIFO_SIZE]; // actual data - } ; - -public: - // constructor for master-side - shmFifo() : - m_invalid( false ), - m_master( true ), - m_shmKey( 0 ), -#ifdef USE_QT_SHMEM - m_shmObj(), -#else - m_shmID( -1 ), -#endif - m_data( NULL ), - m_dataSem( QString() ), - m_messageSem( QString() ), - m_lockDepth( 0 ) - { -#ifdef USE_QT_SHMEM - do - { - m_shmObj.setKey( QString( "%1" ).arg( ++m_shmKey ) ); - m_shmObj.create( sizeof( shmData ) ); - } while( m_shmObj.error() != QSharedMemory::NoError ); - - m_data = (shmData *) m_shmObj.data(); -#else - while( ( m_shmID = shmget( ++m_shmKey, sizeof( shmData ), - IPC_CREAT | IPC_EXCL | 0600 ) ) == -1 ) - { - } - m_data = (shmData *) shmat( m_shmID, 0, 0 ); -#endif - assert( m_data != NULL ); - m_data->startPtr = m_data->endPtr = 0; - static int k = 0; - m_data->dataSem.semKey = ( getpid()<<10 ) + ++k; - m_data->messageSem.semKey = ( getpid()<<10 ) + ++k; - m_dataSem.setKey( QString::number( m_data->dataSem.semKey ), - 1, QSystemSemaphore::Create ); - m_messageSem.setKey( QString::number( - m_data->messageSem.semKey ), - 0, QSystemSemaphore::Create ); - } - - // constructor for remote-/client-side - use _shm_key for making up - // the connection to master - shmFifo( key_t _shm_key ) : - m_invalid( false ), - m_master( false ), - m_shmKey( 0 ), -#ifdef USE_QT_SHMEM - m_shmObj( QString::number( _shm_key ) ), -#else - m_shmID( shmget( _shm_key, 0, 0 ) ), -#endif - m_data( NULL ), - m_dataSem( QString() ), - m_messageSem( QString() ), - m_lockDepth( 0 ) - { -#ifdef USE_QT_SHMEM - if( m_shmObj.attach() ) - { - m_data = (shmData *) m_shmObj.data(); - } -#else - if( m_shmID != -1 ) - { - m_data = (shmData *) shmat( m_shmID, 0, 0 ); - } -#endif - assert( m_data != NULL ); - m_dataSem.setKey( QString::number( m_data->dataSem.semKey ) ); - m_messageSem.setKey( QString::number( - m_data->messageSem.semKey ) ); - } - - ~shmFifo() - { - // master? - if( m_master ) - { -#ifndef USE_QT_SHMEM - shmctl( m_shmID, IPC_RMID, NULL ); -#endif - } -#ifndef USE_QT_SHMEM - shmdt( m_data ); -#endif - } - - inline bool isInvalid() const - { - return m_invalid; - } - - void invalidate() - { - m_invalid = true; - } - - // do we act as master (i.e. not as remote-process?) - inline bool isMaster() const - { - return m_master; - } - - // recursive lock - inline void lock() - { - if( !isInvalid() && m_lockDepth.fetch_add( 1 ) == 0 ) - { - m_dataSem.acquire(); - } - } - - // recursive unlock - inline void unlock() - { - if( m_lockDepth.fetch_sub( 1 ) <= 1 ) - { - m_dataSem.release(); - } - } - - // wait until message-semaphore is available - inline void waitForMessage() - { - if( !isInvalid() ) - { - m_messageSem.acquire(); - } - } - - // increase message-semaphore - inline void messageSent() - { - m_messageSem.release(); - } - - - inline int32_t readInt() - { - int32_t i; - read( &i, sizeof( i ) ); - return i; - } - - inline void writeInt( const int32_t & _i ) - { - write( &_i, sizeof( _i ) ); - } - - inline std::string readString() - { - const int len = readInt(); - if( len ) - { - char * sc = new char[len + 1]; - read( sc, len ); - sc[len] = 0; - std::string s( sc ); - delete[] sc; - return s; - } - return std::string(); - } - - - inline void writeString( const std::string & _s ) - { - const int len = _s.size(); - writeInt( len ); - write( _s.c_str(), len ); - } - - - inline bool messagesLeft() - { - if( isInvalid() ) - { - return false; - } - lock(); - const bool empty = ( m_data->startPtr == m_data->endPtr ); - unlock(); - return !empty; - } - - - inline int shmKey() const - { - return m_shmKey; - } - - -private: - static inline void fastMemCpy( void * _dest, const void * _src, - const int _len ) - { - // calling memcpy() for just an integer is obsolete overhead - if( _len == 4 ) - { - *( (int32_t *) _dest ) = *( (int32_t *) _src ); - } - else - { - memcpy( _dest, _src, _len ); - } - } - - void read( void * _buf, int _len ) - { - if( isInvalid() ) - { - memset( _buf, 0, _len ); - return; - } - lock(); - while( isInvalid() == false && - _len > m_data->endPtr - m_data->startPtr ) - { - unlock(); -#ifndef LMMS_BUILD_WIN32 - usleep( 5 ); -#endif - lock(); - } - fastMemCpy( _buf, m_data->data + m_data->startPtr, _len ); - m_data->startPtr += _len; - // nothing left? - if( m_data->startPtr == m_data->endPtr ) - { - // then reset to 0 - m_data->startPtr = m_data->endPtr = 0; - } - unlock(); - } - - void write( const void * _buf, int _len ) - { - if( isInvalid() || _len > SHM_FIFO_SIZE ) - { - return; - } - lock(); - while( _len > SHM_FIFO_SIZE - m_data->endPtr ) - { - // if no space is left, try to move data to front - if( m_data->startPtr > 0 ) - { - memmove( m_data->data, - m_data->data + m_data->startPtr, - m_data->endPtr - m_data->startPtr ); - m_data->endPtr = m_data->endPtr - - m_data->startPtr; - m_data->startPtr = 0; - } - unlock(); -#ifndef LMMS_BUILD_WIN32 - usleep( 5 ); -#endif - lock(); - } - fastMemCpy( m_data->data + m_data->endPtr, _buf, _len ); - m_data->endPtr += _len; - unlock(); - } - - volatile bool m_invalid; - bool m_master; - key_t m_shmKey; -#ifdef USE_QT_SHMEM - QSharedMemory m_shmObj; -#else - int m_shmID; -#endif - shmData * m_data; - QSystemSemaphore m_dataSem; - QSystemSemaphore m_messageSem; - std::atomic_int m_lockDepth; - -} ; -#endif +#include +#include +#include +#endif // BUILD_REMOTE_PLUGIN_CLIENT enum RemoteMessageIDs @@ -526,14 +168,14 @@ class LMMS_EXPORT RemotePluginBase } ; #ifdef SYNC_WITH_SHM_FIFO - RemotePluginBase( shmFifo * _in, shmFifo * _out ); + RemotePluginBase( ShmFifo * _in, ShmFifo * _out ); #else RemotePluginBase(); #endif virtual ~RemotePluginBase(); #ifdef SYNC_WITH_SHM_FIFO - void reset( shmFifo *in, shmFifo *out ) + void reset( ShmFifo *in, ShmFifo *out ) { delete m_in; delete m_out; @@ -638,12 +280,12 @@ class LMMS_EXPORT RemotePluginBase protected: #ifdef SYNC_WITH_SHM_FIFO - inline const shmFifo * in() const + inline const ShmFifo * in() const { return m_in; } - inline const shmFifo * out() const + inline const ShmFifo * out() const { return m_out; } @@ -676,8 +318,8 @@ class LMMS_EXPORT RemotePluginBase #endif #ifdef SYNC_WITH_SHM_FIFO - shmFifo * m_in; - shmFifo * m_out; + ShmFifo * m_in; + ShmFifo * m_out; #else void read( void * _buf, int _len ) { @@ -766,7 +408,7 @@ class ProcessWatcher : public QThread } private: - virtual void run(); + void run() override; RemotePlugin * m_plugin; volatile bool m_quit; @@ -803,7 +445,7 @@ class LMMS_EXPORT RemotePlugin : public QObject, public RemotePluginBase m_failed = waitForMessage( IdInitDone, _busyWaiting ).id != IdInitDone; } - virtual bool processMessage( const message & _m ); + bool processMessage( const message & _m ) override; bool process( const sampleFrame * _in_buf, sampleFrame * _out_buf ); @@ -873,11 +515,7 @@ public slots: QMutex m_commMutex; bool m_splitChannels; -#ifdef USE_QT_SHMEM - QSharedMemory m_shmObj; -#else - int m_shmID; -#endif + SharedMemory m_shmObj; size_t m_shmSize; float * m_shm; @@ -906,14 +544,14 @@ class RemotePluginClient : public RemotePluginBase { public: #ifdef SYNC_WITH_SHM_FIFO - RemotePluginClient( key_t _shm_in, key_t _shm_out ); + RemotePluginClient(key_t shmIn, key_t shmOut, key_t shmVstSync); #else - RemotePluginClient( const char * socketPath ); + RemotePluginClient(const char * socketPath, key_t shmVstSync); #endif virtual ~RemotePluginClient(); -#ifdef USE_QT_SHMEM - VstSyncData * getQtVSTshm(); -#endif + + VstSyncData * getVSTshm(); + virtual bool processMessage( const message & _m ); virtual void process( const sampleFrame * _in_buf, @@ -987,10 +625,9 @@ class RemotePluginClient : public RemotePluginBase void setShmKey( key_t _key, int _size ); void doProcessing(); -#ifdef USE_QT_SHMEM - QSharedMemory m_shmObj; - QSharedMemory m_shmQtID; -#endif + SharedMemory m_shmObj; + SharedMemory m_shmVstSync; + VstSyncData * m_vstSyncData; float * m_shm; @@ -1016,7 +653,7 @@ class RemotePluginClient : public RemotePluginBase #ifdef SYNC_WITH_SHM_FIFO -RemotePluginBase::RemotePluginBase( shmFifo * _in, shmFifo * _out ) : +RemotePluginBase::RemotePluginBase( ShmFifo * _in, ShmFifo * _out ) : m_in( _in ), m_out( _out ) #else @@ -1184,16 +821,14 @@ RemotePluginBase::message RemotePluginBase::waitForMessage( #ifdef SYNC_WITH_SHM_FIFO -RemotePluginClient::RemotePluginClient( key_t _shm_in, key_t _shm_out ) : - RemotePluginBase( new shmFifo( _shm_in ), new shmFifo( _shm_out ) ), +RemotePluginClient::RemotePluginClient(key_t shmIn, key_t shmOut, key_t shmVstSync) : + RemotePluginBase(new ShmFifo(shmIn), new ShmFifo(shmOut)), #else -RemotePluginClient::RemotePluginClient( const char * socketPath ) : +RemotePluginClient::RemotePluginClient(const char * socketPath, key_t shmVstSync) : RemotePluginBase(), #endif -#ifdef USE_QT_SHMEM m_shmObj(), - m_shmQtID( "/usr/bin/lmms" ), -#endif + m_shmVstSync(shmVstSync), m_vstSyncData( NULL ), m_shm( NULL ), m_inputCount( 0 ), @@ -1225,52 +860,14 @@ RemotePluginClient::RemotePluginClient( const char * socketPath ) : } #endif -#ifdef USE_QT_SHMEM - if( m_shmQtID.attach( QSharedMemory::ReadOnly ) ) + if (m_shmVstSync.attach(true)) { - m_vstSyncData = (VstSyncData *) m_shmQtID.data(); + m_vstSyncData = (VstSyncData *) m_shmVstSync.get(); m_bufferSize = m_vstSyncData->m_bufferSize; m_sampleRate = m_vstSyncData->m_sampleRate; sendMessage( IdHostInfoGotten ); return; } -#else - key_t key; - int m_shmID; - - if( ( key = ftok( VST_SNC_SHM_KEY_FILE, 'R' ) ) == -1 ) - { - perror( "RemotePluginClient::ftok" ); - } - else - { // connect to shared memory segment - if( ( m_shmID = shmget( key, 0, 0 ) ) == -1 ) - { - perror( "RemotePluginClient::shmget" ); - } - else - { // attach segment - m_vstSyncData = (VstSyncData *)shmat(m_shmID, 0, 0); - if( m_vstSyncData == (VstSyncData *)( -1 ) ) - { - perror( "RemotePluginClient::shmat" ); - } - else - { - m_bufferSize = m_vstSyncData->m_bufferSize; - m_sampleRate = m_vstSyncData->m_sampleRate; - sendMessage( IdHostInfoGotten ); - - // detach segment - if( shmdt(m_vstSyncData) == -1 ) - { - perror("RemotePluginClient::shmdt"); - } - return; - } - } - } -#endif // if attaching shared memory fails sendMessage( IdSampleRateInformation ); @@ -1288,15 +885,6 @@ RemotePluginClient::RemotePluginClient( const char * socketPath ) : RemotePluginClient::~RemotePluginClient() { -#ifdef USE_QT_SHMEM - m_shmQtID.detach(); -#endif - sendMessage( IdQuit ); - -#ifndef USE_QT_SHMEM - shmdt( m_shm ); -#endif - #ifndef SYNC_WITH_SHM_FIFO if ( close( m_socket ) == -1) { @@ -1307,12 +895,10 @@ RemotePluginClient::~RemotePluginClient() -#ifdef USE_QT_SHMEM -VstSyncData * RemotePluginClient::getQtVSTshm() +VstSyncData * RemotePluginClient::getVSTshm() { return m_vstSyncData; } -#endif @@ -1385,43 +971,15 @@ bool RemotePluginClient::processMessage( const message & _m ) -void RemotePluginClient::setShmKey( key_t _key, int _size ) +void RemotePluginClient::setShmKey(key_t key, int size) { -#ifdef USE_QT_SHMEM - m_shmObj.setKey( QString::number( _key ) ); - if( m_shmObj.attach() || m_shmObj.error() == QSharedMemory::NoError ) - { - m_shm = (float *) m_shmObj.data(); - } - else + (void)size; + m_shmObj.setKey(key); + if (!(m_shm = (float*)m_shmObj.attach())) { - char buf[64]; - sprintf( buf, "failed getting shared memory: %d\n", m_shmObj.error() ); - debugMessage( buf ); + std::string errorMsg = "failed getting shared memory: " + m_shmObj.errorMessage() + "\n"; + debugMessage(errorMsg.data()); } -#else - if( m_shm != NULL ) - { - shmdt( m_shm ); - m_shm = NULL; - } - - // only called for detaching SHM? - if( _key == 0 ) - { - return; - } - - int shm_id = shmget( _key, _size, 0 ); - if( shm_id == -1 ) - { - debugMessage( "failed getting shared memory\n" ); - } - else - { - m_shm = (float *) shmat( shm_id, 0, 0 ); - } -#endif } diff --git a/include/RenameDialog.h b/include/RenameDialog.h index c1d24a8a9d7..8f526baddad 100644 --- a/include/RenameDialog.h +++ b/include/RenameDialog.h @@ -42,8 +42,8 @@ class RenameDialog : public QDialog protected: - void keyPressEvent( QKeyEvent * _ke ); - virtual void resizeEvent(QResizeEvent * event); + void keyPressEvent( QKeyEvent * _ke ) override; + void resizeEvent(QResizeEvent * event) override; protected slots: diff --git a/include/RenderManager.h b/include/RenderManager.h index 01236d7476a..22e918107a0 100644 --- a/include/RenderManager.h +++ b/include/RenderManager.h @@ -28,11 +28,13 @@ #include +#include "lmms_export.h" + #include "ProjectRenderer.h" #include "OutputSettings.h" -class RenderManager : public QObject +class LMMS_EXPORT RenderManager : public QObject { Q_OBJECT public: diff --git a/include/RingBuffer.h b/include/RingBuffer.h index c761616bd78..c7e91bd3392 100644 --- a/include/RingBuffer.h +++ b/include/RingBuffer.h @@ -32,6 +32,8 @@ #include "lmms_math.h" #include "MemoryManager.h" +/** \brief A basic LMMS ring buffer for single-thread use. For thread and realtime safe alternative see LocklessRingBuffer. +*/ class LMMS_EXPORT RingBuffer : public QObject { Q_OBJECT diff --git a/include/RowTableView.h b/include/RowTableView.h index 537792a0511..a7b07c2c893 100644 --- a/include/RowTableView.h +++ b/include/RowTableView.h @@ -38,11 +38,11 @@ class RowTableView : public QTableView RowTableView( QWidget * parent = 0 ); virtual ~RowTableView(); - virtual void setModel( QAbstractItemModel * model ); + void setModel( QAbstractItemModel * model ) override; protected: - virtual void keyPressEvent( QKeyEvent * event ); + void keyPressEvent( QKeyEvent * event ) override; private: diff --git a/include/Rubberband.h b/include/Rubberband.h index bc9f3c6a200..eeb3c7e5b9a 100644 --- a/include/Rubberband.h +++ b/include/Rubberband.h @@ -83,7 +83,7 @@ class RubberBand : public QRubberBand protected: - virtual void resizeEvent( QResizeEvent * _re ); + void resizeEvent( QResizeEvent * _re ) override; private: diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h index 26e85602508..89a3add3b2a 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -84,7 +84,7 @@ class LMMS_EXPORT SampleBuffer : public QObject, public sharedObject { m_isBackwards = _backwards; } - + int interpolationMode() const { return m_interpolationMode; @@ -251,9 +251,6 @@ class LMMS_EXPORT SampleBuffer : public QObject, public sharedObject m_varLock.unlock(); } - static QString tryToMakeRelative( const QString & _file ); - static QString tryToMakeAbsolute(const QString & file); - public slots: void setAudioFile( const QString & _audio_file ); diff --git a/include/SamplePlayHandle.h b/include/SamplePlayHandle.h index d10c448378c..33f5ebe5294 100644 --- a/include/SamplePlayHandle.h +++ b/include/SamplePlayHandle.h @@ -44,16 +44,16 @@ class SamplePlayHandle : public PlayHandle SamplePlayHandle( SampleTCO* tco ); virtual ~SamplePlayHandle(); - virtual inline bool affinityMatters() const + inline bool affinityMatters() const override { return true; } - virtual void play( sampleFrame * buffer ); - virtual bool isFinished() const; + void play( sampleFrame * buffer ) override; + bool isFinished() const override; - virtual bool isFromTrack( const Track * _track ) const; + bool isFromTrack( const Track * _track ) const override; f_cnt_t totalFrames() const; inline f_cnt_t framesDone() const diff --git a/include/SampleRecordHandle.h b/include/SampleRecordHandle.h index 22d9bf3156c..fc40d062295 100644 --- a/include/SampleRecordHandle.h +++ b/include/SampleRecordHandle.h @@ -44,10 +44,10 @@ class SampleRecordHandle : public PlayHandle SampleRecordHandle( SampleTCO* tco ); virtual ~SampleRecordHandle(); - virtual void play( sampleFrame * _working_buffer ); - virtual bool isFinished() const; + void play( sampleFrame * _working_buffer ) override; + bool isFinished() const override; - virtual bool isFromTrack( const Track * _track ) const; + bool isFromTrack( const Track * _track ) const override; f_cnt_t framesRecorded() const; void createSampleBuffer( SampleBuffer * * _sample_buf ); diff --git a/include/SampleTrack.h b/include/SampleTrack.h index ccb5a020e85..779a59abe57 100644 --- a/include/SampleTrack.h +++ b/include/SampleTrack.h @@ -29,6 +29,7 @@ #include #include "AudioPort.h" +#include "FadeButton.h" #include "FxMixer.h" #include "FxLineLcdSpinBox.h" #include "Track.h" @@ -41,7 +42,7 @@ class TrackLabelButton; class QLineEdit; -class SampleTCO : public TrackContentObject +class LMMS_EXPORT SampleTCO : public TrackContentObject { Q_OBJECT mapPropertyFromModel(bool,isRecord,setRecord,m_recordModel); @@ -49,12 +50,12 @@ class SampleTCO : public TrackContentObject SampleTCO( Track * _track ); virtual ~SampleTCO(); - virtual void changeLength( const MidiTime & _length ); + void changeLength( const MidiTime & _length ) override; const QString & sampleFile() const; - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + inline QString nodeName() const override { return "sampletco"; } @@ -67,7 +68,7 @@ class SampleTCO : public TrackContentObject MidiTime sampleLength() const; void setSampleStartFrame( f_cnt_t startFrame ); void setSamplePlayLength( f_cnt_t length ); - virtual TrackContentObjectView * createView( TrackView * _tv ); + TrackContentObjectView * createView( TrackView * _tv ) override; bool isPlaying() const; @@ -112,13 +113,13 @@ public slots: protected: - virtual void contextMenuEvent( QContextMenuEvent * _cme ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void dropEvent( QDropEvent * _de ); - virtual void mouseDoubleClickEvent( QMouseEvent * ); - virtual void paintEvent( QPaintEvent * ); + void contextMenuEvent( QContextMenuEvent * _cme ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; + void dragEnterEvent( QDragEnterEvent * _dee ) override; + void dropEvent( QDropEvent * _de ) override; + void mouseDoubleClickEvent( QMouseEvent * ) override; + void paintEvent( QPaintEvent * ) override; private: @@ -137,14 +138,14 @@ class SampleTrack : public Track virtual ~SampleTrack(); virtual bool play( const MidiTime & _start, const fpp_t _frames, - const f_cnt_t _frame_base, int _tco_num = -1 ); - virtual TrackView * createView( TrackContainerView* tcv ); - virtual TrackContentObject * createTCO( const MidiTime & _pos ); + const f_cnt_t _frame_base, int _tco_num = -1 ) override; + TrackView * createView( TrackContainerView* tcv ) override; + TrackContentObject * createTCO( const MidiTime & _pos ) override; virtual void saveTrackSpecificSettings( QDomDocument & _doc, - QDomElement & _parent ); - virtual void loadTrackSpecificSettings( const QDomElement & _this ); + QDomElement & _parent ) override; + void loadTrackSpecificSettings( const QDomElement & _this ) override; inline IntModel * effectChannelModel() { @@ -156,11 +157,25 @@ class SampleTrack : public Track return &m_audioPort; } - virtual QString nodeName() const + QString nodeName() const override { return "sampletrack"; } + bool isPlaying() + { + return m_isPlaying; + } + + void setPlaying(bool playing) + { + if (m_isPlaying != playing) { emit playingChanged(); } + m_isPlaying = playing; + } + +signals: + void playingChanged(); + public slots: void updateTcos(); void setPlayingTcos( bool isPlaying ); @@ -171,6 +186,7 @@ public slots: FloatModel m_panningModel; IntModel m_effectChannelModel; AudioPort m_audioPort; + bool m_isPlaying; @@ -204,20 +220,23 @@ class SampleTrackView : public TrackView } - virtual QMenu * createFxMenu( QString title, QString newFxLabel ); + QMenu * createFxMenu( QString title, QString newFxLabel ) override; public slots: void showEffects(); + void updateIndicator(); protected: - void modelChanged(); - virtual QString nodeName() const + void modelChanged() override; + QString nodeName() const override { return "SampleTrackView"; } + void dragEnterEvent(QDragEnterEvent *dee) override; + void dropEvent(QDropEvent *de) override; private slots: void assignFxLine( int channelIndex ); @@ -228,9 +247,14 @@ private slots: SampleTrackWindow * m_window; Knob * m_volumeKnob; Knob * m_panningKnob; + FadeButton * m_activityIndicator; TrackLabelButton * m_tlb; + FadeButton * getActivityIndicator() + { + return m_activityIndicator; + } friend class SampleTrackWindow; @@ -271,13 +295,13 @@ public slots: protected: // capture close-events for toggling sample-track-button - virtual void closeEvent(QCloseEvent * ce); + void closeEvent(QCloseEvent * ce) override; - virtual void saveSettings(QDomDocument & doc, QDomElement & element); - virtual void loadSettings(const QDomElement & element); + void saveSettings(QDomDocument & doc, QDomElement & element) override; + void loadSettings(const QDomElement & element) override; private: - virtual void modelChanged(); + void modelChanged() override; SampleTrack * m_track; SampleTrackView * m_stv; diff --git a/include/ScriptPlugin.h b/include/ScriptPlugin.h new file mode 100644 index 00000000000..11d82d5ce82 --- /dev/null +++ b/include/ScriptPlugin.h @@ -0,0 +1,54 @@ +/* + * ScriptPlugin.h - base class for scripting plugins + * + * Copyright (c) 2019 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef SCRIPTPLUGIN_H +#define SCRIPTPLUGIN_H + +#include "Plugin.h" +#include "Engine.h" + +class LMMS_EXPORT ScriptPlugin : public Plugin +{ + MM_OPERATORS + Q_OBJECT +public: + ScriptPlugin(const Plugin::Descriptor * desc, + Model * parent, + const Descriptor::SubPluginFeatures::Key * key); + virtual ~ScriptPlugin() = default; + + inline QString nodeName() const override + { + return "scriptingplugin"; + } + + // FIXME this should be able to return a meaningful result value or maybe an exception + virtual void evaluateScript(const QString & scriptName, const QString & scriptContent) = 0; + +private: + ; +}; + + +#endif // #ifndef SCRIPTPLUGIN_H diff --git a/include/SendButtonIndicator.h b/include/SendButtonIndicator.h index 97acde1ba5e..b60113758d7 100644 --- a/include/SendButtonIndicator.h +++ b/include/SendButtonIndicator.h @@ -17,7 +17,7 @@ class SendButtonIndicator : public QLabel SendButtonIndicator( QWidget * _parent, FxLine * _owner, FxMixerView * _mv); - virtual void mousePressEvent( QMouseEvent * e ); + void mousePressEvent( QMouseEvent * e ) override; void updateLightStatus(); private: diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 272ba7b093f..7aabde08618 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -1,4 +1,3 @@ - /* * SetupDialog.h - dialog for setting up LMMS * @@ -23,20 +22,20 @@ * */ + #ifndef SETUP_DIALOG_H #define SETUP_DIALOG_H #include #include +#include "AudioDevice.h" +#include "AudioDeviceSetupWidget.h" #include "LedCheckbox.h" #include "lmmsconfig.h" -#include "AudioDevice.h" #include "MidiClient.h" #include "MidiSetupWidget.h" -#include "AudioDeviceSetupWidget.h" - class QComboBox; class QLabel; @@ -48,167 +47,161 @@ class TabBar; class SetupDialog : public QDialog { Q_OBJECT + public: enum ConfigTabs { GeneralSettings, - PathSettings, PerformanceSettings, AudioSettings, - MidiSettings - } ; + MidiSettings, + PathsSettings + }; - SetupDialog( ConfigTabs _tab_to_open = GeneralSettings ); + SetupDialog(ConfigTabs tab_to_open = GeneralSettings); virtual ~SetupDialog(); protected slots: - virtual void accept(); + void accept() override; private slots: - // general settings widget - void setBufferSize( int _value ); - void resetBufSize(); - - // path settings widget - void setWorkingDir( const QString & _wd ); - void setVSTDir( const QString & _vd ); - void setGIGDir( const QString & _gd ); - void setSF2Dir( const QString & _sfd ); - void setArtworkDir( const QString & _ad ); - void setLADSPADir( const QString & _ld ); - void setSTKDir( const QString & _sd ); - void setDefaultSoundfont( const QString & _sf ); - void setBackgroundArtwork( const QString & _ba ); - - // performance settings widget - void setAutoSaveInterval( int time ); + // General settings widget. + void toggleDisplaydBFS(bool enabled); + void toggleTooltips(bool enabled); + void toggleDisplayWaveform(bool enabled); + void toggleNoteLabels(bool enabled); + void toggleCompactTrackButtons(bool enabled); + void toggleOneInstrumentTrackWindow(bool enabled); + void toggleSideBarOnRight(bool enabled); + void toggleSoloLegacyBehavior(bool enabled); + void toggleMMPZ(bool enabled); + void toggleDisableBackup(bool enabled); + void toggleOpenLastProject(bool enabled); + void setLanguage(int lang); + + // Performance settings widget. + void setAutoSaveInterval(int time); void resetAutoSave(); + void toggleAutoSave(bool enabled); + void toggleRunningAutoSave(bool enabled); + void toggleSmoothScroll(bool enabled); + void toggleAnimateAFP(bool enabled); + void toggleSyncVSTPlugins(bool enabled); + void vstEmbedMethodChanged(); + void toggleVSTAlwaysOnTop(bool en); + void toggleDisableAutoQuit(bool enabled); - // audio settings widget - void audioInterfaceChanged( const QString & _driver ); - - // MIDI settings widget - void midiInterfaceChanged( const QString & _driver ); - + // Audio settings widget. + void audioInterfaceChanged(const QString & driver); + void toggleHQAudioDev(bool enabled); + void setBufferSize(int value); + void resetBufferSize(); - void toggleToolTips( bool _enabled ); - void toggleWarnAfterSetup( bool _enabled ); - void toggleDisplaydBFS( bool _enabled ); - void toggleMMPZ( bool _enabled ); - void toggleDisableBackup( bool _enabled ); - void toggleOpenLastProject( bool _enabled ); - void toggleHQAudioDev( bool _enabled ); + // MIDI settings widget. + void midiInterfaceChanged(const QString & driver); + // Paths settings widget. void openWorkingDir(); + void setWorkingDir(const QString & workingDir); void openVSTDir(); - void openGIGDir(); - void openSF2Dir(); - void openArtworkDir(); + void setVSTDir(const QString & vstDir); void openLADSPADir(); - void openSTKDir(); - void openDefaultSoundfont(); - void openBackgroundArtwork(); - - void toggleSmoothScroll( bool _enabled ); - void toggleAutoSave( bool _enabled ); - void toggleRunningAutoSave( bool _enabled ); - void toggleOneInstrumentTrackWindow( bool _enabled ); - void toggleCompactTrackButtons( bool _enabled ); - void toggleSyncVSTPlugins( bool _enabled ); - void toggleAnimateAFP( bool _enabled ); - void toggleNoteLabels( bool en ); - void toggleDisplayWaveform( bool en ); - void toggleDisableAutoquit( bool en ); - - void vstEmbedMethodChanged(); - void toggleVSTAlwaysOnTop( bool en ); - - void setLanguage( int lang ); + void setLADSPADir(const QString & ladspaDir); + void openSF2Dir(); + void setSF2Dir(const QString & sf2Dir); + void openSF2File(); + void setSF2File(const QString & sf2File); + void openGIGDir(); + void setGIGDir(const QString & gigDir); + void openThemeDir(); + void setThemeDir(const QString & themeDir); + void openBackgroundPicFile(); + void setBackgroundPicFile(const QString & backgroundPicFile); + void showRestartWarning(); private: TabBar * m_tabBar; - QSlider * m_bufSizeSlider; - QLabel * m_bufSizeLbl; - int m_bufferSize; - - bool m_toolTips; - bool m_warnAfterSetup; + // General settings widgets. bool m_displaydBFS; + bool m_tooltips; + bool m_displayWaveform; + bool m_printNoteLabels; + bool m_compactTrackButtons; + bool m_oneInstrumentTrackWindow; + bool m_sideBarOnRight; + bool m_soloLegacyBehavior; bool m_MMPZ; bool m_disableBackup; bool m_openLastProject; - bool m_NaNHandler; - bool m_hqAudioDev; QString m_lang; QStringList m_languages; - - QLineEdit * m_wdLineEdit; - QLineEdit * m_vdLineEdit; - QLineEdit * m_adLineEdit; - QLineEdit * m_ladLineEdit; - QLineEdit * m_gigLineEdit; - QLineEdit * m_sf2LineEdit; -#ifdef LMMS_HAVE_FLUIDSYNTH - QLineEdit * m_sfLineEdit; -#endif -#ifdef LMMS_HAVE_STK - QLineEdit * m_stkLineEdit; -#endif - QLineEdit * m_baLineEdit; - - QString m_workingDir; - QString m_vstDir; - QString m_artworkDir; - QString m_ladDir; - QString m_gigDir; - QString m_sf2Dir; -#ifdef LMMS_HAVE_FLUIDSYNTH - QString m_defaultSoundfont; -#endif -#ifdef LMMS_HAVE_STK - QString m_stkDir; -#endif - QString m_backgroundArtwork; - - bool m_smoothScroll; + // Performance settings widgets. + int m_saveInterval; bool m_enableAutoSave; bool m_enableRunningAutoSave; - int m_saveInterval; QSlider * m_saveIntervalSlider; QLabel * m_saveIntervalLbl; LedCheckBox * m_autoSave; LedCheckBox * m_runningAutoSave; - - bool m_oneInstrumentTrackWindow; - bool m_compactTrackButtons; - bool m_syncVSTPlugins; + bool m_smoothScroll; bool m_animateAFP; - bool m_printNoteLabels; - bool m_displayWaveform; + QLabel * m_vstEmbedLbl; + QComboBox* m_vstEmbedComboBox; + QString m_vstEmbedMethod; + LedCheckBox * m_vstAlwaysOnTopCheckBox; + bool m_vstAlwaysOnTop; + bool m_syncVSTPlugins; bool m_disableAutoQuit; + typedef QMap AswMap; typedef QMap MswMap; typedef QMap trMap; + // Audio settings widgets. QComboBox * m_audioInterfaces; AswMap m_audioIfaceSetupWidgets; trMap m_audioIfaceNames; + bool m_NaNHandler; + bool m_hqAudioDev; + int m_bufferSize; + QSlider * m_bufferSizeSlider; + QLabel * m_bufferSizeLbl; + // MIDI settings widgets. QComboBox * m_midiInterfaces; MswMap m_midiIfaceSetupWidgets; trMap m_midiIfaceNames; + QComboBox * m_assignableMidiDevices; - QComboBox* m_vstEmbedComboBox; - QString m_vstEmbedMethod; - LedCheckBox * m_vstAlwaysOnTopCheckBox; - bool m_vstAlwaysOnTop; -} ; - + // Paths settings widgets. + QString m_workingDir; + QString m_vstDir; + QString m_ladspaDir; + QString m_gigDir; + QString m_sf2Dir; +#ifdef LMMS_HAVE_FLUIDSYNTH + QString m_sf2File; +#endif + QString m_themeDir; + QString m_backgroundPicFile; + + QLineEdit * m_workingDirLineEdit; + QLineEdit * m_vstDirLineEdit; + QLineEdit * m_themeDirLineEdit; + QLineEdit * m_ladspaDirLineEdit; + QLineEdit * m_gigDirLineEdit; + QLineEdit * m_sf2DirLineEdit; +#ifdef LMMS_HAVE_FLUIDSYNTH + QLineEdit * m_sf2FileLineEdit; +#endif + QLineEdit * m_backgroundPicFileLineEdit; + QLabel * restartWarningLbl; +}; #endif diff --git a/include/SideBarWidget.h b/include/SideBarWidget.h index 229f07df032..9972daa7c19 100644 --- a/include/SideBarWidget.h +++ b/include/SideBarWidget.h @@ -28,6 +28,7 @@ #include #include #include +#include class SideBarWidget : public QWidget @@ -47,11 +48,13 @@ class SideBarWidget : public QWidget return m_title; } +signals: + void closeButtonClicked(); protected: - virtual void paintEvent( QPaintEvent * _pe ); - virtual void resizeEvent( QResizeEvent * _re ); - virtual void contextMenuEvent( QContextMenuEvent * ) + void paintEvent( QPaintEvent * _pe ) override; + void resizeEvent( QResizeEvent * _re ) override; + void contextMenuEvent( QContextMenuEvent * ) override { } @@ -75,6 +78,8 @@ class SideBarWidget : public QWidget QVBoxLayout * m_layout; QString m_title; QPixmap m_icon; + QPushButton * m_closeBtn; + const QSize m_buttonSize; } ; diff --git a/include/Song.h b/include/Song.h index 32ead7181f5..c7aa18bf151 100644 --- a/include/Song.h +++ b/include/Song.h @@ -45,7 +45,7 @@ class TimeLineWidget; const bpm_t MinTempo = 10; const bpm_t DefaultTempo = 140; const bpm_t MaxTempo = 999; -const tick_t MaxSongLength = 9999 * DefaultTicksPerTact; +const tick_t MaxSongLength = 9999 * DefaultTicksPerBar; class LMMS_EXPORT Song : public TrackContainer @@ -155,14 +155,14 @@ class LMMS_EXPORT Song : public TrackContainer m_playPos[playMode].setTicks(ticks); } - inline int getTacts() const + inline int getBars() const { - return currentTact(); + return currentBar(); } - inline int ticksPerTact() const + inline int ticksPerBar() const { - return MidiTime::ticksPerTact(m_timeSigModel); + return MidiTime::ticksPerBar(m_timeSigModel); } // Returns the beat position inside the bar, 0-based @@ -254,14 +254,14 @@ class LMMS_EXPORT Song : public TrackContainer } void updateLength(); - tact_t length() const + bar_t length() const { return m_length; } bpm_t getTempo(); - virtual AutomationPattern * tempoAutomationPattern(); + AutomationPattern * tempoAutomationPattern() override; AutomationTrack * globalAutomationTrack() { @@ -269,7 +269,7 @@ class LMMS_EXPORT Song : public TrackContainer } //TODO: Add Q_DECL_OVERRIDE when Qt4 is dropped - AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum = -1) const; + AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum = -1) const override; // file management void createNewProject(); @@ -305,7 +305,7 @@ class LMMS_EXPORT Song : public TrackContainer return m_modified; } - virtual QString nodeName() const + QString nodeName() const override { return "song"; } @@ -339,6 +339,16 @@ class LMMS_EXPORT Song : public TrackContainer bool isSavingProject() const; + inline VstSyncController& vstSyncController() + { + return m_vstSyncController; + } + + inline const VstSyncController& vstSyncController() const + { + return m_vstSyncController; + } + public slots: void playSong(); void record(); @@ -382,9 +392,9 @@ private slots: virtual ~Song(); - inline tact_t currentTact() const + inline bar_t currentBar() const { - return m_playPos[m_playMode].getTact(); + return m_playPos[m_playMode].getBar(); } inline tick_t currentTick() const @@ -415,7 +425,7 @@ private slots: IntModel m_tempoModel; MeterModel m_timeSigModel; - int m_oldTicksPerTact; + int m_oldTicksPerBar; IntModel m_masterVolumeModel; IntModel m_masterPitchModel; @@ -441,18 +451,18 @@ private slots: SaveOptions m_saveOptions; - QStringList m_errors; + QHash m_errors; PlayModes m_playMode; PlayPos m_playPos[Mode_Count]; - tact_t m_length; + bar_t m_length; const Pattern* m_patternToPlay; bool m_loopPattern; double m_elapsedMilliSeconds[Mode_Count]; tick_t m_elapsedTicks; - tact_t m_elapsedTacts; + bar_t m_elapsedBars; VstSyncController m_vstSyncController; @@ -473,9 +483,9 @@ private slots: void projectLoaded(); void playbackStateChanged(); void playbackPositionChanged(); - void lengthChanged( int tacts ); + void lengthChanged( int bars ); void tempoChanged( bpm_t newBPM ); - void timeSignatureChanged( int oldTicksPerTact, int ticksPerTact ); + void timeSignatureChanged( int oldTicksPerBar, int ticksPerBar ); void controllerAdded( Controller * ); void controllerRemoved( Controller * ); void updateSampleTracks(); diff --git a/include/SongEditor.h b/include/SongEditor.h index f9b6aad1b56..7e0fe986a8c 100644 --- a/include/SongEditor.h +++ b/include/SongEditor.h @@ -28,10 +28,12 @@ #define SONG_EDITOR_H #include +#include #include "ActionGroup.h" #include "Editor.h" #include "TrackContainerView.h" +#include "PositionLine.h" class QLabel; class QScrollBar; @@ -45,16 +47,6 @@ class Song; class TextFloat; class TimeLineWidget; -class positionLine : public QWidget -{ -public: - positionLine( QWidget * parent ); - -private: - virtual void paintEvent( QPaintEvent * pe ); - -} ; - class SongEditor : public TrackContainerView { @@ -69,24 +61,34 @@ class SongEditor : public TrackContainerView SongEditor( Song * song ); ~SongEditor(); - void saveSettings( QDomDocument& doc, QDomElement& element ); - void loadSettings( const QDomElement& element ); + void saveSettings( QDomDocument& doc, QDomElement& element ) override; + void loadSettings( const QDomElement& element ) override; ComboBoxModel *zoomingModel() const; + ComboBoxModel *snappingModel() const; + float getSnapSize() const; + QString getSnapSizeString() const; public slots: void scrolled( int new_pos ); + void selectRegionFromPixels(int xStart, int xEnd); + void stopSelectRegion(); + void updateRubberband(); void setEditMode( EditMode mode ); void setEditModeDraw(); void setEditModeSelect(); + void toggleProportionalSnap(); void updatePosition( const MidiTime & t ); void updatePositionLine(); void selectAllTcos( bool select ); protected: - virtual void closeEvent( QCloseEvent * ce ); + void closeEvent( QCloseEvent * ce ) override; + void mousePressEvent(QMouseEvent * me) override; + void mouseMoveEvent(QMouseEvent * me) override; + void mouseReleaseEvent(QMouseEvent * me) override; private slots: void setHighQuality( bool ); @@ -106,10 +108,13 @@ private slots: void zoomingChanged(); private: - virtual void keyPressEvent( QKeyEvent * ke ); - virtual void wheelEvent( QWheelEvent * we ); + void keyPressEvent( QKeyEvent * ke ) override; + void wheelEvent( QWheelEvent * we ) override; + + bool allowRubberband() const override; - virtual bool allowRubberband() const; + int trackIndexFromSelectionPoint(int yPos); + int indexOfTrackView(const TrackView* tv); Song * m_song; @@ -127,21 +132,33 @@ private slots: TextFloat * m_mvsStatus; TextFloat * m_mpsStatus; - positionLine * m_positionLine; + PositionLine * m_positionLine; ComboBoxModel* m_zoomingModel; + ComboBoxModel* m_snappingModel; + bool m_proportionalSnap; static const QVector m_zoomLevels; bool m_scrollBack; bool m_smoothScroll; - int m_widgetWidthTotal; EditMode m_mode; EditMode m_ctrlMode; // mode they were in before they hit ctrl + QPoint m_origin; + QPoint m_scrollPos; + QPoint m_mousePos; + int m_rubberBandStartTrackview; + MidiTime m_rubberbandStartMidipos; + int m_currentZoomingValue; + int m_trackHeadWidth; + bool m_selectRegion; + friend class SongEditorWindow; +signals: + void zoomingValueChanged( double ); } ; @@ -153,34 +170,37 @@ class SongEditorWindow : public Editor public: SongEditorWindow( Song* song ); - QSize sizeHint() const; + QSize sizeHint() const override; SongEditor* m_editor; protected: - virtual void resizeEvent( QResizeEvent * event ); - virtual void changeEvent( QEvent * ); + void resizeEvent( QResizeEvent * event ) override; + void changeEvent( QEvent * ) override; protected slots: - void play(); - void record(); - void recordAccompany(); - void stop(); + void play() override; + void record() override; + void recordAccompany() override; + void stop() override; void lostFocus(); void adjustUiAfterProjectLoad(); + void updateSnapLabel(); + signals: void playTriggered(); void resized(); private: - virtual void keyPressEvent( QKeyEvent * ke ); - virtual void keyReleaseEvent( QKeyEvent * ke ); + void keyPressEvent( QKeyEvent * ke ) override; + void keyReleaseEvent( QKeyEvent * ke ) override; QAction* m_addBBTrackAction; QAction* m_addSampleTrackAction; QAction* m_addAutomationTrackAction; + QAction* m_setProportionalSnapAction; ActionGroup * m_editModeGroup; QAction* m_drawModeAction; @@ -188,6 +208,8 @@ protected slots: QAction* m_crtlAction; ComboBox * m_zoomingComboBox; + ComboBox * m_snappingComboBox; + QLabel* m_snapSizeLabel; }; #endif diff --git a/include/StepRecorderWidget.h b/include/StepRecorderWidget.h index 0e45121698b..67f2a4b6547 100644 --- a/include/StepRecorderWidget.h +++ b/include/StepRecorderWidget.h @@ -36,16 +36,18 @@ class StepRecorderWidget : public QWidget public: StepRecorderWidget( QWidget * parent, - const int ppt, + const int ppb, const int marginTop, const int marginBottom, const int marginLeft, const int marginRight); //API used by PianoRoll - void setPixelsPerTact(int ppt); + void setPixelsPerBar(int ppb); void setCurrentPosition(MidiTime currentPosition); + void setMargins(const QMargins &qm); void setBottomMargin(const int marginBottom); + QMargins margins(); //API used by StepRecorder void setStepsLength(MidiTime stepsLength); @@ -55,7 +57,7 @@ class StepRecorderWidget : public QWidget void showHint(); private: - virtual void paintEvent(QPaintEvent * pe); + void paintEvent(QPaintEvent * pe) override; int xCoordOfTick(int tick); @@ -68,7 +70,7 @@ class StepRecorderWidget : public QWidget MidiTime m_curStepStartPos; MidiTime m_curStepEndPos; - int m_ppt; // pixels per tact + int m_ppb; // pixels per bar MidiTime m_currentPosition; // current position showed by on PianoRoll QColor m_colorLineStart; diff --git a/include/SubWindow.h b/include/SubWindow.h index f6247d06169..148cf2c9997 100644 --- a/include/SubWindow.h +++ b/include/SubWindow.h @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -68,10 +67,10 @@ class LMMS_EXPORT SubWindow : public QMdiSubWindow protected: // hook the QWidget move/resize events to update the tracked geometry - virtual void moveEvent( QMoveEvent * event ); - virtual void resizeEvent( QResizeEvent * event ); - virtual void paintEvent( QPaintEvent * pe ); - virtual void changeEvent( QEvent * event ); + void moveEvent( QMoveEvent * event ) override; + void resizeEvent( QResizeEvent * event ) override; + void paintEvent( QPaintEvent * pe ) override; + void changeEvent( QEvent * event ) override; signals: void focusLost(); diff --git a/include/TabWidget.h b/include/TabWidget.h index 11e4da40a02..0cf15155b99 100644 --- a/include/TabWidget.h +++ b/include/TabWidget.h @@ -72,12 +72,13 @@ class TabWidget : public QWidget void setTabBorder( const QColor & c ); protected: - virtual bool event( QEvent * event ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void paintEvent( QPaintEvent * _pe ); - virtual void resizeEvent( QResizeEvent * _re ); - virtual void wheelEvent( QWheelEvent * _we ); - virtual QSize minimumSizeHint() const; + bool event( QEvent * event ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void paintEvent( QPaintEvent * _pe ) override; + void resizeEvent( QResizeEvent * _re ) override; + void wheelEvent( QWheelEvent * _we ) override; + QSize minimumSizeHint() const override; + QSize sizeHint() const override; private: struct widgetDesc diff --git a/include/TemplatesMenu.h b/include/TemplatesMenu.h new file mode 100644 index 00000000000..049f1f47eeb --- /dev/null +++ b/include/TemplatesMenu.h @@ -0,0 +1,21 @@ +#ifndef TEMPLATESMENU_H +#define TEMPLATESMENU_H + +#include +#include + +class TemplatesMenu : public QMenu +{ + Q_OBJECT +public: + TemplatesMenu(QWidget *parent = nullptr); + virtual ~TemplatesMenu() = default; + +private slots: + static void createNewProjectFromTemplate(QAction * _action); + void fillTemplatesMenu(); + void addTemplatesFromDir( const QDir& dir ); + +}; + +#endif // TEMPLATESMENU_H diff --git a/include/TempoSyncKnob.h b/include/TempoSyncKnob.h index 034e2b8f4b7..416abe1fc0e 100644 --- a/include/TempoSyncKnob.h +++ b/include/TempoSyncKnob.h @@ -52,7 +52,7 @@ class LMMS_EXPORT TempoSyncKnob : public Knob return castModel(); } - virtual void modelChanged(); + void modelChanged() override; signals: @@ -61,7 +61,7 @@ class LMMS_EXPORT TempoSyncKnob : public Knob protected: - virtual void contextMenuEvent( QContextMenuEvent * _me ); + void contextMenuEvent( QContextMenuEvent * _me ) override; protected slots: diff --git a/include/TempoSyncKnobModel.h b/include/TempoSyncKnobModel.h index 9aaf48fea8b..b9512aa1a93 100644 --- a/include/TempoSyncKnobModel.h +++ b/include/TempoSyncKnobModel.h @@ -52,7 +52,7 @@ class LMMS_EXPORT TempoSyncKnobModel : public FloatModel const float _max, const float _step, const float _scale, Model * _parent, const QString & _display_name = QString() ); - virtual ~TempoSyncKnobModel() override; + ~TempoSyncKnobModel() override; void saveSettings( QDomDocument & _doc, QDomElement & _this, const QString& name ) override; void loadSettings( const QDomElement & _this, const QString& name ) override; diff --git a/include/TextFloat.h b/include/TextFloat.h index ed10516b552..8f940c591c7 100644 --- a/include/TextFloat.h +++ b/include/TextFloat.h @@ -66,8 +66,8 @@ class LMMS_EXPORT TextFloat : public QWidget protected: - virtual void paintEvent( QPaintEvent * _me ); - virtual void mousePressEvent( QMouseEvent * _me ); + void paintEvent( QPaintEvent * _me ) override; + void mousePressEvent( QMouseEvent * _me ) override; private: diff --git a/include/TimeDisplayWidget.h b/include/TimeDisplayWidget.h index 175f159c943..e7e5cb21010 100644 --- a/include/TimeDisplayWidget.h +++ b/include/TimeDisplayWidget.h @@ -41,7 +41,7 @@ class TimeDisplayWidget : public QWidget protected: - virtual void mousePressEvent( QMouseEvent* mouseEvent ); + void mousePressEvent( QMouseEvent* mouseEvent ) override; private slots: diff --git a/include/TimeLineWidget.h b/include/TimeLineWidget.h index 7629694caa8..8a9dc5044ea 100644 --- a/include/TimeLineWidget.h +++ b/include/TimeLineWidget.h @@ -72,15 +72,15 @@ class TimeLineWidget : public QWidget, public JournallingObject } ; - TimeLineWidget(int xoff, int yoff, float ppt, Song::PlayPos & pos, + TimeLineWidget(int xoff, int yoff, float ppb, Song::PlayPos & pos, const MidiTime & begin, Song::PlayModes mode, QWidget * parent); virtual ~TimeLineWidget(); inline QColor const & getBarLineColor() const { return m_barLineColor; } - inline void setBarLineColor(QColor const & tactLineColor) { m_barLineColor = tactLineColor; } + inline void setBarLineColor(QColor const & barLineColor) { m_barLineColor = barLineColor; } inline QColor const & getBarNumberColor() const { return m_barNumberColor; } - inline void setBarNumberColor(QColor const & tactNumberColor) { m_barNumberColor = tactNumberColor; } + inline void setBarNumberColor(QColor const & barNumberColor) { m_barNumberColor = barNumberColor; } inline QColor const & getInactiveLoopColor() const { return m_inactiveLoopColor; } inline void setInactiveLoopColor(QColor const & inactiveLoopColor) { m_inactiveLoopColor = inactiveLoopColor; } @@ -135,27 +135,29 @@ class TimeLineWidget : public QWidget, public JournallingObject m_loopPos[0] : m_loopPos[1]; } - inline void savePos( const MidiTime & _pos ) + inline void savePos( const MidiTime & pos ) { - m_savedPos = _pos; + m_savedPos = pos; } inline const MidiTime & savedPos() const { return m_savedPos; } - inline void setPixelsPerTact( float _ppt ) + inline void setPixelsPerBar( float ppb ) { - m_ppt = _ppt; + m_ppb = ppb; update(); } + void setXOffset(const int x); + void addToolButtons(QToolBar* _tool_bar ); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + inline QString nodeName() const override { return "timeline"; } @@ -163,7 +165,7 @@ class TimeLineWidget : public QWidget, public JournallingObject inline int markerX( const MidiTime & _t ) const { return m_xOffset + static_cast( ( _t - m_begin ) * - m_ppt / MidiTime::ticksPerTact() ); + m_ppb / MidiTime::ticksPerBar() ); } signals: @@ -184,10 +186,10 @@ public slots: protected: - virtual void paintEvent( QPaintEvent * _pe ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseMoveEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); + void paintEvent( QPaintEvent * _pe ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseMoveEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; private: @@ -214,7 +216,7 @@ public slots: int m_xOffset; int m_posMarkerX; - float m_ppt; + float m_ppb; Song::PlayPos & m_pos; const MidiTime & m_begin; const Song::PlayModes m_mode; @@ -243,6 +245,7 @@ public slots: void positionChanged( const MidiTime & _t ); void loopPointStateLoaded( int _n ); void positionMarkerMoved(); + void loadBehaviourAtStop( int _n ); } ; diff --git a/include/Track.h b/include/Track.h index 1267d2ef742..9362a838019 100644 --- a/include/Track.h +++ b/include/Track.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include @@ -40,6 +40,7 @@ #include "AutomatableModel.h" #include "ModelView.h" #include "DataFile.h" +#include "FadeButton.h" class QMenu; @@ -72,8 +73,10 @@ const int DEFAULT_TRACK_HEIGHT = 32; const int TCO_BORDER_WIDTH = 2; +char const *const FILENAME_FILTER = "[\\0000-\x1f\"*/:<>?\\\\|\x7f]"; -class TrackContentObject : public Model, public JournallingObject + +class LMMS_EXPORT TrackContentObject : public Model, public JournallingObject { Q_OBJECT MM_OPERATORS @@ -99,7 +102,7 @@ class TrackContentObject : public Model, public JournallingObject emit dataChanged(); } - virtual QString displayName() const + QString displayName() const override { return name(); } @@ -204,6 +207,9 @@ class TrackContentObjectView : public selectableObject, public ModelView Q_PROPERTY( QColor textShadowColor READ textShadowColor WRITE setTextShadowColor ) Q_PROPERTY( QColor BBPatternBackground READ BBPatternBackground WRITE setBBPatternBackground ) Q_PROPERTY( bool gradient READ gradient WRITE setGradient ) + // We have to use a QSize here because using QPoint isn't supported. + // width -> x, height -> y + Q_PROPERTY( QSize mouseHotspotHand WRITE setMouseHotspotHand ) public: TrackContentObjectView( TrackContentObject * tco, TrackView * tv ); @@ -215,6 +221,12 @@ class TrackContentObjectView : public selectableObject, public ModelView { return m_tco; } + + inline TrackView * getTrackView() + { + return m_trackView; + } + // qproperty access func QColor mutedColor() const; QColor mutedBackgroundColor() const; @@ -232,41 +244,62 @@ class TrackContentObjectView : public selectableObject, public ModelView void setTextShadowColor( const QColor & c ); void setBBPatternBackground( const QColor & c ); void setGradient( const bool & b ); + void setMouseHotspotHand(const QSize & s); // access needsUpdate member variable bool needsUpdate(); void setNeedsUpdate( bool b ); - + + // Method to get a QVector of TCOs to be affected by a context menu action + QVector getClickedTCOs(); + + // Methods to remove, copy, cut, paste and mute a QVector of TCO views + void copy( QVector tcovs ); + void cut( QVector tcovs ); + void paste(); + // remove and toggleMute are static because they don't depend + // being called from a particular TCO view, but can be called anywhere as long + // as a valid TCO view list is given, while copy/cut require an instance for + // some metadata to be written to the clipboard. + static void remove( QVector tcovs ); + static void toggleMute( QVector tcovs ); + public slots: virtual bool close(); void cut(); void remove(); - virtual void update(); + void update() override; protected: + enum ContextMenuAction + { + Remove, + Cut, + Copy, + Paste, + Mute + }; + virtual void constructContextMenu( QMenu * ) { } - virtual void contextMenuEvent( QContextMenuEvent * cme ); - virtual void dragEnterEvent( QDragEnterEvent * dee ); - virtual void dropEvent( QDropEvent * de ); - virtual void leaveEvent( QEvent * e ); - virtual void mousePressEvent( QMouseEvent * me ); - virtual void mouseMoveEvent( QMouseEvent * me ); - virtual void mouseReleaseEvent( QMouseEvent * me ); - virtual void resizeEvent( QResizeEvent * re ) + void contextMenuEvent( QContextMenuEvent * cme ) override; + void contextMenuAction( ContextMenuAction action ); + void dragEnterEvent( QDragEnterEvent * dee ) override; + void dropEvent( QDropEvent * de ) override; + void leaveEvent( QEvent * e ) override; + void mousePressEvent( QMouseEvent * me ) override; + void mouseMoveEvent( QMouseEvent * me ) override; + void mouseReleaseEvent( QMouseEvent * me ) override; + void resizeEvent( QResizeEvent * re ) override { m_needsUpdate = true; selectableObject::resizeEvent( re ); } - float pixelsPerTact(); + float pixelsPerBar(); - inline TrackView * getTrackView() - { - return m_trackView; - } DataFile createTCODataFiles(const QVector & tcos) const; @@ -297,6 +330,9 @@ protected slots: Actions m_action; QPoint m_initialMousePos; QPoint m_initialMouseGlobalPos; + MidiTime m_initialTCOPos; + MidiTime m_initialTCOEnd; + QVector m_initialOffsets; TextFloat * m_hint; @@ -309,16 +345,21 @@ protected slots: QColor m_textShadowColor; QColor m_BBPatternBackground; bool m_gradient; + QSize m_mouseHotspotHand; // QSize must be used because QPoint isn't supported by property system + bool m_cursorSetYet; - bool m_needsUpdate; - inline void setInitialMousePos( QPoint pos ) + bool m_needsUpdate; + inline void setInitialPos( QPoint pos ) { m_initialMousePos = pos; m_initialMouseGlobalPos = mapToGlobal( pos ); + m_initialTCOPos = m_tco->startPosition(); + m_initialTCOEnd = m_initialTCOPos + m_tco->length(); } + void setInitialOffsets(); bool mouseMovedDistance( QMouseEvent * me, int distance ); - + MidiTime draggedTCOPos( QMouseEvent * me ); } ; @@ -353,7 +394,9 @@ class TrackContentWidget : public QWidget, public JournallingObject } bool canPasteSelection( MidiTime tcoPos, const QDropEvent *de ); + bool canPasteSelection( MidiTime tcoPos, const QMimeData *md, bool allowSameBar = false ); bool pasteSelection( MidiTime tcoPos, QDropEvent * de ); + bool pasteSelection( MidiTime tcoPos, const QMimeData * md, bool skipSafetyCheck = false ); MidiTime endPosition( const MidiTime & posStart ); @@ -374,24 +417,31 @@ public slots: void changePosition( const MidiTime & newPos = MidiTime( -1 ) ); protected: - virtual void dragEnterEvent( QDragEnterEvent * dee ); - virtual void dropEvent( QDropEvent * de ); - virtual void mousePressEvent( QMouseEvent * me ); - virtual void paintEvent( QPaintEvent * pe ); - virtual void resizeEvent( QResizeEvent * re ); + enum ContextMenuAction + { + Paste + }; + + void contextMenuEvent( QContextMenuEvent * cme ) override; + void contextMenuAction( QContextMenuEvent * cme, ContextMenuAction action ); + void dragEnterEvent( QDragEnterEvent * dee ) override; + void dropEvent( QDropEvent * de ) override; + void mousePressEvent( QMouseEvent * me ) override; + void paintEvent( QPaintEvent * pe ) override; + void resizeEvent( QResizeEvent * re ) override; - virtual QString nodeName() const + QString nodeName() const override { return "trackcontentwidget"; } - virtual void saveSettings( QDomDocument& doc, QDomElement& element ) + void saveSettings( QDomDocument& doc, QDomElement& element ) override { Q_UNUSED(doc) Q_UNUSED(element) } - virtual void loadSettings( const QDomElement& element ) + void loadSettings( const QDomElement& element ) override { Q_UNUSED(element) } @@ -428,8 +478,8 @@ class TrackOperationsWidget : public QWidget protected: - virtual void mousePressEvent( QMouseEvent * me ); - virtual void paintEvent( QPaintEvent * pe ); + void mousePressEvent( QMouseEvent * me ) override; + void paintEvent( QPaintEvent * pe ) override; private slots: @@ -442,8 +492,6 @@ private slots: void clearTrack(); private: - static QPixmap * s_grip; - TrackView * m_trackView; QPushButton * m_trackOps; @@ -511,8 +559,8 @@ class LMMS_EXPORT Track : public Model, public JournallingObject virtual void loadTrackSpecificSettings( const QDomElement & element ) = 0; - virtual void saveSettings( QDomDocument & doc, QDomElement & element ); - virtual void loadSettings( const QDomElement & element ); + void saveSettings( QDomDocument & doc, QDomElement & element ) override; + void loadSettings( const QDomElement & element ) override; void setSimpleSerializing() { @@ -540,10 +588,10 @@ class LMMS_EXPORT Track : public Model, public JournallingObject void createTCOsForBB( int bb ); - void insertTact( const MidiTime & pos ); - void removeTact( const MidiTime & pos ); + void insertBar( const MidiTime & pos ); + void removeBar( const MidiTime & pos ); - tact_t length() const; + bar_t length() const; inline TrackContainer* trackContainer() const @@ -557,20 +605,20 @@ class LMMS_EXPORT Track : public Model, public JournallingObject return m_name; } - virtual QString displayName() const + QString displayName() const override { return name(); } using Model::dataChanged; - inline int getHeight() + inline int getHeight() { return m_height >= MINIMAL_TRACK_HEIGHT - ? m_height + ? m_height : DEFAULT_TRACK_HEIGHT; } - inline void setHeight( int height ) + inline void setHeight( int height ) { m_height = height; } @@ -685,32 +733,32 @@ public slots: protected: - virtual void modelChanged(); + void modelChanged() override; - virtual void saveSettings( QDomDocument& doc, QDomElement& element ) + void saveSettings( QDomDocument& doc, QDomElement& element ) override { Q_UNUSED(doc) Q_UNUSED(element) } - virtual void loadSettings( const QDomElement& element ) + void loadSettings( const QDomElement& element ) override { Q_UNUSED(element) } - virtual QString nodeName() const + QString nodeName() const override { return "trackview"; } - virtual void dragEnterEvent( QDragEnterEvent * dee ); - virtual void dropEvent( QDropEvent * de ); - virtual void mousePressEvent( QMouseEvent * me ); - virtual void mouseMoveEvent( QMouseEvent * me ); - virtual void mouseReleaseEvent( QMouseEvent * me ); - virtual void paintEvent( QPaintEvent * pe ); - virtual void resizeEvent( QResizeEvent * re ); + void dragEnterEvent( QDragEnterEvent * dee ) override; + void dropEvent( QDropEvent * de ) override; + void mousePressEvent( QMouseEvent * me ) override; + void mouseMoveEvent( QMouseEvent * me ) override; + void mouseReleaseEvent( QMouseEvent * me ) override; + void paintEvent( QPaintEvent * pe ) override; + void resizeEvent( QResizeEvent * re ) override; private: @@ -730,12 +778,19 @@ public slots: Actions m_action; + virtual FadeButton * getActivityIndicator() + { + return nullptr; + } + + void setIndicatorMute(FadeButton* indicator, bool muted); friend class TrackLabelButton; private slots: void createTCOView( TrackContentObject * tco ); + void muteChanged(); } ; diff --git a/include/TrackContainer.h b/include/TrackContainer.h index 1caca922e23..e89f0b20fab 100644 --- a/include/TrackContainer.h +++ b/include/TrackContainer.h @@ -51,9 +51,9 @@ class LMMS_EXPORT TrackContainer : public Model, public JournallingObject TrackContainer(); virtual ~TrackContainer(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; - virtual void loadSettings( const QDomElement & _this ); + void loadSettings( const QDomElement & _this ) override; virtual AutomationPattern * tempoAutomationPattern() @@ -97,6 +97,8 @@ class LMMS_EXPORT TrackContainer : public Model, public JournallingObject signals: void trackAdded( Track * _track ); + void trackRemoved(); + void trackRenamed(); protected: static AutomatedValueMap automatedValuesFromTracks(const TrackList &tracks, MidiTime timeStart, int tcoNum = -1); @@ -124,7 +126,7 @@ class DummyTrackContainer : public TrackContainer { } - virtual QString nodeName() const + QString nodeName() const override { return "DummyTrackContainer"; } diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h index 67575583b51..4597fe17240 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -49,30 +49,30 @@ class TrackContainerView : public QWidget, public ModelView, TrackContainerView( TrackContainer* tc ); virtual ~TrackContainerView(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; + void loadSettings( const QDomElement & _this ) override; QScrollArea * contentWidget() { - return( m_scrollArea ); + return m_scrollArea; } inline const MidiTime & currentPosition() const { - return( m_currentPosition ); + return m_currentPosition; } virtual bool fixedTCOs() const { - return( false ); + return false; } - inline float pixelsPerTact() const + inline float pixelsPerBar() const { - return( m_ppt ); + return m_ppb; } - void setPixelsPerTact( int _ppt ); + void setPixelsPerBar( int ppb ); const TrackView * trackViewAt( const int _y ) const; @@ -80,12 +80,12 @@ class TrackContainerView : public QWidget, public ModelView, inline bool rubberBandActive() const { - return( m_rubberBand->isEnabled() && m_rubberBand->isVisible() ); + return m_rubberBand->isEnabled() && m_rubberBand->isVisible(); } inline QVector selectedObjects() { - return( m_rubberBand->selectedObjects() ); + return m_rubberBand->selectedObjects(); } @@ -116,9 +116,9 @@ class TrackContainerView : public QWidget, public ModelView, void clearAllTracks(); - virtual QString nodeName() const + QString nodeName() const override { - return( "trackcontainerview" ); + return "trackcontainerview"; } @@ -129,27 +129,19 @@ public slots: TrackView * createTrackView( Track * _t ); void deleteTrackView( TrackView * _tv ); - virtual void dropEvent( QDropEvent * _de ); - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - /// - /// \brief selectRegionFromPixels - /// \param x - /// \param y - /// Use the rubber band to select TCO from all tracks using x, y pixels - void selectRegionFromPixels(int xStart, int xEnd); + void dropEvent( QDropEvent * _de ) override; + void dragEnterEvent( QDragEnterEvent * _dee ) override; /// /// \brief stopRubberBand /// Removes the rubber band from display when finished with. void stopRubberBand(); + protected: - static const int DEFAULT_PIXELS_PER_TACT = 16; + static const int DEFAULT_PIXELS_PER_BAR = 16; - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseMoveEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void resizeEvent( QResizeEvent * ); + void resizeEvent( QResizeEvent * ) override; MidiTime m_currentPosition; @@ -168,7 +160,7 @@ public slots: virtual ~scrollArea(); protected: - virtual void wheelEvent( QWheelEvent * _we ); + void wheelEvent( QWheelEvent * _we ) override; private: TrackContainerView* m_trackContainerView; @@ -183,14 +175,15 @@ public slots: scrollArea * m_scrollArea; QVBoxLayout * m_scrollLayout; - float m_ppt; + float m_ppb; RubberBand * m_rubberBand; - QPoint m_origin; + signals: void positionChanged( const MidiTime & _pos ); + void movedTrackView(); } ; @@ -202,7 +195,7 @@ class InstrumentLoaderThread : public QThread InstrumentLoaderThread( QObject *parent = 0, InstrumentTrack *it = 0, QString name = "" ); - void run(); + void run() override; private: InstrumentTrack *m_it; diff --git a/include/TrackLabelButton.h b/include/TrackLabelButton.h index f1059bdbf4f..7d9726febde 100644 --- a/include/TrackLabelButton.h +++ b/include/TrackLabelButton.h @@ -49,13 +49,13 @@ public slots: protected: - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void dropEvent( QDropEvent * _de ); - virtual void mousePressEvent( QMouseEvent * _me ); - virtual void mouseDoubleClickEvent( QMouseEvent * _me ); - virtual void mouseReleaseEvent( QMouseEvent * _me ); - virtual void paintEvent( QPaintEvent * _pe ); - virtual void resizeEvent( QResizeEvent * _re ); + void dragEnterEvent( QDragEnterEvent * _dee ) override; + void dropEvent( QDropEvent * _de ) override; + void mousePressEvent( QMouseEvent * _me ) override; + void mouseDoubleClickEvent( QMouseEvent * _me ) override; + void mouseReleaseEvent( QMouseEvent * _me ) override; + void paintEvent( QPaintEvent * _pe ) override; + void resizeEvent( QResizeEvent * _re ) override; private: diff --git a/include/TrackRenameLineEdit.h b/include/TrackRenameLineEdit.h index 6883b9b0508..e681a2d212c 100644 --- a/include/TrackRenameLineEdit.h +++ b/include/TrackRenameLineEdit.h @@ -37,7 +37,7 @@ class TrackRenameLineEdit : public QLineEdit void show(); protected: - virtual void keyPressEvent( QKeyEvent * ke ); + void keyPressEvent( QKeyEvent * ke ) override; private: QString m_oldName; diff --git a/include/VstSyncController.h b/include/VstSyncController.h index 33f2ee036b3..a5dfb03c874 100644 --- a/include/VstSyncController.h +++ b/include/VstSyncController.h @@ -26,9 +26,7 @@ #ifndef VST_SYNC_CONTROLLER_H #define VST_SYNC_CONTROLLER_H -#include -#include - +#include "IPCHelper.h" #include "VstSyncData.h" @@ -68,6 +66,7 @@ class VstSyncController : public QObject void update(); + inline key_t sharedMemoryKey() const { return m_shm.key(); } private slots: void updateSampleRate(); @@ -75,11 +74,7 @@ private slots: private: VstSyncData* m_syncData; - - int m_shmID; - - QSharedMemory m_shm; - + SharedMemory m_shm; }; #endif diff --git a/include/VstSyncData.h b/include/VstSyncData.h index 6c2f1bbd2a6..c9fca056aba 100644 --- a/include/VstSyncData.h +++ b/include/VstSyncData.h @@ -34,8 +34,6 @@ //#define VST_SNC_LATENCY // define file for ftok as shared memory shmget key -#define VST_SNC_SHM_KEY_FILE "/dev/null" -//#define VST_SNC_SHM_RND_KEY 3561653564469 diff --git a/include/aeffectx.h b/include/aeffectx.h index 133d925acd8..b7a78dfad2b 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -97,6 +97,8 @@ const int effClose = 1; // currently unused const int effSetProgram = 2; // currently unused const int effGetProgram = 3; // currently unused const int effGetProgramName = 5; // currently unused +const int effGetParamLabel = 6; +const int effGetParamDisplay = 7; const int effGetParamName = 8; // currently unused const int effSetSampleRate = 10; const int effSetBlockSize = 11; diff --git a/include/fft_helpers.h b/include/fft_helpers.h index 23450d2ca5a..88183fb1969 100644 --- a/include/fft_helpers.h +++ b/include/fft_helpers.h @@ -2,6 +2,7 @@ * fft_helpers.h - some functions around FFT analysis * * Copyright (c) 2008-2012 Tobias Doerffel + * Copyright (c) 2019 Martin Pavelek * * This file is part of LMMS - https://lmms.io * @@ -28,57 +29,78 @@ #include "lmms_export.h" +#include #include -const int FFT_BUFFER_SIZE = 2048; +// NOTE: FFT_BUFFER_SIZE should be considered deprecated! +// It is used by Eq plugin and some older code here, but this should be a user +// switchable parameter, not a constant. Use a value from FFT_BLOCK_SIZES +const unsigned int FFT_BUFFER_SIZE = 2048; -enum WINDOWS +// Allowed FFT block sizes. Ranging from barely useful to barely acceptable +// because of performance and latency reasons. +const std::vector FFT_BLOCK_SIZES = {256, 512, 1024, 2048, 4096, 8192, 16384}; + +// List of FFT window functions supported by precomputeWindow() +enum FFT_WINDOWS { - KAISER=1, - RECTANGLE, - HANNING, - HAMMING + RECTANGULAR = 0, + BLACKMAN_HARRIS, + HAMMING, + HANNING }; -/* returns biggest value from abs_spectrum[spec_size] array + +/** Returns biggest value from abs_spectrum[spec_size] array. * - * returns -1 on error + * @return -1 on error, 0 on success */ -float LMMS_EXPORT maximum( float * _abs_spectrum, unsigned int _spec_size ); +float LMMS_EXPORT maximum(const float *abs_spectrum, unsigned int spec_size); +float LMMS_EXPORT maximum(const std::vector &abs_spectrum); -/* apply hanning or hamming window to channel + +/** Normalize the abs_spectrum array of absolute values to a 0..1 range + * based on supplied energy and stores it in the norm_spectrum array. * - * returns -1 on error + * @return -1 on error */ -int LMMS_EXPORT hanming( float * _timebuffer, int _length, WINDOWS _type ); +int LMMS_EXPORT normalize(const float *abs_spectrum, float *norm_spectrum, unsigned int bin_count, unsigned int block_size); +int LMMS_EXPORT normalize(const std::vector &abs_spectrum, std::vector &norm_spectrum, unsigned int block_size); + -/* compute absolute values of complex_buffer, save to absspec_buffer - * take care that - compl_len is not bigger than complex_buffer! - * - absspec buffer is big enough! +/** Check if the spectrum contains any non-zero value. * - * returns 0 on success, else -1 + * @return 1 if spectrum contains any non-zero value + * @return 0 otherwise */ -int LMMS_EXPORT absspec( fftwf_complex * _complex_buffer, float * _absspec_buffer, - int _compl_length ); +int LMMS_EXPORT notEmpty(const std::vector &spectrum); -/* build fewer subbands from many absolute spectrum values - * take care that - compressedbands[] array num_new elements long - * - num_old > num_new + +/** Precompute a window function for later real-time use. + * Set normalized to false if you do not want to apply amplitude correction. * - * returns 0 on success, else -1 + * @return -1 on error */ -int LMMS_EXPORT compressbands( float * _absspec_buffer, float * _compressedband, - int _num_old, int _num_new, int _bottom, int _top ); +int LMMS_EXPORT precomputeWindow(float *window, unsigned int length, FFT_WINDOWS type, bool normalized = true); + +/** Compute absolute values of complex_buffer, save to absspec_buffer. + * Take care that - compl_len is not bigger than complex_buffer! + * - absspec buffer is big enough! + * + * @return 0 on success, else -1 + */ +int LMMS_EXPORT absspec(const fftwf_complex *complex_buffer, float *absspec_buffer, + unsigned int compl_length); -int LMMS_EXPORT calc13octaveband31( float * _absspec_buffer, float * _subbands, - int _num_spec, float _max_frequency ); -/* compute power of finite time sequence - * take care num_values is length of timesignal[] +/** Build fewer subbands from many absolute spectrum values. + * Take care that - compressedbands[] array num_new elements long + * - num_old > num_new * - * returns power on success, else -1 + * @return 0 on success, else -1 */ -float LMMS_EXPORT signalpower(float *timesignal, int num_values); +int LMMS_EXPORT compressbands(const float * _absspec_buffer, float * _compressedband, + int _num_old, int _num_new, int _bottom, int _top); #endif diff --git a/include/lmms_basics.h b/include/lmms_basics.h index cca04e97d8f..77a24649820 100644 --- a/include/lmms_basics.h +++ b/include/lmms_basics.h @@ -35,7 +35,7 @@ #endif -typedef int32_t tact_t; +typedef int32_t bar_t; typedef int32_t tick_t; typedef uint8_t volume_t; typedef int8_t panning_t; @@ -55,9 +55,6 @@ typedef uint16_t fx_ch_t; // FX-channel (0 to MAX_EFFECT_CHANNEL) typedef uint32_t jo_id_t; // (unique) ID of a journalling object -// use for improved branch prediction -#define likely(x) Q_LIKELY(x) -#define unlikely(x) Q_UNLIKELY(x) // windows headers define "min" and "max" macros, breaking the methods bwloe #undef min diff --git a/include/lmms_constants.h b/include/lmms_constants.h index befa789dd5c..ae6d3d277b1 100644 --- a/include/lmms_constants.h +++ b/include/lmms_constants.h @@ -49,4 +49,47 @@ const float F_PI_SQR = (float) LD_PI_SQR; const float F_E = (float) LD_E; const float F_E_R = (float) LD_E_R; +// Frequency ranges (in Hz). +// Arbitrary low limit for logarithmic frequency scale; >1 Hz. +const int LOWEST_LOG_FREQ = 10; + +// Full range is defined by LOWEST_LOG_FREQ and current sample rate. +enum FREQUENCY_RANGES +{ + FRANGE_FULL = 0, + FRANGE_AUDIBLE, + FRANGE_BASS, + FRANGE_MIDS, + FRANGE_HIGH +}; + +const int FRANGE_AUDIBLE_START = 20; +const int FRANGE_AUDIBLE_END = 20000; +const int FRANGE_BASS_START = 20; +const int FRANGE_BASS_END = 300; +const int FRANGE_MIDS_START = 200; +const int FRANGE_MIDS_END = 5000; +const int FRANGE_HIGH_START = 4000; +const int FRANGE_HIGH_END = 20000; + +// Amplitude ranges (in dBFS). +// Reference: full scale sine wave (-1.0 to 1.0) is 0 dB. +// Doubling or halving the amplitude produces 3 dB difference. +enum AMPLITUDE_RANGES +{ + ARANGE_EXTENDED = 0, + ARANGE_AUDIBLE, + ARANGE_LOUD, + ARANGE_SILENT +}; + +const int ARANGE_EXTENDED_START = -80; +const int ARANGE_EXTENDED_END = 20; +const int ARANGE_AUDIBLE_START = -50; +const int ARANGE_AUDIBLE_END = 0; +const int ARANGE_LOUD_START = -30; +const int ARANGE_LOUD_END = 0; +const int ARANGE_SILENT_START = -60; +const int ARANGE_SILENT_END = -10; + #endif diff --git a/include/panning.h b/include/panning.h index 8668ddf88a8..c043adf5c65 100644 --- a/include/panning.h +++ b/include/panning.h @@ -27,9 +27,9 @@ #define PANNING_H #include "lmms_basics.h" -#include "volume.h" #include "panning_constants.h" #include "Midi.h" +#include "volume.h" inline stereoVolumeVector panningToVolumeVector( panning_t _p, float _scale = 1.0f ) diff --git a/include/stdshims.h b/include/stdshims.h index 85c4f457aab..c12254e1506 100644 --- a/include/stdshims.h +++ b/include/stdshims.h @@ -5,11 +5,12 @@ #define STDSHIMS_H #include +#include #include #if (__cplusplus >= 201402L || _MSC_VER) #ifndef _MSC_VER -#warning "This file should now be removed! The functions it provides are part of the C++14 standard." +#warning "This part of this file should now be removed! The functions it provides are part of the C++14 standard." #endif using std::make_unique; @@ -21,6 +22,32 @@ std::unique_ptr make_unique(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...)); } + +//! Overload for the case a deleter should be specified +template +std::unique_ptr make_unique(Args&&... args) +{ + return std::unique_ptr(new T(std::forward(args)...)); +} +#endif + +#if (__cplusplus >= 201703L || _MSC_VER >= 1914) +#ifndef _MSC_VER +#warning "This part of this file should now be removed! The functions it provides are part of the C++17 standard." +#endif +using std::as_const; + +#else + +/// Shim for http://en.cppreference.com/w/cpp/utility/as_const +template +constexpr typename std::add_const::type& as_const(T& t) noexcept +{ + return t; +} + +template +void as_const(const T&&) = delete; #endif #endif // include guard diff --git a/include/versioninfo.h b/include/versioninfo.h index b34936d5742..a5d3d64c646 100644 --- a/include/versioninfo.h +++ b/include/versioninfo.h @@ -32,6 +32,10 @@ #define PLATFORM "OpenBSD" #endif +#ifdef LMMS_BUILD_FREEBSD +#define PLATFORM "FreeBSD" +#endif + #ifdef LMMS_BUILD_WIN32 #define PLATFORM "win32" #endif diff --git a/include/volume.h b/include/volume.h index f0f7708adf3..9172395d625 100644 --- a/include/volume.h +++ b/include/volume.h @@ -26,10 +26,7 @@ #ifndef VOLUME_H #define VOLUME_H -#include "lmmsconfig.h" - #include "lmms_basics.h" -#include "Midi.h" const volume_t MinVolume = 0; const volume_t MaxVolume = 200; diff --git a/plugins/Amplifier/Amplifier.cpp b/plugins/Amplifier/Amplifier.cpp index d90ea55b329..cc2a63304ff 100644 --- a/plugins/Amplifier/Amplifier.cpp +++ b/plugins/Amplifier/Amplifier.cpp @@ -83,7 +83,6 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) for( fpp_t f = 0; f < frames; ++f ) { // qDebug( "offset %d, value %f", f, m_ampControls.m_volumeModel.value( f ) ); - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; sample_t s[2] = { buf[f][0], buf[f][1] }; @@ -123,6 +122,7 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) buf[f][0] = d * buf[f][0] + w * s[0]; buf[f][1] = d * buf[f][1] + w * s[1]; + outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; } checkGate( outSum / frames ); diff --git a/plugins/AudioMixMaster/AudioMixMaster.cpp b/plugins/AudioMixMaster/AudioMixMaster.cpp new file mode 100644 index 00000000000..138369cad68 --- /dev/null +++ b/plugins/AudioMixMaster/AudioMixMaster.cpp @@ -0,0 +1,560 @@ +/* + * AudioMixMaster.cpp - A sample scripting plugin + * + * Copyright (c) 2020 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "AudioMixMaster.h" + +#include "embed.h" +#include "plugin_export.h" + +#include "ConfigManager.h" +#include "Effect.h" +#include "EffectChain.h" +#include "Engine.h" +#include "FxMixer.h" +#include "ImportFilter.h" +#include "InstrumentTrack.h" +#include "RenderManager.h" +#include "SampleTrack.h" +#include "Song.h" +#include "stdshims.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT audiomixmaster_plugin_descriptor = +{ + STRINGIFY(PLUGIN_NAME), + "AudioMixMaster", + QT_TRANSLATE_NOOP("pluginBrowser", "A sample scripting plugin"), + "Hyunjin Song ", + 0x0100, + Plugin::Scripting, + new PluginPixmapLoader("logo"), + NULL, + NULL +} ; + +} + + + +AudioMixMaster::AudioMixMaster(Model* parent, const Descriptor::SubPluginFeatures::Key* key) : + ScriptPlugin(&audiomixmaster_plugin_descriptor, parent, key) +{ +} + + + +AudioMixMaster::~AudioMixMaster() +{ +} + + + +struct ExtraChannelInfo +{ + bool isRoot; + bool isSource; + bool isMuted; + bool isSolo; + int inputIndex; + bool inputIsBus; + int outputIndex; + bool outputIsBus; + float gain; + float pan; +}; + + + +ExtraChannelInfo parseExtraChannelInfo(const QJsonObject &obj) +{ + return ExtraChannelInfo + { + .isRoot = obj["isRoot"].toBool(false), + .isSource = obj["isSource"].toBool(false), + .isMuted = obj["isMuted"].toBool(false), + .isSolo = obj["isSolo"].toBool(false), + .inputIndex = obj["inIdx"].toInt(-1), + .inputIsBus = obj["inIsBus"].toBool(false), + .outputIndex = obj["outIdx"].toInt(-1), + .outputIsBus = obj["outIsBus"].toBool(false), + .gain = static_cast(obj["gain"].toDouble(1.0)), + .pan = static_cast(obj["pan"].toDouble(0.0)) + }; +} + + + +void AudioMixMaster::evaluateScript(const QString & scriptName, const QString & scriptContent) +{ + QJsonParseError err; + QJsonDocument doc = QJsonDocument::fromJson(scriptContent.toUtf8(), &err); + if (err.error != QJsonParseError::NoError) + { + qWarning().noquote() << QStringLiteral("Failed to parse \"%1\" as a JSON file: \"%2\".").arg(scriptName).arg(err.errorString()); + return; + } + if (!doc.isObject()) + { + qWarning("Bad input data format."); + return; + } + + Engine::getSong()->clearProject(); + QJsonObject obj = doc.object(); + QJsonArray inputs = obj["inputs"].toArray(); + + auto busyWait = [] (int waittime) + { + if (waittime) + { + qInfo("Waiting %dms...", waittime); + QElapsedTimer timer; + timer.start(); + while (!timer.hasExpired(waittime)) + { + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + QThread::msleep(20); + } + } + }; + + auto processEffects = [](QJsonArray effects, int idx) + { + qInfo("Processing %d effects for channel %d...", effects.size(), idx); + + EffectChain & fxChain = Engine::fxMixer()->effectChannel(idx)->m_fxChain; + for (auto val2 : effects) + { + if (!val2.isObject()) + { + qWarning("Effect descriptor is not an object."); + continue; + } + QJsonObject effectData = val2.toObject(); + + QString effectName = effectData["name"].toString(); + if (effectName.isEmpty()) {continue;} + + Plugin::Descriptor::SubPluginFeatures::Key key; + // XXX why do I need this 'class'? + class Effect * e = Effect::instantiate(effectData["name"].toString(), &fxChain, &key); + if (e) + { + QString fileName = effectData["file"].toString(""); + if (!fileName.isEmpty()) {e->loadFile(fileName);} + /* + // TODO effect presets are not implemented yet + QString presetFileName = effectData["presetFile"].toString(""); + */ + QString pluginPresetFileName = effectData["pluginPresetFile"].toString(""); + if (!pluginPresetFileName.isEmpty()) {e->loadPluginPresetFile(pluginPresetFileName);} + fxChain.appendEffect(e); + } + else + { + qWarning().noquote() << QStringLiteral("Failed to add effect \"%1\"").arg(effectName); + } + } + }; + + + // override masterIndex if you want to route the output to other channels + auto processChannels = [&processEffects] (QJsonArray chs, int &curIndex, int masterIndex = 0) + { + int beginIndex = curIndex; + int numChannelsToAdd = chs.size(); + int curIndexInGroup = 0; + int rootIndex = -1; + int sourceIndex = -1; + std::vector inputIndexes, outputIndexes; + std::vector > sends; // TODO use a struct if desired + inputIndexes.resize(numChannelsToAdd); + outputIndexes.resize(numChannelsToAdd); + + qInfo("Processing %d FX channels...", numChannelsToAdd); + // Engine::fxMixer()->allocateChannelsTo(beginIndex - 1 + numChannelsToAdd); + for (int i = Engine::fxMixer()->numChannels(); i < beginIndex + numChannelsToAdd; ++i) + { + Engine::fxMixer()->createChannel(); + + // delete the default send to master + Engine::fxMixer()->deleteChannelSend(i, 0); + } + + for (auto val : chs) + { + if (!val.isObject()) + { + qWarning("Channel descriptor is not an object."); + continue; + } + + QJsonObject chData = val.toObject(); + ExtraChannelInfo extraInfo = parseExtraChannelInfo(chData); + + // set volume, panning is not supported at this moment + Engine::fxMixer()->effectChannel(curIndex)->m_volumeModel.setValue(extraInfo.gain); + // set mute, ignoring solo + Engine::fxMixer()->effectChannel(curIndex)->m_muteModel.setValue(extraInfo.isMuted); + + // process effects + processEffects(chData["effects"].toArray(), curIndex); + + // handle routing + if (extraInfo.isRoot) + { + rootIndex = curIndexInGroup + beginIndex; + } + if (extraInfo.isSource) + { + if (sourceIndex != -1) + { + qWarning("Multiple sources detected!"); + } + else + { + sourceIndex = curIndexInGroup + beginIndex; + } + } + inputIndexes[curIndexInGroup] = extraInfo.inputIsBus ? extraInfo.inputIndex : -2; + outputIndexes[curIndexInGroup] = extraInfo.outputIsBus ? extraInfo.outputIndex : -3; + // FIXME is this condition always right with internal routing? + if (extraInfo.isRoot || (!extraInfo.outputIsBus && extraInfo.outputIndex == 0)) + { + // send to master + Engine::fxMixer()->createChannelSend(curIndex, masterIndex); + } + QJsonArray sendsData = chData["sends"].toArray(); + for (auto val2 : sendsData) + { + if (!val2.isObject()) + { + qWarning("Send descriptor is not an object."); + continue; + } + QJsonObject sendData = val2.toObject(); + int sendTarget = sendData["target"].toInt(-1); + float sendGain = static_cast(sendData["gain"].toDouble(0.0)); + if (sendTarget >= 0 && sendTarget != extraInfo.inputIndex) + { + sends.push_back({curIndex, sendTarget, sendGain}); + } + } + ++curIndex; + ++curIndexInGroup; + } + // complete routing + for (int src = 0; src < numChannelsToAdd; ++src) + { + for (int dst = 0; dst < numChannelsToAdd; ++dst) + { + if (src != dst && outputIndexes[src] == inputIndexes[dst]) + { + Engine::fxMixer()->createChannelSend(beginIndex + src, beginIndex + dst); + } + } + } + for (auto sendInfo : sends) + { + for (int dst = 0; dst < numChannelsToAdd; ++dst) + { + if (std::get<1>(sendInfo) == inputIndexes[dst]) + { + Engine::fxMixer()->createChannelSend(std::get<0>(sendInfo), beginIndex + dst, std::get<2>(sendInfo)); + } + } + } + if (sourceIndex == -1) sourceIndex = rootIndex; + if (sourceIndex == -1) sourceIndex = 0; + return sourceIndex; + }; + + auto processInputFile = [&processEffects] (QJsonObject inputObj, QJsonObject infoObj, int fxCh = 0) + { + QString sampleFile = inputObj["audiofile"].toString(); + if (!sampleFile.isEmpty()) + { + // add a sample track + SampleTrack *st = static_cast(Track::create(Track::SampleTrack, Engine::getSong())); + st->effectChannelModel()->setInitValue(fxCh); + + // load the sample track + SampleTCO *stco = static_cast(st->createTCO(MidiTime(0))); + stco->setSampleFile(sampleFile); + } + + QString midiFile = inputObj["midifile"].toString(); + if (!midiFile.isEmpty()) + { + ConfigManager::inst()->setValue("tmp", "midifxch", QString::number(fxCh)); + ImportFilter::import(midiFile, Engine::getSong(), infoObj["midiconfig"]); + } + }; + + auto afterLoad = [] () + { + // NOTE: Workaround for some broken Kontakt libraries + // FIXME make this arbitrary values reliable + int fixPitches[] = {60, 69, 71}; + int fixVel = 64; + for (auto track: Engine::getSong()->tracks()) + { + if (track->type() == Track::TrackTypes::InstrumentTrack) + { + auto itrack = static_cast(track); + for (int fixPitch: fixPitches) + { + itrack->processOutEvent(MidiEvent(MidiNoteOn, -1, fixPitch, fixVel)); + } + } + } + QThread::msleep(200); + for (auto track: Engine::getSong()->tracks()) + { + if (track->type() == Track::TrackTypes::InstrumentTrack) + { + auto itrack = static_cast(track); + for (int fixPitch: fixPitches) + { + itrack->processOutEvent(MidiEvent(MidiNoteOff, -1, fixPitch, fixVel)); + } + } + } + }; + + // now process channels + int curIndex = 1; // 0 is master + int masterIndex = 0; + + // master channel + if (obj["master"].isObject()) + { + // using CST + QJsonObject masterChannel = obj["master"].toObject(); + ExtraChannelInfo extraInfo = parseExtraChannelInfo(masterChannel); + // set volume and stuff + Engine::fxMixer()->effectChannel(0)->m_volumeModel.setValue(extraInfo.gain); + processEffects(masterChannel["effects"].toArray(), 0); + } + else if (obj["master"].isArray()) + { + // using PATCH + masterIndex = processChannels(obj["master"].toArray(), curIndex, 0); + } + else if (!obj["master"].isNull()) + { + qWarning("Invalid type for master channel info"); + } + + // others for inputs + bool batchMode = obj["batch"].toBool(false); + int jobCount = obj["jobcount"].toInt(0); + std::vector targetFxChannels; + if (batchMode) + { + if (jobCount < 1) + { + qWarning("Invalid job count!"); + jobCount = 0; + } + else if (jobCount > 1000) + { + qWarning("Too many jobs to process."); + jobCount = 1000; + } + } + + for (auto elem : inputs) // TODO + { + if (!elem.isObject()) + { + qWarning("Input descriptor is not an object."); + continue; + } + + QJsonObject currentInput = elem.toObject(); + + // setup channels + int sourceIndex = processChannels(currentInput["channels"].toArray(), curIndex, masterIndex); + if (!batchMode) + { + processInputFile(currentInput, currentInput, sourceIndex); + } + else + { + targetFxChannels.push_back(sourceIndex); + } + } + + if (batchMode) + { + ConfigManager::inst()->setValue("tmp", "midiimportcache", "1"); + QJsonArray outputPaths = obj["outputs"].toArray(); + for (int i = 0; i < jobCount; ++i) + { + if (i != 0) + { + // Cleanup from the last import + std::vector tracksToRemove; + for (auto track: Engine::getSong()->tracks()) + { + if (track->type() != Track::TrackTypes::InstrumentTrack) + { + tracksToRemove.push_back(track); + } + else + { + track->deleteTCOs(); + } + } + for (auto track: tracksToRemove) + { + // TODO: this should work with GUI as well... + Engine::getSong()->removeTrack(track); + } + } + for (auto elem : inputs) // TODO + { + if (!elem.isObject()) + { + // qWarning("Input descriptor is not an object."); + continue; + } + + const QJsonArray inputBatch = elem.toObject()["batch"].toArray(); + if (i >= inputBatch.size()) + { + continue; + } + + processInputFile(inputBatch[i].toObject(), elem.toObject(), targetFxChannels[i]); + } + + // Post-setup steps + if (i == 0) + { + afterLoad(); + busyWait(obj["waittime"].toInt(0)); + } + + if (i < outputPaths.size()) + { + const QString outPath = outputPaths[i].toString(); + // TODO validate as well + if (!outPath.isEmpty()) + { + std::unique_ptr r = make_unique( + Engine::mixer()->currentQualitySettings(), + OutputSettings( + Engine::mixer()->outputSampleRate(), + OutputSettings::BitRateSettings(160, false), // ignored in WAV files + OutputSettings::Depth_16Bit + ), + ProjectRenderer::ExportFileFormats::WaveFile, + outPath + ); + bool renderDone = false; + QObject::connect(r.get(), &RenderManager::finished, [&renderDone](){renderDone = true;}); + + // stolen from main.cpp + QTimer * t = new QTimer(r.get()); + r->connect(t, SIGNAL(timeout()), SLOT(updateConsoleProgress())); + t->start(200); + r->renderProject(); + + while (!renderDone) + { + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents, 50); + } + } + } + } + } + + QString fileToSave = obj["savefile"].toString(); + if (!fileToSave.isEmpty()) + { + bool result = Engine::getSong()->saveProjectFile(fileToSave); + if (!result) + { + qWarning("Failed to save the result."); + return; + } + } + if (!batchMode) + { + afterLoad(); + busyWait(obj["waittime"].toInt(0)); + } + qInfo("Done."); +} + + + + +void AudioMixMaster::saveSettings(QDomDocument & doc, QDomElement & element) +{ +} + + + +void AudioMixMaster::loadSettings(const QDomElement & element) +{ +} + + + +PluginView * AudioMixMaster::instantiateView(QWidget * parent) +{ + return nullptr; +} + + + +extern "C" +{ + +// necessary for getting instance out of shared lib +PLUGIN_EXPORT Plugin * lmms_plugin_main(Model* parent, void* data) +{ + return new AudioMixMaster(parent, static_cast(data)); +} + +} + diff --git a/plugins/AudioMixMaster/AudioMixMaster.h b/plugins/AudioMixMaster/AudioMixMaster.h new file mode 100644 index 00000000000..b32f1f20952 --- /dev/null +++ b/plugins/AudioMixMaster/AudioMixMaster.h @@ -0,0 +1,45 @@ +/* + * AudioMixMaster.h - a sample scripting plugin + * + * Copyright (c) 2019 - 2020 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef SCRIPTSAMPLE_H +#define SCRIPTSAMPLE_H + +#include "ScriptPlugin.h" + +class AudioMixMaster : public ScriptPlugin +{ +public: + AudioMixMaster(Model* parent, const Descriptor::SubPluginFeatures::Key* key); + virtual ~AudioMixMaster(); + + void evaluateScript(const QString & scriptName, const QString & scriptContent) override; + + void saveSettings(QDomDocument & doc, QDomElement & element) override; + void loadSettings(const QDomElement & element) override; + + PluginView * instantiateView(QWidget * parent) override; +}; + +#endif diff --git a/plugins/AudioMixMaster/CMakeLists.txt b/plugins/AudioMixMaster/CMakeLists.txt new file mode 100644 index 00000000000..352ac395186 --- /dev/null +++ b/plugins/AudioMixMaster/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(audiomixmaster AudioMixMaster.cpp MOCFILES AudioMixMaster.h) diff --git a/plugins/BassBooster/BassBooster.cpp b/plugins/BassBooster/BassBooster.cpp index 6fdb1671c66..535834aae77 100644 --- a/plugins/BassBooster/BassBooster.cpp +++ b/plugins/BassBooster/BassBooster.cpp @@ -100,13 +100,13 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames //float gain = gainBuffer ? gainBuffer[f] : gain; m_bbFX.leftFX().setGain( gain ); m_bbFX.rightFX().setGain( gain); - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; sample_t s[2] = { buf[f][0], buf[f][1] }; m_bbFX.nextSample( s[0], s[1] ); buf[f][0] = d * buf[f][0] + w * s[0]; buf[f][1] = d * buf[f][1] + w * s[1]; + outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; } checkGate( outSum / frames ); diff --git a/plugins/Bitcrush/BitcrushControls.cpp b/plugins/Bitcrush/BitcrushControls.cpp index 6aafd0b194e..f768be4b86f 100644 --- a/plugins/Bitcrush/BitcrushControls.cpp +++ b/plugins/Bitcrush/BitcrushControls.cpp @@ -40,7 +40,7 @@ BitcrushControls::BitcrushControls( BitcrushEffect * eff ) : m_outClip( 0.0f, -20.0f, 20.0f, 0.1f, this, tr( "Output clip" ) ), m_rate( 44100.f, 20.f, 44100.f, 1.0f, this, tr( "Sample rate" ) ), m_stereoDiff( 0.f, 0.f, 50.f, 0.1f, this, tr( "Stereo difference" ) ), - m_levels( 256.f, 1.f, 256.f, 1.0f, this, tr( "Levels" ) ), + m_levels( 256.f, 1.f, 256.f, 0.01f, this, tr( "Levels" ) ), m_rateEnabled( true, this, tr( "Rate enabled" ) ), m_depthEnabled( true, this, tr( "Depth enabled" ) ) { diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 4f139f8b32b..a4e56921fea 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -14,89 +14,7 @@ INCLUDE_DIRECTORIES( "${CMAKE_BINARY_DIR}/src" ) -SET(PLUGIN_LIST "" CACHE STRING "List of plug-ins to build") - -STRING(REPLACE " " ";" PLUGIN_LIST "${PLUGIN_LIST}") - -OPTION(LMMS_MINIMAL "Build a minimal list of plug-ins" OFF) - -SET(MINIMAL_LIST - audio_file_processor - kicker - triple_oscillator -) - -IF(LMMS_MINIMAL) - IF("${PLUGIN_LIST}" STREQUAL "") - STRING(REPLACE ";" " " MINIMAL_LIST_STRING "${MINIMAL_LIST}") - MESSAGE( -"-- Using minimal plug-ins: ${MINIMAL_LIST_STRING}\n" -" Note: You can specify specific plug-ins using -DPLUGIN_LIST=\"foo bar\"" - ) - ENDIF() - SET(PLUGIN_LIST ${MINIMAL_LIST} ${PLUGIN_LIST}) -ENDIF() - -IF("${PLUGIN_LIST}" STREQUAL "") - SET(PLUGIN_LIST - ${MINIMAL_LIST} - Amplifier - BassBooster - bit_invader - Bitcrush - carlabase - carlapatchbay - carlarack - CrossoverEQ - Delay - DualFilter - dynamics_processor - Eq - Flanger - HydrogenImport - ladspa_browser - LadspaEffect - lb302 - MidiImport - MidiExport - MultitapEcho - monstro - nes - OpulenZ - organic - FreeBoy - patman - peak_controller_effect - GigPlayer - ReverbSC - sf2_player - sfxr - sid - SpectrumAnalyzer - stereo_enhancer - stereo_matrix - stk - vst_base - vestige - VstEffect - watsyn - waveshaper - vibed - Xpressive - zynaddsubfx - ) - -ENDIF("${PLUGIN_LIST}" STREQUAL "") - -IF(MSVC) - SET(MSVC_INCOMPATIBLE_PLUGINS - LadspaEffect - zynaddsubfx - ) - message(WARNING "Compiling with MSVC. The following plugins are not available: ${MSVC_INCOMPATIBLE_PLUGINS}") - LIST(REMOVE_ITEM PLUGIN_LIST ${MSVC_INCOMPATIBLE_PLUGINS}) -ENDIF() - +# See cmake/modules/PluginList.cmake FOREACH(PLUGIN ${PLUGIN_LIST}) ADD_SUBDIRECTORY(${PLUGIN}) ENDFOREACH() diff --git a/plugins/CrossoverEQ/CrossoverEQ.cpp b/plugins/CrossoverEQ/CrossoverEQ.cpp index e7d3dce7d34..e2090980a06 100644 --- a/plugins/CrossoverEQ/CrossoverEQ.cpp +++ b/plugins/CrossoverEQ/CrossoverEQ.cpp @@ -191,12 +191,12 @@ bool CrossoverEQEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames double outSum = 0.0; for( int f = 0; f < frames; ++f ) { - outSum = buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; buf[f][0] = d * buf[f][0] + w * m_work[f][0]; buf[f][1] = d * buf[f][1] + w * m_work[f][1]; + outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; } - checkGate( outSum ); + checkGate( outSum / frames ); return isRunning(); } diff --git a/plugins/DualFilter/DualFilter.cpp b/plugins/DualFilter/DualFilter.cpp index 5b8b7a622c1..b4e11ccb396 100644 --- a/plugins/DualFilter/DualFilter.cpp +++ b/plugins/DualFilter/DualFilter.cpp @@ -193,11 +193,11 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames s[0] += ( s2[0] * mix2 ); s[1] += ( s2[1] * mix2 ); } - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; // do another mix with dry signal buf[f][0] = d * buf[f][0] + w * s[0]; buf[f][1] = d * buf[f][1] + w * s[1]; + outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; //increment pointers cut1Ptr += cut1Inc; diff --git a/plugins/DualFilter/DualFilterControlDialog.cpp b/plugins/DualFilter/DualFilterControlDialog.cpp index 73755bef38f..0c7732bc6c2 100755 --- a/plugins/DualFilter/DualFilterControlDialog.cpp +++ b/plugins/DualFilter/DualFilterControlDialog.cpp @@ -75,12 +75,12 @@ DualFilterControlDialog::DualFilterControlDialog( DualFilterControls* controls ) ToolTip::add( enabled2Toggle, tr( "Enable/disable filter 2" ) ); ComboBox * m_filter1ComboBox = new ComboBox( this ); - m_filter1ComboBox->setGeometry( 19, 70, 137, 22 ); + m_filter1ComboBox->setGeometry( 19, 70, 137, ComboBox::DEFAULT_HEIGHT ); m_filter1ComboBox->setFont( pointSize<8>( m_filter1ComboBox->font() ) ); m_filter1ComboBox->setModel( &controls->m_filter1Model ); ComboBox * m_filter2ComboBox = new ComboBox( this ); - m_filter2ComboBox->setGeometry( 217, 70, 137, 22 ); + m_filter2ComboBox->setGeometry( 217, 70, 137, ComboBox::DEFAULT_HEIGHT ); m_filter2ComboBox->setFont( pointSize<8>( m_filter2ComboBox->font() ) ); m_filter2ComboBox->setModel( &controls->m_filter2Model ); } diff --git a/plugins/Eq/EqSpectrumView.h b/plugins/Eq/EqSpectrumView.h index cd3f1775863..84feeff13e8 100644 --- a/plugins/Eq/EqSpectrumView.h +++ b/plugins/Eq/EqSpectrumView.h @@ -24,6 +24,7 @@ #define EQSPECTRUMVIEW_H #include +#include #include #include "fft_helpers.h" diff --git a/plugins/FreeBoy/FreeBoy.cpp b/plugins/FreeBoy/FreeBoy.cpp index 8647e7f4b27..2f787044f25 100644 --- a/plugins/FreeBoy/FreeBoy.cpp +++ b/plugins/FreeBoy/FreeBoy.cpp @@ -457,7 +457,7 @@ class FreeBoyKnob : public Knob FreeBoyInstrumentView::FreeBoyInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); diff --git a/plugins/FreeBoy/FreeBoy.h b/plugins/FreeBoy/FreeBoy.h index 69c4785050b..9ceb2796671 100644 --- a/plugins/FreeBoy/FreeBoy.h +++ b/plugins/FreeBoy/FreeBoy.h @@ -111,7 +111,7 @@ class FreeBoyInstrument : public Instrument } ; -class FreeBoyInstrumentView : public InstrumentView +class FreeBoyInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/GigPlayer/GigPlayer.cpp b/plugins/GigPlayer/GigPlayer.cpp index 200439dae92..334e2bd7737 100644 --- a/plugins/GigPlayer/GigPlayer.cpp +++ b/plugins/GigPlayer/GigPlayer.cpp @@ -28,6 +28,7 @@ * */ +#include "GigPlayer.h" #include #include @@ -35,18 +36,18 @@ #include #include -#include "FileDialog.h" -#include "GigPlayer.h" +#include "ConfigManager.h" +#include "endian_handling.h" #include "Engine.h" +#include "FileDialog.h" #include "InstrumentTrack.h" #include "InstrumentPlayHandle.h" +#include "Knob.h" #include "Mixer.h" #include "NotePlayHandle.h" -#include "Knob.h" +#include "PathUtil.h" #include "SampleBuffer.h" #include "Song.h" -#include "ConfigManager.h" -#include "endian_handling.h" #include "PatchesDialog.h" #include "ToolTip.h" @@ -211,8 +212,8 @@ void GigInstrument::openFile( const QString & _gigFile, bool updateTrackName ) try { - m_instance = new GigInstance( SampleBuffer::tryToMakeAbsolute( _gigFile ) ); - m_filename = SampleBuffer::tryToMakeRelative( _gigFile ); + m_instance = new GigInstance( PathUtil::toAbsolute( _gigFile ) ); + m_filename = PathUtil::toShortestRelative( _gigFile ); } catch( ... ) { @@ -225,7 +226,7 @@ void GigInstrument::openFile( const QString & _gigFile, bool updateTrackName ) if( updateTrackName == true ) { - instrumentTrack()->setName( QFileInfo( _gigFile ).baseName() ); + instrumentTrack()->setName(PathUtil::cleanName( _gigFile ) ); updatePatch(); } } @@ -922,7 +923,7 @@ class gigKnob : public Knob GigInstrumentView::GigInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { GigInstrument * k = castModel(); @@ -1057,7 +1058,7 @@ void GigInstrumentView::showFileDialog() if( k->m_filename != "" ) { - QString f = SampleBuffer::tryToMakeAbsolute( k->m_filename ); + QString f = PathUtil::toAbsolute( k->m_filename ); ofd.setDirectory( QFileInfo( f ).absolutePath() ); ofd.selectFile( QFileInfo( f ).fileName() ); } diff --git a/plugins/GigPlayer/GigPlayer.h b/plugins/GigPlayer/GigPlayer.h index 0a5e023f9b6..b9467b91bbf 100644 --- a/plugins/GigPlayer/GigPlayer.h +++ b/plugins/GigPlayer/GigPlayer.h @@ -334,7 +334,7 @@ public slots: -class GigInstrumentView : public InstrumentView +class GigInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/HydrogenImport/HydrogenImport.cpp b/plugins/HydrogenImport/HydrogenImport.cpp index 9f9f1dd4961..c9363063a7f 100644 --- a/plugins/HydrogenImport/HydrogenImport.cpp +++ b/plugins/HydrogenImport/HydrogenImport.cpp @@ -202,13 +202,19 @@ bool HydrogenImport::readSong() else { unsigned nLayer = 0; - QDomNode layerNode = instrumentNode.firstChildElement( "layer" ); + QDomNode instrumentComponentNode = instrumentNode.firstChildElement("instrumentComponent"); + if (instrumentComponentNode.isNull()) + { + instrumentComponentNode = instrumentNode; + } + + QDomNode layerNode = instrumentComponentNode.firstChildElement( "layer" ); while ( ! layerNode.isNull() ) { if ( nLayer >= MAX_LAYERS ) { - printf( "nLayer >= MAX_LAYERS" ); - continue; + printf("nLayer >= MAX_LAYERS\n"); + break; } QString sFilename = LocalFileMng::readXmlString( layerNode, "filename", "" ); QString sMode = LocalFileMng::readXmlString( layerNode, "smode", "forward" ); @@ -327,7 +333,7 @@ bool HydrogenImport::readSong() } return true; } -bool HydrogenImport::tryImport( TrackContainer* tc ) +bool HydrogenImport::tryImport(TrackContainer* tc, QJsonValue config) { if( openFile() == false ) { diff --git a/plugins/HydrogenImport/HydrogenImport.h b/plugins/HydrogenImport/HydrogenImport.h index 1c916f3c342..0d78bf9b960 100644 --- a/plugins/HydrogenImport/HydrogenImport.h +++ b/plugins/HydrogenImport/HydrogenImport.h @@ -21,7 +21,7 @@ class HydrogenImport : public ImportFilter return( NULL ); } private: - virtual bool tryImport( TrackContainer* tc ); + virtual bool tryImport(TrackContainer* tc, QJsonValue config = QJsonValue()); }; #endif diff --git a/plugins/LadspaEffect/LadspaControls.h b/plugins/LadspaEffect/LadspaControls.h index ccb96dd7484..013b914d45d 100644 --- a/plugins/LadspaEffect/LadspaControls.h +++ b/plugins/LadspaEffect/LadspaControls.h @@ -71,6 +71,7 @@ protected slots: ch_cnt_t m_controlCount; bool m_noLink; BoolModel m_stereoLinkModel; + //! control vector for each processor QVector m_controls; diff --git a/plugins/Lv2Effect/CMakeLists.txt b/plugins/Lv2Effect/CMakeLists.txt new file mode 100644 index 00000000000..915751797d1 --- /dev/null +++ b/plugins/Lv2Effect/CMakeLists.txt @@ -0,0 +1,9 @@ +IF(LMMS_HAVE_LV2) + INCLUDE_DIRECTORIES(${LV2_INCLUDE_DIRS}) + INCLUDE_DIRECTORIES(${LILV_INCLUDE_DIRS}) + INCLUDE_DIRECTORIES(${SUIL_INCLUDE_DIRS}) + INCLUDE(BuildPlugin) + BUILD_PLUGIN(lv2effect Lv2Effect.cpp Lv2FxControls.cpp Lv2FxControlDialog.cpp Lv2Effect.h Lv2FxControls.h Lv2FxControlDialog.h + MOCFILES Lv2Effect.h Lv2FxControls.h Lv2FxControlDialog.h + EMBEDDED_RESOURCES logo.png) +ENDIF(LMMS_HAVE_LV2) diff --git a/plugins/Lv2Effect/Lv2Effect.cpp b/plugins/Lv2Effect/Lv2Effect.cpp new file mode 100644 index 00000000000..2ee5ceabbe5 --- /dev/null +++ b/plugins/Lv2Effect/Lv2Effect.cpp @@ -0,0 +1,111 @@ +/* + * Lv2Effect.cpp - implementation of LV2 effect + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Lv2Effect.h" + +#include +#include + +#include "Lv2SubPluginFeatures.h" + +#include "embed.h" +#include "plugin_export.h" + + + + +Plugin::Descriptor PLUGIN_EXPORT lv2effect_plugin_descriptor = +{ + STRINGIFY(PLUGIN_NAME), + "LV2", + QT_TRANSLATE_NOOP("pluginBrowser", + "plugin for using arbitrary LV2-effects inside LMMS."), + "Johannes Lorenz ", + 0x0100, + Plugin::Effect, + new PluginPixmapLoader("logo"), + nullptr, + new Lv2SubPluginFeatures(Plugin::Effect) +}; + + + + +Lv2Effect::Lv2Effect(Model* parent, const Descriptor::SubPluginFeatures::Key *key) : + Effect(&lv2effect_plugin_descriptor, parent, key), + m_controls(this, key->attributes["uri"]), + m_tmpOutputSmps(Engine::mixer()->framesPerPeriod()) +{ +} + + + + +bool Lv2Effect::processAudioBuffer(sampleFrame *buf, const fpp_t frames) +{ + if (!isEnabled() || !isRunning()) { return false; } + Q_ASSERT(frames <= static_cast(m_tmpOutputSmps.size())); + + m_controls.copyBuffersFromLmms(buf, frames); + m_controls.copyModelsFromLmms(); + +// m_pluginMutex.lock(); + m_controls.run(frames); +// m_pluginMutex.unlock(); + + m_controls.copyBuffersToLmms(m_tmpOutputSmps.data(), frames); + + double outSum = .0; + bool corrupt = wetLevel() < 0; // #3261 - if w < 0, bash w := 0, d := 1 + const float d = corrupt ? 1 : dryLevel(); + const float w = corrupt ? 0 : wetLevel(); + for(fpp_t f = 0; f < frames; ++f) + { + buf[f][0] = d * buf[f][0] + w * m_tmpOutputSmps[f][0]; + buf[f][1] = d * buf[f][1] + w * m_tmpOutputSmps[f][1]; + double l = static_cast(buf[f][0]); + double r = static_cast(buf[f][1]); + outSum += l*l + r*r; + } + checkGate(outSum / frames); + + return isRunning(); +} + + + + +extern "C" +{ + +// necessary for getting instance out of shared lib +PLUGIN_EXPORT Plugin *lmms_plugin_main(Model *_parent, void *_data) +{ + using KeyType = Plugin::Descriptor::SubPluginFeatures::Key; + Lv2Effect* eff = new Lv2Effect(_parent, static_cast(_data)); + if (!eff->isValid()) { delete eff; eff = nullptr; } + return eff; +} + +} diff --git a/plugins/Lv2Effect/Lv2Effect.h b/plugins/Lv2Effect/Lv2Effect.h new file mode 100644 index 00000000000..77792d428a1 --- /dev/null +++ b/plugins/Lv2Effect/Lv2Effect.h @@ -0,0 +1,54 @@ +/* + * Lv2Effect.h - implementation of LV2 effect + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2_EFFECT_H +#define LV2_EFFECT_H + +#include "Effect.h" +#include "Lv2FxControls.h" + +class Lv2Effect : public Effect +{ + Q_OBJECT + +public: + /* + initialization + */ + Lv2Effect(Model* parent, const Descriptor::SubPluginFeatures::Key* _key); + //! Must be checked after ctor or reload + bool isValid() const { return m_controls.isValid(); } + + bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override; + EffectControls* controls() override { return &m_controls; } + + Lv2FxControls* lv2Controls() { return &m_controls; } + const Lv2FxControls* lv2Controls() const { return &m_controls; } + +private: + Lv2FxControls m_controls; + std::vector m_tmpOutputSmps; +}; + +#endif // LMMS_HAVE_LV2 diff --git a/plugins/Lv2Effect/Lv2FxControlDialog.cpp b/plugins/Lv2Effect/Lv2FxControlDialog.cpp new file mode 100644 index 00000000000..9a77171d6df --- /dev/null +++ b/plugins/Lv2Effect/Lv2FxControlDialog.cpp @@ -0,0 +1,72 @@ +/* + * Lv2FxControlDialog.cpp - Lv2FxControlDialog implementation + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Lv2FxControlDialog.h" + +#include +#include +#include + +#include "Lv2Effect.h" +#include "Lv2FxControls.h" + + +Lv2FxControlDialog::Lv2FxControlDialog(Lv2FxControls *controls) : + EffectControlDialog(controls), + Lv2ViewBase(this, controls) +{ + if (m_reloadPluginButton) { + connect(m_reloadPluginButton, &QPushButton::clicked, + this, [this](){ lv2Controls()->reloadPlugin(); }); + } + if (m_toggleUIButton) { + connect(m_toggleUIButton, &QPushButton::toggled, + this, [this](){ toggleUI(); }); + } + if (m_helpButton) { + connect(m_helpButton, &QPushButton::toggled, + this, [this](bool visible){ toggleHelp(visible); }); + } + // for Effects, modelChanged only goes to the top EffectView + // we need to call it manually + modelChanged(); +} + + + + +Lv2FxControls *Lv2FxControlDialog::lv2Controls() +{ + return static_cast(m_effectControls); +} + + + + +void Lv2FxControlDialog::modelChanged() +{ + Lv2ViewBase::modelChanged(lv2Controls()); +} + + diff --git a/include/update_event.h b/plugins/Lv2Effect/Lv2FxControlDialog.h similarity index 62% rename from include/update_event.h rename to plugins/Lv2Effect/Lv2FxControlDialog.h index c3773263032..3abdb300d4d 100644 --- a/include/update_event.h +++ b/plugins/Lv2Effect/Lv2FxControlDialog.h @@ -1,7 +1,7 @@ /* - * update_event.h - signal GUI updates + * Lv2FxControlDialog.h - Lv2FxControlDialog implementation * - * Copyright (c) 2007 Javier Serrano Polo + * Copyright (c) 2018-2020 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * @@ -22,23 +22,26 @@ * */ +#ifndef LV2_FX_CONTROL_DIALOG_H +#define LV2_FX_CONTROL_DIALOG_H -#ifndef UPDATE_EVENT_H -#define UPDATE_EVENT_H +#include "EffectControlDialog.h" +#include "Lv2ViewBase.h" -#include "custom_events.h" +class Lv2FxControls; - -class updateEvent : public QEvent +class Lv2FxControlDialog : public EffectControlDialog, public Lv2ViewBase { + Q_OBJECT + public: - updateEvent() : - QEvent( (QEvent::Type)customEvents::GUI_UPDATE ) - { - } + Lv2FxControlDialog(Lv2FxControls *controls); -} ; +private: + Lv2FxControls *lv2Controls(); + void modelChanged() override; +}; #endif diff --git a/plugins/Lv2Effect/Lv2FxControls.cpp b/plugins/Lv2Effect/Lv2FxControls.cpp new file mode 100644 index 00000000000..a5733fec670 --- /dev/null +++ b/plugins/Lv2Effect/Lv2FxControls.cpp @@ -0,0 +1,104 @@ +/* + * Lv2FxControls.cpp - Lv2FxControls implementation + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Lv2FxControls.h" + +#include + +#include "Engine.h" +#include "Lv2Effect.h" +#include "Lv2FxControlDialog.h" +#include "Lv2Proc.h" + + + + +Lv2FxControls::Lv2FxControls(class Lv2Effect *effect, const QString& uri) : + EffectControls(effect), + Lv2ControlBase(this, uri) +{ + if (isValid()) + { + connect(Engine::mixer(), &Mixer::sampleRateChanged, + this, [this](){Lv2ControlBase::reloadPlugin();}); + } +} + + + + +void Lv2FxControls::saveSettings(QDomDocument &doc, QDomElement &that) +{ + Lv2ControlBase::saveSettings(doc, that); +} + + + + +void Lv2FxControls::loadSettings(const QDomElement &that) +{ + Lv2ControlBase::loadSettings(that); +} + + + + +int Lv2FxControls::controlCount() +{ + return static_cast(Lv2ControlBase::controlCount()); +} + + + + +EffectControlDialog *Lv2FxControls::createView() +{ + return new Lv2FxControlDialog(this); +} + + + + +void Lv2FxControls::changeControl() // TODO: what is that? +{ + // engine::getSong()->setModified(); +} + + + + +DataFile::Types Lv2FxControls::settingsType() +{ + return DataFile::EffectSettings; +} + + + + +void Lv2FxControls::setNameFromFile(const QString &name) +{ + effect()->setDisplayName(name); +} + + diff --git a/plugins/Lv2Effect/Lv2FxControls.h b/plugins/Lv2Effect/Lv2FxControls.h new file mode 100644 index 00000000000..e5449a4f7fe --- /dev/null +++ b/plugins/Lv2Effect/Lv2FxControls.h @@ -0,0 +1,61 @@ +/* + * Lv2FxControls.h - Lv2FxControls implementation + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2_FX_CONTROLS_H +#define LV2_FX_CONTROLS_H + +#include "EffectControls.h" +#include "Lv2ControlBase.h" + +class Lv2Effect; + + +class Lv2FxControls : public EffectControls, public Lv2ControlBase +{ + Q_OBJECT +public: + Lv2FxControls(Lv2Effect *effect, const QString &uri); + + void saveSettings(QDomDocument &_doc, QDomElement &_parent) override; + void loadSettings(const QDomElement &that) override; + inline QString nodeName() const override + { + return Lv2ControlBase::nodeName(); + } + + int controlCount() override; + EffectControlDialog *createView() override; + +private slots: + void changeControl(); + +private: + DataFile::Types settingsType() override; + void setNameFromFile(const QString &name) override; + + friend class Lv2FxControlDialog; + friend class Lv2Effect; +}; + +#endif diff --git a/plugins/Lv2Effect/logo.png b/plugins/Lv2Effect/logo.png new file mode 100644 index 00000000000..c423ccea458 Binary files /dev/null and b/plugins/Lv2Effect/logo.png differ diff --git a/plugins/Lv2Instrument/CMakeLists.txt b/plugins/Lv2Instrument/CMakeLists.txt new file mode 100644 index 00000000000..290bd84e82e --- /dev/null +++ b/plugins/Lv2Instrument/CMakeLists.txt @@ -0,0 +1,7 @@ +IF(LMMS_HAVE_LV2) + INCLUDE_DIRECTORIES(${LV2_INCLUDE_DIRS}) + INCLUDE_DIRECTORIES(${LILV_INCLUDE_DIRS}) + INCLUDE_DIRECTORIES(${SUIL_INCLUDE_DIRS}) + INCLUDE(BuildPlugin) + BUILD_PLUGIN(lv2instrument Lv2Instrument.cpp Lv2Instrument.h MOCFILES Lv2Instrument.h EMBEDDED_RESOURCES logo.png) +ENDIF(LMMS_HAVE_LV2) diff --git a/plugins/Lv2Instrument/Lv2Instrument.cpp b/plugins/Lv2Instrument/Lv2Instrument.cpp new file mode 100644 index 00000000000..974aaf416b4 --- /dev/null +++ b/plugins/Lv2Instrument/Lv2Instrument.cpp @@ -0,0 +1,303 @@ +/* + * Lv2Instrument.cpp - implementation of LV2 instrument + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Lv2Instrument.h" + +#include +#include + +#include "Engine.h" +#include "InstrumentPlayHandle.h" +#include "InstrumentTrack.h" +#include "Lv2SubPluginFeatures.h" +#include "Mixer.h" +#include "StringPairDrag.h" + +#include "embed.h" +#include "plugin_export.h" + + + + +Plugin::Descriptor PLUGIN_EXPORT lv2instrument_plugin_descriptor = +{ + STRINGIFY(PLUGIN_NAME), + "LV2", + QT_TRANSLATE_NOOP("pluginBrowser", + "plugin for using arbitrary LV2 instruments inside LMMS."), + "Johannes Lorenz ", + 0x0100, + Plugin::Instrument, + new PluginPixmapLoader("logo"), + nullptr, + new Lv2SubPluginFeatures(Plugin::Instrument) +}; + + + + +/* + Lv2Instrument +*/ + + +Lv2Instrument::Lv2Instrument(InstrumentTrack *instrumentTrackArg, + Descriptor::SubPluginFeatures::Key *key) : + Instrument(instrumentTrackArg, &lv2instrument_plugin_descriptor, key), + Lv2ControlBase(this, key->attributes["uri"]) +{ + if (Lv2ControlBase::isValid()) + { +#ifdef LV2_INSTRUMENT_USE_MIDI + for (int i = 0; i < NumKeys; ++i) { m_runningNotes[i] = 0; } +#endif + connect(instrumentTrack()->pitchRangeModel(), SIGNAL(dataChanged()), + this, SLOT(updatePitchRange()), Qt::DirectConnection); + connect(Engine::mixer(), &Mixer::sampleRateChanged, + this, [this](){Lv2ControlBase::reloadPlugin();}); + + // now we need a play-handle which cares for calling play() + InstrumentPlayHandle *iph = + new InstrumentPlayHandle(this, instrumentTrackArg); + Engine::mixer()->addPlayHandle(iph); + } +} + + + + +Lv2Instrument::~Lv2Instrument() +{ + Engine::mixer()->removePlayHandlesOfTypes(instrumentTrack(), + PlayHandle::TypeNotePlayHandle | + PlayHandle::TypeInstrumentPlayHandle); +} + + + + +bool Lv2Instrument::isValid() const { return Lv2ControlBase::isValid(); } + + + + +void Lv2Instrument::saveSettings(QDomDocument &doc, QDomElement &that) +{ + Lv2ControlBase::saveSettings(doc, that); +} + + + + +void Lv2Instrument::loadSettings(const QDomElement &that) +{ + Lv2ControlBase::loadSettings(that); +} + + + + +void Lv2Instrument::loadFile(const QString &file) +{ + Lv2ControlBase::loadFile(file); +} + + + + +#ifdef LV2_INSTRUMENT_USE_MIDI +bool Lv2Instrument::handleMidiEvent( + const MidiEvent &event, const MidiTime &time, f_cnt_t offset) +{ + // this function can be called from GUI threads while the plugin is running, + // so this requires caching, e.g. in ringbuffers + (void)time; + (void)offset; + (void)event; + return true; +} +#endif + + + + +// not yet working +#ifndef LV2_INSTRUMENT_USE_MIDI +void Lv2Instrument::playNote(NotePlayHandle *nph, sampleFrame *) +{ +} +#endif + + + + +void Lv2Instrument::play(sampleFrame *buf) +{ + copyModelsFromLmms(); + + fpp_t fpp = Engine::mixer()->framesPerPeriod(); + + run(fpp); + + copyBuffersToLmms(buf, fpp); + + instrumentTrack()->processAudioBuffer(buf, fpp, nullptr); +} + + + + +PluginView *Lv2Instrument::instantiateView(QWidget *parent) +{ + return new Lv2InsView(this, parent); +} + + + + +void Lv2Instrument::updatePitchRange() +{ + qDebug() << "Lmms: Cannot update pitch range for lv2 plugin:" + "not implemented yet"; +} + + + + +QString Lv2Instrument::nodeName() const +{ + return Lv2ControlBase::nodeName(); +} + + + + +DataFile::Types Lv2Instrument::settingsType() +{ + return DataFile::InstrumentTrackSettings; +} + + + + +void Lv2Instrument::setNameFromFile(const QString &name) +{ + instrumentTrack()->setName(name); +} + + + + +/* + Lv2InsView +*/ + + +Lv2InsView::Lv2InsView(Lv2Instrument *_instrument, QWidget *_parent) : + InstrumentView(_instrument, _parent), + Lv2ViewBase(this, _instrument) +{ + setAutoFillBackground(true); + if (m_reloadPluginButton) { + connect(m_reloadPluginButton, &QPushButton::clicked, + this, [this](){ castModel()->reloadPlugin();} ); + } + if (m_toggleUIButton) { + connect(m_toggleUIButton, &QPushButton::toggled, + this, [this](){ toggleUI(); }); + } + if (m_helpButton) { + connect(m_helpButton, &QPushButton::toggled, + this, [this](bool visible){ toggleHelp(visible); }); + } +} + + + + +void Lv2InsView::dragEnterEvent(QDragEnterEvent *_dee) +{ + void (QDragEnterEvent::*reaction)(void) = &QDragEnterEvent::ignore; + + if (_dee->mimeData()->hasFormat(StringPairDrag::mimeType())) + { + const QString txt = + _dee->mimeData()->data(StringPairDrag::mimeType()); + if (txt.section(':', 0, 0) == "pluginpresetfile") { + reaction = &QDragEnterEvent::acceptProposedAction; + } + } + + (_dee->*reaction)(); +} + + + + +void Lv2InsView::dropEvent(QDropEvent *_de) +{ + const QString type = StringPairDrag::decodeKey(_de); + const QString value = StringPairDrag::decodeValue(_de); + if (type == "pluginpresetfile") + { + castModel()->loadFile(value); + _de->accept(); + return; + } + _de->ignore(); +} + + + + +void Lv2InsView::toggleUI() +{ +} + + + + +void Lv2InsView::modelChanged() +{ + Lv2ViewBase::modelChanged(castModel()); +} + + + + +extern "C" +{ + +// necessary for getting instance out of shared lib +PLUGIN_EXPORT Plugin *lmms_plugin_main(Model *_parent, void *_data) +{ + using KeyType = Plugin::Descriptor::SubPluginFeatures::Key; + Lv2Instrument* ins = new Lv2Instrument( + static_cast(_parent), + static_cast(_data )); + if (!ins->isValid()) { delete ins; ins = nullptr; } + return ins; +} + +} diff --git a/plugins/Lv2Instrument/Lv2Instrument.h b/plugins/Lv2Instrument/Lv2Instrument.h new file mode 100644 index 00000000000..6451d49cdcf --- /dev/null +++ b/plugins/Lv2Instrument/Lv2Instrument.h @@ -0,0 +1,123 @@ +/* + * Lv2Instrument.h - implementation of LV2 instrument + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LV2_INSTRUMENT_H +#define LV2_INSTRUMENT_H + +#include + +#include "Instrument.h" +#include "InstrumentView.h" +#include "Note.h" +#include "Lv2ControlBase.h" +#include "Lv2ViewBase.h" + +// whether to use MIDI vs playHandle +// currently only MIDI works +#define LV2_INSTRUMENT_USE_MIDI + +class QPushButton; + + +class Lv2Instrument : public Instrument, public Lv2ControlBase +{ + Q_OBJECT +public: + /* + initialization + */ + Lv2Instrument(InstrumentTrack *instrumentTrackArg, + Descriptor::SubPluginFeatures::Key* key); + ~Lv2Instrument() override; + //! Must be checked after ctor or reload + bool isValid() const; + + /* + load/save + */ + void saveSettings(QDomDocument &doc, QDomElement &that) override; + void loadSettings(const QDomElement &that) override; + void loadFile(const QString &file) override; + + /* + realtime funcs + */ + bool hasNoteInput() const override { return false; /* not supported yet */ } +#ifdef LV2_INSTRUMENT_USE_MIDI + bool handleMidiEvent(const MidiEvent &event, + const MidiTime &time = MidiTime(), f_cnt_t offset = 0) override; +#else + void playNote(NotePlayHandle *nph, sampleFrame *) override; +#endif + void play(sampleFrame *buf) override; + + /* + misc + */ + Flags flags() const override + { +#ifdef LV2_INSTRUMENT_USE_MIDI + return IsSingleStreamed | IsMidiBased; +#else + return IsSingleStreamed; +#endif + } + PluginView *instantiateView(QWidget *parent) override; + +private slots: + void updatePitchRange(); + +private: + QString nodeName() const override; + DataFile::Types settingsType() override; + void setNameFromFile(const QString &name) override; + +#ifdef LV2_INSTRUMENT_USE_MIDI + int m_runningNotes[NumKeys]; +#endif + + friend class Lv2InsView; +}; + + +class Lv2InsView : public InstrumentView, public Lv2ViewBase +{ + Q_OBJECT +public: + Lv2InsView(Lv2Instrument *_instrument, QWidget *_parent); + +protected: + void dragEnterEvent(QDragEnterEvent *_dee) override; + void dropEvent(QDropEvent *_de) override; + +private slots: + void reloadPlugin(); + void toggleUI(); + +private: + void modelChanged() override; +}; + + +#endif // LV2_INSTRUMENT_H diff --git a/plugins/Lv2Instrument/logo.png b/plugins/Lv2Instrument/logo.png new file mode 100644 index 00000000000..c423ccea458 Binary files /dev/null and b/plugins/Lv2Instrument/logo.png differ diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index e31c2450826..b3181af241a 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -30,7 +30,10 @@ #include #include +#include #include +#include +#include #include "MidiImport.h" #include "TrackContainer.h" @@ -45,11 +48,14 @@ #include "MidiTime.h" #include "debug.h" #include "Song.h" +#include "FxMixer.h" +#include "stdshims.h" #include "embed.h" #include "plugin_export.h" #include "portsmf/allegro.h" +#include "portsmf/algsmfrd_internal.h" #define makeID(_c0, _c1, _c2, _c3) \ ( 0 | \ @@ -94,7 +100,7 @@ MidiImport::~MidiImport() -bool MidiImport::tryImport( TrackContainer* tc ) +bool MidiImport::tryImport(TrackContainer* tc, QJsonValue config) { if( openFile() == false ) { @@ -103,7 +109,7 @@ bool MidiImport::tryImport( TrackContainer* tc ) #ifdef LMMS_HAVE_FLUIDSYNTH if( gui != NULL && - ConfigManager::inst()->defaultSoundfont().isEmpty() ) + ConfigManager::inst()->sf2File().isEmpty() ) { QMessageBox::information( gui->mainWindow(), tr( "Setup incomplete" ), @@ -127,6 +133,8 @@ bool MidiImport::tryImport( TrackContainer* tc ) } #endif + m_settings = config.toObject().value(QStringLiteral("MidiImportPreset")).toObject(); + switch( readID() ) { case makeID( 'M', 'T', 'h', 'd' ): @@ -153,14 +161,12 @@ class smfMidiCC public: smfMidiCC() : at( NULL ), - ap( NULL ), - lastPos( 0 ) - { } - + ap( NULL ) + {} + AutomationTrack * at; AutomationPattern * ap; - MidiTime lastPos; - + smfMidiCC & create( TrackContainer* tc, QString tn ) { if( !at ) @@ -182,31 +188,59 @@ class smfMidiCC { at = NULL; ap = NULL; - lastPos = 0; } smfMidiCC & putValue( MidiTime time, AutomatableModel * objModel, float value ) { - if( !ap || time > lastPos + DefaultTicksPerTact ) + if (!ap) { - MidiTime pPos = MidiTime( time.getTact(), 0 ); ap = dynamic_cast( at->createTCO(0) ); - ap->movePosition( pPos ); + ap->movePosition(0); ap->addObject( objModel ); } - lastPos = time; - time = time - ap->startPosition(); ap->putValue( time, value, false ); - ap->changeLength( MidiTime( time.getTact() + 1, 0 ) ); + ap->changeLength( MidiTime( time.getBar() + 1, 0 ) ); return *this; } }; +class smfTrackMapping +{ +public: + smfTrackMapping() : +#ifdef LMMS_HAVE_FLUIDSYNTH + instrumentName(QStringLiteral("sf2player")), +#else + instrumentName(QStringLiteral("patman")), +#endif + fxChannel(0) + {} + + void parse(QJsonObject mapping) + { +#ifdef LMMS_HAVE_FLUIDSYNTH + instrumentName = mapping.value("instrument").toString("sf2player"); +#else + instrumentName = mapping.value("instrument").toString("patman"); +#endif + + fileName = mapping.value("file").toString(""); + presetFileName = mapping.value("presetFile").toString(""); + pluginPresetFileName = mapping.value("pluginPresetFile").toString(""); + fxChannel = mapping.value("fxChannel").toInt(0); + } + QString instrumentName; + QString fileName; + QString presetFileName; + QString pluginPresetFileName; + int fxChannel; +}; + class smfMidiChannel { @@ -217,8 +251,7 @@ class smfMidiChannel p( NULL ), it_inst( NULL ), isSF2( false ), - hasNotes( false ), - lastEnd( 0 ) + hasNotes( false ) { } InstrumentTrack * it; @@ -226,40 +259,57 @@ class smfMidiChannel Instrument * it_inst; bool isSF2; bool hasNotes; - MidiTime lastEnd; - QString trackName; - smfMidiChannel * create( TrackContainer* tc, QString tn ) + smfMidiChannel * create(TrackContainer* tc, QString tn, const smfTrackMapping& mapping) { if( !it ) { // Keep LMMS responsive qApp->processEvents(); it = dynamic_cast( Track::create( Track::InstrumentTrack, tc ) ); + it_inst = it->loadInstrument(mapping.instrumentName); + #ifdef LMMS_HAVE_FLUIDSYNTH - it_inst = it->loadInstrument( "sf2player" ); - - if( it_inst ) + if (mapping.instrumentName == QStringLiteral("sf2player")) { isSF2 = true; - it_inst->loadFile( ConfigManager::inst()->defaultSoundfont() ); + it_inst->loadFile( ConfigManager::inst()->sf2File() ); it_inst->childModel( "bank" )->setValue( 0 ); it_inst->childModel( "patch" )->setValue( 0 ); } - else - { - it_inst = it->loadInstrument( "patman" ); - } -#else - it_inst = it->loadInstrument( "patman" ); #endif - trackName = tn; - if( trackName != "") { + if (!mapping.fileName.isEmpty()) + { + it_inst->loadFile(mapping.fileName); + } + if (!mapping.presetFileName.isEmpty()) + { + DataFile dataFile(mapping.presetFileName); + InstrumentTrack::removeMidiPortNode(dataFile); + it->setSimpleSerializing(); + it->loadSettings(dataFile.content().toElement()); + } + if (!mapping.pluginPresetFileName.isEmpty()) + { + it_inst->loadPluginPresetFile(mapping.pluginPresetFileName); + } + if( tn != "") { it->setName( tn ); } - lastEnd = 0; // General MIDI default it->pitchRangeModel()->setInitValue( 2 ); + bool overrideFxChannel = false; + int fxOverrideChannel = ConfigManager::inst()->value("tmp", "midifxch").toInt(&overrideFxChannel); + if (overrideFxChannel && fxOverrideChannel >= 0 && fxOverrideChannel <= Engine::fxMixer()->numChannels()) + { + it->effectChannelModel()->setInitValue(fxOverrideChannel); + } + else if (mapping.fxChannel <= Engine::fxMixer()->numChannels()) + { + it->effectChannelModel()->setInitValue(mapping.fxChannel); + } + // Create a default pattern + p = dynamic_cast(it->createTCO(0)); } return this; } @@ -267,77 +317,136 @@ class smfMidiChannel void addNote( Note & n ) { - if( !p || n.pos() > lastEnd + DefaultTicksPerTact ) + if (!p) { - MidiTime pPos = MidiTime( n.pos().getTact(), 0 ); - p = dynamic_cast( it->createTCO( 0 ) ); - p->movePosition( pPos ); + p = dynamic_cast(it->createTCO(0)); } + p->addNote(n, false); hasNotes = true; - lastEnd = n.pos() + n.length(); - n.setPos( n.pos( p->startPosition() ) ); - p->addNote( n, false ); + } + + void splitPatterns() + { + Pattern * newPattern = nullptr; + MidiTime lastEnd(0); + + p->rearrangeAllNotes(); + for (auto n : p->notes()) + { + if (!newPattern || n->pos() > lastEnd + DefaultTicksPerBar) + { + MidiTime pPos = MidiTime(n->pos().getBar(), 0); + newPattern = dynamic_cast(it->createTCO(0)); + newPattern->movePosition(pPos); + } + lastEnd = n->pos() + n->length(); + + Note newNote(*n); + newNote.setPos(n->pos(newPattern->startPosition())); + newPattern->addNote(newNote, false); + } + + delete p; + p = nullptr; } }; +static std::map s_trackCache{}; + + bool MidiImport::readSMF( TrackContainer* tc ) { - + std::unique_ptr pd; const int preTrackSteps = 2; - QProgressDialog pd( TrackContainer::tr( "Importing MIDI-file..." ), - TrackContainer::tr( "Cancel" ), 0, preTrackSteps, gui->mainWindow() ); - pd.setWindowTitle( TrackContainer::tr( "Please wait..." ) ); - pd.setWindowModality(Qt::WindowModal); - pd.setMinimumDuration( 0 ); - - pd.setValue( 0 ); std::stringstream stream; QByteArray arr = readAllData(); stream.str(std::string(arr.constData(), arr.size())); - Alg_seq_ptr seq = new Alg_seq(stream, true); + Alg_seq_ptr seq = new Alg_seq(); + seq->channel_offset_per_track = 4096; // to separate tracks + alg_smf_read(stream, seq); + seq->convert_to_beats(); - pd.setMaximum( seq->tracks() + preTrackSteps ); - pd.setValue( 1 ); - - // 128 CC + Pitch Bend - smfMidiCC ccs[129]; - smfMidiChannel chs[256]; + if (gui) + { + pd = std::move(make_unique(TrackContainer::tr("Importing MIDI-file..."), + TrackContainer::tr("Cancel"), 0, preTrackSteps, gui->mainWindow())); + pd->setWindowTitle( TrackContainer::tr( "Please wait..." ) ); + pd->setWindowModality(Qt::WindowModal); + pd->setMinimumDuration( 0 ); + + pd->setValue( 0 ); + + pd->setMaximum( seq->tracks() + preTrackSteps ); + pd->setValue( 1 ); + } + + smfMidiCC ccs[129]; // 128 CC + Pitch Bend + std::map chs; + std::map mappings; + smfTrackMapping defaultMapping; MeterModel & timeSigMM = Engine::getSong()->getTimeSigModel(); - AutomationPattern * timeSigNumeratorPat = - AutomationPattern::globalAutomationPattern( &timeSigMM.numeratorModel() ); - AutomationPattern * timeSigDenominatorPat = - AutomationPattern::globalAutomationPattern( &timeSigMM.denominatorModel() ); + AutomationTrack * nt = dynamic_cast( + Track::create(Track::AutomationTrack, Engine::getSong())); + nt->setName(tr("MIDI Time Signature Numerator")); + AutomationTrack * dt = dynamic_cast( + Track::create(Track::AutomationTrack, Engine::getSong())); + dt->setName(tr("MIDI Time Signature Denominator")); + AutomationPattern * timeSigNumeratorPat = + new AutomationPattern(nt); + timeSigNumeratorPat->setDisplayName(tr("Numerator")); + timeSigNumeratorPat->addObject(&timeSigMM.numeratorModel()); + AutomationPattern * timeSigDenominatorPat = + new AutomationPattern(dt); + timeSigDenominatorPat->setDisplayName(tr("Denominator")); + timeSigDenominatorPat->addObject(&timeSigMM.denominatorModel()); // TODO: adjust these to Time.Sig changes - double beatsPerTact = 4; - double ticksPerBeat = DefaultTicksPerTact / beatsPerTact; + double beatsPerBar = 4; + double ticksPerBeat = DefaultTicksPerBar / beatsPerBar; - // Time-sig changes - Alg_time_sigs * timeSigs = &seq->time_sig; - for( int s = 0; s < timeSigs->length(); ++s ) + // parse mappings + for (auto mapping : m_settings.value("mapping").toArray()) { - Alg_time_sig timeSig = (*timeSigs)[s]; - // Initial timeSig, set song-default value - if(/* timeSig.beat == 0*/ true ) + int channel = mapping.toObject().value("channel").toInt() - 1; + if (channel >= 0) { - // TODO set song-global default value - printf("Another timesig at %f\n", timeSig.beat); - timeSigNumeratorPat->putValue( timeSig.beat*ticksPerBeat, timeSig.num ); - timeSigDenominatorPat->putValue( timeSig.beat*ticksPerBeat, timeSig.den ); + mappings[channel].parse(mapping.toObject()); } else { + defaultMapping.parse(mapping.toObject()); } + } + auto mappingForChannel = [&mappings, &defaultMapping](int index) { + return mappings.count(index) ? mappings[index] : defaultMapping; + }; + // Load track cache if enabled + if (ConfigManager::inst()->value("tmp", "midiimportcache").toInt(0)) + { + using std::swap; + swap(chs, s_trackCache); + } + + // Time-sig changes + Alg_time_sigs * timeSigs = &seq->time_sig; + for( int s = 0; s < timeSigs->length(); ++s ) + { + Alg_time_sig timeSig = (*timeSigs)[s]; + timeSigNumeratorPat->putValue(timeSig.beat * ticksPerBeat, timeSig.num); + timeSigDenominatorPat->putValue(timeSig.beat * ticksPerBeat, timeSig.den); } + // manually call otherwise the pattern shows being 1 bar + timeSigNumeratorPat->updateLength(); + timeSigDenominatorPat->updateLength(); - pd.setValue( 2 ); + if (pd.get()) {pd->setValue(2);} // Tempo stuff AutomationPattern * tap = tc->tempoAutomationPattern(); @@ -349,14 +458,17 @@ bool MidiImport::readSMF( TrackContainer* tc ) for( int i = 0; i < beats.len - 1; i++ ) { Alg_beat_ptr b = &(beats[i]); + if (beats[i + 1].time == beats[i].time) { continue; } double tempo = ( beats[i + 1].beat - b->beat ) / ( beats[i + 1].time - beats[i].time ); - tap->putValue( b->beat * ticksPerBeat, tempo * 60.0 ); + tap->putValue( b->beat * ticksPerBeat, round(tempo * 60.0) ); + if (b->beat == 0) { Engine::getSong()->setTempo(round(tempo * 60.0)); } } if( timeMap->last_tempo_flag ) { Alg_beat_ptr b = &( beats[beats.len - 1] ); - tap->putValue( b->beat * ticksPerBeat, timeMap->last_tempo * 60.0 ); + tap->putValue( b->beat * ticksPerBeat, round(timeMap->last_tempo * 60.0) ); + if (b->beat == 0) { Engine::getSong()->setTempo(round(timeMap->last_tempo * 60.0)); } } } @@ -381,7 +493,7 @@ bool MidiImport::readSMF( TrackContainer* tc ) { QString trackName = QString( tr( "Track" ) + " %1" ).arg( t ); Alg_track_ptr trk = seq->track( t ); - pd.setValue( t + preTrackSteps ); + if (pd.get()) {pd->setValue(t + preTrackSteps);} for( int c = 0; c < 129; c++ ) { @@ -420,22 +532,23 @@ bool MidiImport::readSMF( TrackContainer* tc ) printf( "\n" ); } } - else if( evt->is_note() && evt->chan < 256 ) + else if( evt->is_note() ) { - smfMidiChannel * ch = chs[evt->chan].create( tc, trackName ); + smfMidiChannel * ch = chs[evt->chan].create(tc, trackName, mappingForChannel(evt->chan)); Alg_note_ptr noteEvt = dynamic_cast( evt ); int ticks = noteEvt->get_duration() * ticksPerBeat; + int pitchCorrection = ch->it_inst->flags() & Instrument::IsMidiBased ? 0 : -12; Note n( (ticks < 1 ? 1 : ticks ), noteEvt->get_start_time() * ticksPerBeat, - noteEvt->get_identifier() - 12, - noteEvt->get_loud() * (200.f / 127.f)); // Map from MIDI velocity to LMMS volume + noteEvt->get_identifier() + pitchCorrection, + std::round(noteEvt->get_loud() * (200.f / 127.f))); // Map from MIDI velocity to LMMS volume ch->addNote( n ); - + } else if( evt->is_update() ) { - smfMidiChannel * ch = chs[evt->chan].create( tc, trackName ); + smfMidiChannel * ch = chs[evt->chan].create(tc, trackName, mappingForChannel(evt->chan)); double time = evt->time*ticksPerBeat; QString update( evt->get_attribute() ); @@ -497,10 +610,13 @@ bool MidiImport::readSMF( TrackContainer* tc ) case 128: objModel = ch->it->pitchModel(); - cc = cc * 100.0f; + //cc = cc * 100.0f; + cc = cc * 100.0f * ch->it->pitchRangeModel()->value(); break; default: - //TODO: something useful for other CCs + ch->it->m_midiCCEnable->setValue(true); + objModel = ch->it->m_midiCCModel[ccid]; + cc = cc * 127.0f; break; } @@ -520,9 +636,15 @@ bool MidiImport::readSMF( TrackContainer* tc ) } ccs[ccid].putValue( time, objModel, cc ); } + emit objModel->dataChanged(); } } } + else if (update == "tracknames" && evt->get_update_type() == 's') + { + const char * name = evt->get_string_value(); + if (name) {ch->it->setName(name);} + } else { printf("Unhandled update: %d %d %f %s\n", (int) evt->chan, evt->get_type_code(), evt->time, evt->get_attribute() ); @@ -534,9 +656,14 @@ bool MidiImport::readSMF( TrackContainer* tc ) delete seq; - for( int c=0; c < 256; ++c ) + for (auto channelPair : chs) { - if( !chs[c].hasNotes && chs[c].it ) + const auto c = channelPair.first; + if (chs[c].hasNotes) + { + chs[c].splitPatterns(); + } + else if (chs[c].it) { printf(" Should remove empty track\n"); // must delete trackView first - but where is it? @@ -545,6 +672,7 @@ bool MidiImport::readSMF( TrackContainer* tc ) } } + // FIXME this can be 9+alpha, or sometimes unable to detect // Set channel 10 to drums as per General MIDI's orders if( chs[9].hasNotes && chs[9].it_inst && chs[9].isSF2 ) { @@ -554,6 +682,12 @@ bool MidiImport::readSMF( TrackContainer* tc ) chs[9].it_inst->childModel( "patch" )->setValue( 0 ); } + // store track cache + { + using std::swap; + swap(chs, s_trackCache); + } + return true; } diff --git a/plugins/MidiImport/MidiImport.h b/plugins/MidiImport/MidiImport.h index 88bda9bb51f..ba394b525aa 100644 --- a/plugins/MidiImport/MidiImport.h +++ b/plugins/MidiImport/MidiImport.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "MidiEvent.h" #include "ImportFilter.h" @@ -47,7 +49,7 @@ class MidiImport : public ImportFilter private: - virtual bool tryImport( TrackContainer* tc ); + virtual bool tryImport(TrackContainer* tc, QJsonValue config = QJsonValue()); bool readSMF( TrackContainer* tc ); bool readRIFF( TrackContainer* tc ); @@ -121,6 +123,7 @@ class MidiImport : public ImportFilter typedef QVector > EventVector; EventVector m_events; int m_timingDivision; + QJsonObject m_settings; } ; diff --git a/plugins/MidiImport/portsmf/allegrosmfrd.cpp b/plugins/MidiImport/portsmf/allegrosmfrd.cpp index 49e2ef03ee6..56a36823b27 100644 --- a/plugins/MidiImport/portsmf/allegrosmfrd.cpp +++ b/plugins/MidiImport/portsmf/allegrosmfrd.cpp @@ -6,6 +6,8 @@ #include "debug.h" #include #include +#include +#include #include "allegro.h" #include "algsmfrd_internal.h" #include "mfmidi.h" @@ -13,21 +15,12 @@ using namespace std; -typedef class Alg_pending { -public: - Alg_note_ptr note; - class Alg_pending *next; - Alg_pending(Alg_note_ptr n, class Alg_pending *list) { - note = n; next = list; } -} *Alg_pending_ptr; - - class Alg_midifile_reader: public Midifile_reader { public: istream *file; Alg_seq_ptr seq; int divisions; - Alg_pending_ptr pending; + std::list pending; Alg_track_ptr track; int track_number; // the number of the (current) track // chan is actual_channel + channel_offset_per_track * track_num + @@ -41,7 +34,6 @@ class Alg_midifile_reader: public Midifile_reader { Alg_midifile_reader(istream &f, Alg_seq_ptr new_seq) { file = &f; - pending = NULL; seq = new_seq; channel_offset_per_track = 0; channel_offset_per_port = 16; @@ -99,11 +91,6 @@ class Alg_midifile_reader: public Midifile_reader { Alg_midifile_reader::~Alg_midifile_reader() { - while (pending) { - Alg_pending_ptr to_be_freed = pending; - pending = pending->next; - delete to_be_freed; - } finalize(); // free Mf reader memory } @@ -201,7 +188,7 @@ void Alg_midifile_reader::Mf_on(int chan, int key, int vel) return; } Alg_note_ptr note = new Alg_note(); - pending = new Alg_pending(note, pending); + pending.push_back(note); /* trace("on: %d at %g\n", key, get_time()); */ note->time = get_time(); note->chan = chan + channel_offset + port * channel_offset_per_port; @@ -217,19 +204,15 @@ void Alg_midifile_reader::Mf_on(int chan, int key, int vel) void Alg_midifile_reader::Mf_off(int chan, int key, int vel) { double time = get_time(); - Alg_pending_ptr *p = &pending; - while (*p) { - if ((*p)->note->get_identifier() == key && - (*p)->note->chan == - chan + channel_offset + port * channel_offset_per_port) { - (*p)->note->dur = time - (*p)->note->time; - // trace("updated %d dur %g\n", (*p)->note->key, (*p)->note->dur); - Alg_pending_ptr to_be_freed = *p; - *p = to_be_freed->next; - delete to_be_freed; - } else { - p = &((*p)->next); - } + auto it = std::find_if(pending.begin(), pending.end(), [=](Alg_note_ptr note){ + return note->get_identifier() == key && + note->chan == chan + channel_offset + port * channel_offset_per_port; + }); + if (it != pending.end()) { + Alg_note_ptr note = *it; + note->dur = time - note->time; + pending.erase(it); + // trace("updated %d dur %g\n", note->key, note->dur); } meta_channel = -1; } diff --git a/plugins/MixSetup/CMakeLists.txt b/plugins/MixSetup/CMakeLists.txt new file mode 100644 index 00000000000..caa2858c90f --- /dev/null +++ b/plugins/MixSetup/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(mixsetup MixSetup.cpp MOCFILES MixSetup.h) diff --git a/plugins/MixSetup/MixSetup.cpp b/plugins/MixSetup/MixSetup.cpp new file mode 100644 index 00000000000..3b9c694e7ab --- /dev/null +++ b/plugins/MixSetup/MixSetup.cpp @@ -0,0 +1,214 @@ +/* + * MixSetup.cpp - A sample scripting plugin + * + * Copyright (c) 2019 - 2020 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "MixSetup.h" + +#include "embed.h" +#include "plugin_export.h" + +#include "Effect.h" +#include "EffectChain.h" +#include "Engine.h" +#include "FxMixer.h" +#include "Song.h" + +#include +#include +#include +#include +#include + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT mixsetup_plugin_descriptor = +{ + STRINGIFY(PLUGIN_NAME), + "MixSetup", + QT_TRANSLATE_NOOP("pluginBrowser", "A sample scripting plugin"), + "Hyunjin Song ", + 0x0100, + Plugin::Scripting, + new PluginPixmapLoader("logo"), + NULL, + NULL +} ; + +} + + + +MixSetup::MixSetup(Model* parent, const Descriptor::SubPluginFeatures::Key* key) : + ScriptPlugin(&mixsetup_plugin_descriptor, parent, key) +{ +} + + + +MixSetup::~MixSetup() +{ +} + + + +void MixSetup::evaluateScript(const QString & scriptName, const QString & scriptContent) +{ + QJsonParseError err; + QJsonDocument doc = QJsonDocument::fromJson(scriptContent.toUtf8(), &err); + if (err.error != QJsonParseError::NoError) + { + qWarning().noquote() << QStringLiteral("Failed to parse \"%1\" as a JSON file: \"%2\".").arg(scriptName).arg(err.errorString()); + return; + } + if (!doc.isObject()) + { + qWarning("Bad input data format."); + return; + } + + Engine::getSong()->clearProject(); + + QJsonObject obj = doc.object(); + QString fileToLoad = obj["basefile"].toString(); + if (!fileToLoad.isEmpty()) + { + Engine::getSong()->loadProject(fileToLoad); + } + + QJsonArray chs = obj["channels"].toArray(); + + qInfo("Processing %d FX channels...", chs.size()); + for (auto val : chs) + { + if (!val.isObject()) + { + qWarning("Channel descriptor is not an object."); + continue; + } + + QJsonObject chData = val.toObject(); + int idx = chData["index"].toInt(-1); + if (idx < 0) + { + qWarning("Invalid channel index %d.", idx); + continue; + } + + // ensure the target FX channel exists + for (int n = idx + 1 - Engine::fxMixer()->numChannels(); n > 0; --n) + { + Engine::fxMixer()->createChannel(); + } + + // reset the channel if requested + if (chData["clear"].toBool(false)) + { + Engine::fxMixer()->clearChannel(idx); + } + + QJsonArray effects = chData["effects"].toArray(); + qInfo("Processing %d effects for channel %d...", effects.size(), idx); + + EffectChain & fxChain = Engine::fxMixer()->effectChannel(idx)->m_fxChain; + for (auto val2 : effects) + { + if (!val2.isObject()) + { + qWarning("Effect descriptor is not an object."); + continue; + } + QJsonObject effectData = val2.toObject(); + + QString effectName = effectData["name"].toString(); + if (effectName.isEmpty()) {continue;} + + Plugin::Descriptor::SubPluginFeatures::Key key; + // XXX why do I need this 'class'? + class Effect * e = Effect::instantiate(effectData["name"].toString(), &fxChain, &key); + if (e) + { + QString fileName = effectData["file"].toString(""); + if (!fileName.isEmpty()) {e->loadFile(fileName);} + /* + // TODO effect presets are not implemented yet + QString presetFileName = effectData["presetFile"].toString(""); + */ + QString pluginPresetFileName = effectData["pluginPresetFile"].toString(""); + if (!pluginPresetFileName.isEmpty()) {e->loadPluginPresetFile(pluginPresetFileName);} + fxChain.appendEffect(e); + } + else + { + qWarning().noquote() << QStringLiteral("Failed to add effect \"%1\"").arg(effectName); + } + } + } + + QString fileToSave = obj["savefile"].toString(); + if (!fileToSave.isEmpty()) + { + bool result = Engine::getSong()->saveProjectFile(fileToSave); + if (!result) + { + qWarning("Failed to save the result."); + return; + } + } + QCoreApplication::processEvents(); + qInfo("Done."); +} + + + + +void MixSetup::saveSettings(QDomDocument & doc, QDomElement & element) +{ +} + + + +void MixSetup::loadSettings(const QDomElement & element) +{ +} + + + +PluginView * MixSetup::instantiateView(QWidget * parent) +{ + return nullptr; +} + + + +extern "C" +{ + +// necessary for getting instance out of shared lib +PLUGIN_EXPORT Plugin * lmms_plugin_main(Model* parent, void* data) +{ + return new MixSetup(parent, static_cast(data)); +} + +} + diff --git a/plugins/MixSetup/MixSetup.h b/plugins/MixSetup/MixSetup.h new file mode 100644 index 00000000000..831d5274e49 --- /dev/null +++ b/plugins/MixSetup/MixSetup.h @@ -0,0 +1,45 @@ +/* + * MixSetup.h - a sample scripting plugin + * + * Copyright (c) 2019 - 2020 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef SCRIPTSAMPLE_H +#define SCRIPTSAMPLE_H + +#include "ScriptPlugin.h" + +class MixSetup : public ScriptPlugin +{ +public: + MixSetup( Model* parent, const Descriptor::SubPluginFeatures::Key* key ); + virtual ~MixSetup(); + + void evaluateScript(const QString & scriptName, const QString & scriptContent) override; + + void saveSettings(QDomDocument & doc, QDomElement & element) override; + void loadSettings(const QDomElement & element) override; + + PluginView * instantiateView(QWidget * parent) override; +}; + +#endif diff --git a/plugins/OpulenZ/OpulenZ.cpp b/plugins/OpulenZ/OpulenZ.cpp index 8e5b7f098ca..4dde05b0f3b 100644 --- a/plugins/OpulenZ/OpulenZ.cpp +++ b/plugins/OpulenZ/OpulenZ.cpp @@ -681,7 +681,7 @@ void OpulenzInstrument::loadFile( const QString& file ) { OpulenzInstrumentView::OpulenzInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { #define KNOB_GEN(knobname, hinttext, hintunit,xpos,ypos) \ diff --git a/plugins/OpulenZ/OpulenZ.h b/plugins/OpulenZ/OpulenZ.h index e69c278efc9..2273b355aff 100644 --- a/plugins/OpulenZ/OpulenZ.h +++ b/plugins/OpulenZ/OpulenZ.h @@ -142,7 +142,7 @@ private slots: -class OpulenzInstrumentView : public InstrumentView +class OpulenzInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/SpectrumAnalyzer/Analyzer.cpp b/plugins/SpectrumAnalyzer/Analyzer.cpp new file mode 100644 index 00000000000..656d18bd4d6 --- /dev/null +++ b/plugins/SpectrumAnalyzer/Analyzer.cpp @@ -0,0 +1,118 @@ +/* + * Analyzer.cpp - definition of Analyzer class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014-2017, David French + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Analyzer.h" + +#ifdef SA_DEBUG + #include + #include +#endif + +#include "embed.h" +#include "lmms_basics.h" +#include "plugin_export.h" + + +extern "C" { + Plugin::Descriptor PLUGIN_EXPORT analyzer_plugin_descriptor = + { + "spectrumanalyzer", + "Spectrum Analyzer", + QT_TRANSLATE_NOOP("pluginBrowser", "A graphical spectrum analyzer."), + "Martin Pavelek ", + 0x0112, + Plugin::Effect, + new PluginPixmapLoader("logo"), + NULL, + NULL + }; +} + + +Analyzer::Analyzer(Model *parent, const Plugin::Descriptor::SubPluginFeatures::Key *key) : + Effect(&analyzer_plugin_descriptor, parent, key), + m_processor(&m_controls), + m_controls(this), + m_processorThread(m_processor, m_inputBuffer), + // Buffer is sized to cover 4* the current maximum LMMS audio buffer size, + // so that it has some reserve space in case data processor is busy. + m_inputBuffer(4 * m_maxBufferSize) +{ + m_processorThread.start(); +} + + +Analyzer::~Analyzer() +{ + m_processor.terminate(); + m_inputBuffer.wakeAll(); + m_processorThread.wait(); +} + +// Take audio data and pass them to the spectrum processor. +bool Analyzer::processAudioBuffer(sampleFrame *buffer, const fpp_t frame_count) +{ + // Measure time spent in audio thread; both average and peak should be well under 1 ms. + #ifdef SA_DEBUG + unsigned int audio_time = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + if (audio_time - m_last_dump_time > 5000000000) // print every 5 seconds + { + std::cout << "Analyzer audio thread: " << m_sum_execution / m_dump_count << " ms avg / " + << m_max_execution << " ms peak." << std::endl; + m_last_dump_time = audio_time; + m_sum_execution = m_max_execution = m_dump_count = 0; + } + #endif + + if (!isEnabled() || !isRunning ()) {return false;} + + // Skip processing if the controls dialog isn't visible, it would only waste CPU cycles. + if (m_controls.isViewVisible()) + { + // To avoid processing spikes on audio thread, data are stored in + // a lockless ringbuffer and processed in a separate thread. + m_inputBuffer.write(buffer, frame_count, true); + } + #ifdef SA_DEBUG + audio_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - audio_time; + m_dump_count++; + m_sum_execution += audio_time / 1000000.0; + if (audio_time / 1000000.0 > m_max_execution) {m_max_execution = audio_time / 1000000.0;} + #endif + + return isRunning(); +} + + +extern "C" { + // needed for getting plugin out of shared lib + PLUGIN_EXPORT Plugin *lmms_plugin_main(Model *parent, void *data) + { + return new Analyzer(parent, static_cast(data)); + } +} + diff --git a/plugins/SpectrumAnalyzer/Analyzer.h b/plugins/SpectrumAnalyzer/Analyzer.h new file mode 100644 index 00000000000..304777c9a09 --- /dev/null +++ b/plugins/SpectrumAnalyzer/Analyzer.h @@ -0,0 +1,75 @@ +/* Analyzer.h - declaration of Analyzer class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014-2017, David French + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef ANALYZER_H +#define ANALYZER_H + +#include + +#include "DataprocLauncher.h" +#include "Effect.h" +#include "LocklessRingBuffer.h" +#include "SaControls.h" +#include "SaProcessor.h" + + +//! Top level class; handles LMMS interface and feeds data to the data processor. +class Analyzer : public Effect +{ +public: + Analyzer(Model *parent, const Descriptor::SubPluginFeatures::Key *key); + virtual ~Analyzer(); + + bool processAudioBuffer(sampleFrame *buffer, const fpp_t frame_count) override; + EffectControls *controls() override {return &m_controls;} + + SaProcessor *getProcessor() {return &m_processor;} + +private: + SaProcessor m_processor; + SaControls m_controls; + + // Maximum LMMS buffer size (hard coded, the actual constant is hard to get) + const unsigned int m_maxBufferSize = 4096; + + // QThread::create() workaround + // Replace DataprocLauncher by QThread and replace initializer in constructor + // with the following commented line when LMMS CI starts using Qt > 5.9 + //m_processorThread = QThread::create([=]{m_processor.analyze(m_inputBuffer);}); + DataprocLauncher m_processorThread; + + LocklessRingBuffer m_inputBuffer; + + #ifdef SA_DEBUG + int m_last_dump_time; + int m_dump_count; + float m_sum_execution; + float m_max_execution; + #endif +}; + +#endif // ANALYZER_H + diff --git a/plugins/SpectrumAnalyzer/CMakeLists.txt b/plugins/SpectrumAnalyzer/CMakeLists.txt index 29187b39d99..488495a9e3d 100644 --- a/plugins/SpectrumAnalyzer/CMakeLists.txt +++ b/plugins/SpectrumAnalyzer/CMakeLists.txt @@ -1,4 +1,7 @@ INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${FFTW3F_INCLUDE_DIRS}) + LINK_LIBRARIES(${FFTW3F_LIBRARIES}) -BUILD_PLUGIN(spectrumanalyzer SpectrumAnalyzer.cpp SpectrumAnalyzerControls.cpp SpectrumAnalyzerControlDialog.cpp SpectrumAnalyzer.h SpectrumAnalyzerControls.h SpectrumAnalyzerControlDialog.h MOCFILES SpectrumAnalyzerControlDialog.h SpectrumAnalyzerControls.h EMBEDDED_RESOURCES *.png) + +BUILD_PLUGIN(analyzer Analyzer.cpp SaProcessor.cpp SaControls.cpp SaControlsDialog.cpp SaSpectrumView.cpp SaWaterfallView.cpp +MOCFILES SaProcessor.h SaControls.h SaControlsDialog.h SaSpectrumView.h SaWaterfallView.h DataprocLauncher.h EMBEDDED_RESOURCES *.svg logo.png) diff --git a/plugins/SpectrumAnalyzer/DataprocLauncher.h b/plugins/SpectrumAnalyzer/DataprocLauncher.h new file mode 100644 index 00000000000..d91e0bedfcc --- /dev/null +++ b/plugins/SpectrumAnalyzer/DataprocLauncher.h @@ -0,0 +1,52 @@ +/* + * DataprocLauncher.h - QThread::create workaround for older Qt version + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef DATAPROCLAUNCHER_H +#define DATAPROCLAUNCHER_H + +#include + +#include "SaProcessor.h" +#include "LocklessRingBuffer.h" + +class DataprocLauncher : public QThread +{ +public: + explicit DataprocLauncher(SaProcessor &proc, LocklessRingBuffer &buffer) + : m_processor(&proc), + m_inputBuffer(&buffer) + { + } + +private: + void run() override + { + m_processor->analyze(*m_inputBuffer); + } + + SaProcessor *m_processor; + LocklessRingBuffer *m_inputBuffer; +}; + +#endif // DATAPROCLAUNCHER_H diff --git a/plugins/SpectrumAnalyzer/README.md b/plugins/SpectrumAnalyzer/README.md new file mode 100644 index 00000000000..473083da81e --- /dev/null +++ b/plugins/SpectrumAnalyzer/README.md @@ -0,0 +1,47 @@ +# Spectrum Analyzer plugin + +## Overview + +This plugin consists of three widgets and back-end code to provide them with required data. + +The top-level widget is `SaControlDialog`. It populates configuration widgets (created dynamically) and instantiates spectrum display widgets. Its main back-end class is `SaControls`, which holds all configuration values. + +`SaSpectrumView` and `SaWaterfallView` widgets show the result of spectrum analysis. Their main back-end class is `SaProcessor`, which performs FFT analysis on data received from the `Analyzer` class, which in turn handles the interface with LMMS. + +## Threads + +The Spectrum Analyzer is involved in three different threads: + - **Effect mixer thread**: periodically calls `Analyzer::processAudioBuffer()` to provide the plugin with more data. This thread is real-time sensitive -- any latency spikes can potentially cause interruptions in the audio stream. For this reason, `Analyzer::processAudioBuffer()` must finish as fast as possible and must not call any functions that could cause it to be delayed for unpredictable amount of time. A lock-less ring buffer is used to safely feed data to the FFT analysis thread without risking any latency spikes due to a shared mutex being unavailable at the time of writing. + - **FFT analysis thread**: a standalone thread formed by the `SaProcessor::analyze()` function. Takes in data from the ring buffer, performs FFT analysis and prepares results for display. This thread is not real-time sensitive but excessive locking is discouraged to maintain good performance. + - **GUI thread**: periodically triggers `paintEvent()` of all Qt widgets, including `SaSpectrumView` and `SaWaterfallView`. While it is not as sensitive to latency spikes as the effect mixer thread, the `paintEvent()`s appear to be called sequentially and the execution time of each widget therefore adds to the total time needed to complete one full refresh cycle. This means the maximum frame rate of the Qt GUI will be limited to `1 / total_execution_time`. Good performance of the `paintEvent()` functions should be therefore kept in mind. + + +## Changelog + 1.1.2 2019-11-18 + - waterfall is no longer cut short when width limit is reached + - various small tweaks based on final review + 1.1.1 2019-10-13 + - improved interface for accessing SaProcessor private data + - readme file update + - other small improvements based on reviews + 1.1.0 2019-08-29 + - advanced config: expose hidden constants to user + - advanced config: add support for FFT window overlapping + - waterfall: display at native resolution on high-DPI screens + - waterfall: add cursor and improve label density + - FFT: fix normalization so that 0 dBFS matches full-scale sinewave + - FFT: decouple data acquisition from processing and display + - FFT: separate lock for reallocation (to avoid some needless waiting) + - moved ranges and other constants to a separate file + - debug: better performance measurements + - various performance optimizations + 1.0.3 2019-07-25 + - rename and tweak amplitude ranges based on feedback + 1.0.2 2019-07-12 + - variety of small changes based on code review + 1.0.1 2019-06-02 + - code style changes + - added tool-tips + - use const for unmodified arrays passed to fft_helpers + 1.0.0 2019-04-07 + - initial release diff --git a/plugins/SpectrumAnalyzer/SaControls.cpp b/plugins/SpectrumAnalyzer/SaControls.cpp new file mode 100644 index 00000000000..6be298e27e4 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaControls.cpp @@ -0,0 +1,176 @@ +/* + * SaControls.cpp - definition of SaControls class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "SaControls.h" + +#include + +#include "Analyzer.h" +#include "SaControlsDialog.h" + + +SaControls::SaControls(Analyzer *effect) : + EffectControls(effect), + m_effect(effect), + + // initialize bool models and set default values + m_pauseModel(false, this, tr("Pause")), + m_refFreezeModel(false, this, tr("Reference freeze")), + + m_waterfallModel(false, this, tr("Waterfall")), + m_smoothModel(false, this, tr("Averaging")), + m_stereoModel(false, this, tr("Stereo")), + m_peakHoldModel(false, this, tr("Peak hold")), + + m_logXModel(true, this, tr("Logarithmic frequency")), + m_logYModel(true, this, tr("Logarithmic amplitude")), + + // default values of combo boxes are set after they are populated + m_freqRangeModel(this, tr("Frequency range")), + m_ampRangeModel(this, tr("Amplitude range")), + m_blockSizeModel(this, tr("FFT block size")), + m_windowModel(this, tr("FFT window type")), + + // Advanced settings knobs + m_envelopeResolutionModel(0.25f, 0.1f, 3.0f, 0.05f, this, tr("Peak envelope resolution")), + m_spectrumResolutionModel(1.5f, 0.1f, 3.0f, 0.05f, this, tr("Spectrum display resolution")), + m_peakDecayFactorModel(0.992f, 0.95f, 0.999f, 0.001f, this, tr("Peak decay multiplier")), + m_averagingWeightModel(0.15f, 0.01f, 0.5f, 0.01f, this, tr("Averaging weight")), + m_waterfallHeightModel(300.0f, 50.0f, 1000.0f, 50.0f, this, tr("Waterfall history size")), + m_waterfallGammaModel(0.30f, 0.10f, 1.00f, 0.05f, this, tr("Waterfall gamma correction")), + m_windowOverlapModel(2.0f, 1.0f, 4.0f, 1.0f, this, tr("FFT window overlap")), + m_zeroPaddingModel(2.0f, 0.0f, 4.0f, 1.0f, this, tr("FFT zero padding")) +{ + // Frequency and amplitude ranges; order must match + // FREQUENCY_RANGES and AMPLITUDE_RANGES defined in SaControls.h + m_freqRangeModel.addItem(tr("Full (auto)")); + m_freqRangeModel.addItem(tr("Audible")); + m_freqRangeModel.addItem(tr("Bass")); + m_freqRangeModel.addItem(tr("Mids")); + m_freqRangeModel.addItem(tr("High")); + m_freqRangeModel.setValue(m_freqRangeModel.findText(tr("Full (auto)"))); + + m_ampRangeModel.addItem(tr("Extended")); + m_ampRangeModel.addItem(tr("Audible")); + m_ampRangeModel.addItem(tr("Loud")); + m_ampRangeModel.addItem(tr("Silent")); + m_ampRangeModel.setValue(m_ampRangeModel.findText(tr("Audible"))); + + // FFT block size labels are generated automatically, based on + // FFT_BLOCK_SIZES vector defined in fft_helpers.h + for (unsigned int i = 0; i < FFT_BLOCK_SIZES.size(); i++) + { + if (i == 0) + { + m_blockSizeModel.addItem((std::to_string(FFT_BLOCK_SIZES[i]) + " ").c_str() + tr("(High time res.)")); + } + else if (i == FFT_BLOCK_SIZES.size() - 1) + { + m_blockSizeModel.addItem((std::to_string(FFT_BLOCK_SIZES[i]) + " ").c_str() + tr("(High freq. res.)")); + } + else + { + m_blockSizeModel.addItem(std::to_string(FFT_BLOCK_SIZES[i]).c_str()); + } + } + m_blockSizeModel.setValue(m_blockSizeModel.findText("2048")); + + // Window type order must match FFT_WINDOWS defined in fft_helpers.h + m_windowModel.addItem(tr("Rectangular (Off)")); + m_windowModel.addItem(tr("Blackman-Harris (Default)")); + m_windowModel.addItem(tr("Hamming")); + m_windowModel.addItem(tr("Hanning")); + m_windowModel.setValue(m_windowModel.findText(tr("Blackman-Harris (Default)"))); + + // Colors + // Background color is defined by Qt / theme. + // Make sure the sum of colors for L and R channel results into a neutral + // color that has at least one component equal to 255 (i.e. ideally white). + // This means the color overflows to zero exactly when signal reaches + // clipping threshold, indicating the problematic frequency to user. + // Mono waterfall color should have similarly at least one component at 255. + m_colorL = QColor(51, 148, 204, 135); + m_colorR = QColor(204, 107, 51, 135); + m_colorMono = QColor(51, 148, 204, 204); + m_colorMonoW = QColor(64, 185, 255, 255); + m_colorBG = QColor(7, 7, 7, 255); // ~20 % gray (after gamma correction) + m_colorGrid = QColor(30, 34, 38, 255); // ~40 % gray (slightly cold / blue) + m_colorLabels = QColor(192, 202, 212, 255); // ~90 % gray (slightly cold / blue) +} + + +// Create the SaControlDialog widget which handles display of GUI elements. +EffectControlDialog* SaControls::createView() +{ + return new SaControlsDialog(this, m_effect->getProcessor()); +} + + +void SaControls::loadSettings(const QDomElement &_this) +{ + m_waterfallModel.loadSettings(_this, "Waterfall"); + m_smoothModel.loadSettings(_this, "Smooth"); + m_stereoModel.loadSettings(_this, "Stereo"); + m_peakHoldModel.loadSettings(_this, "PeakHold"); + m_logXModel.loadSettings(_this, "LogX"); + m_logYModel.loadSettings(_this, "LogY"); + m_freqRangeModel.loadSettings(_this, "RangeX"); + m_ampRangeModel.loadSettings(_this, "RangeY"); + m_blockSizeModel.loadSettings(_this, "BlockSize"); + m_windowModel.loadSettings(_this, "WindowType"); + + m_envelopeResolutionModel.loadSettings(_this, "EnvelopeRes"); + m_spectrumResolutionModel.loadSettings(_this, "SpectrumRes"); + m_peakDecayFactorModel.loadSettings(_this, "PeakDecayFactor"); + m_averagingWeightModel.loadSettings(_this, "AverageWeight"); + m_waterfallHeightModel.loadSettings(_this, "WaterfallHeight"); + m_waterfallGammaModel.loadSettings(_this, "WaterfallGamma"); + m_windowOverlapModel.loadSettings(_this, "WindowOverlap"); + m_zeroPaddingModel.loadSettings(_this, "ZeroPadding"); +} + + +void SaControls::saveSettings(QDomDocument &doc, QDomElement &parent) +{ + m_waterfallModel.saveSettings(doc, parent, "Waterfall"); + m_smoothModel.saveSettings(doc, parent, "Smooth"); + m_stereoModel.saveSettings(doc, parent, "Stereo"); + m_peakHoldModel.saveSettings(doc, parent, "PeakHold"); + m_logXModel.saveSettings(doc, parent, "LogX"); + m_logYModel.saveSettings(doc, parent, "LogY"); + m_freqRangeModel.saveSettings(doc, parent, "RangeX"); + m_ampRangeModel.saveSettings(doc, parent, "RangeY"); + m_blockSizeModel.saveSettings(doc, parent, "BlockSize"); + m_windowModel.saveSettings(doc, parent, "WindowType"); + + m_envelopeResolutionModel.saveSettings(doc, parent, "EnvelopeRes"); + m_spectrumResolutionModel.saveSettings(doc, parent, "SpectrumRes"); + m_peakDecayFactorModel.saveSettings(doc, parent, "PeakDecayFactor"); + m_averagingWeightModel.saveSettings(doc, parent, "AverageWeight"); + m_waterfallHeightModel.saveSettings(doc, parent, "WaterfallHeight"); + m_waterfallGammaModel.saveSettings(doc, parent, "WaterfallGamma"); + m_windowOverlapModel.saveSettings(doc, parent, "WindowOverlap"); + m_zeroPaddingModel.saveSettings(doc, parent, "ZeroPadding"); + +} diff --git a/plugins/SpectrumAnalyzer/SaControls.h b/plugins/SpectrumAnalyzer/SaControls.h new file mode 100644 index 00000000000..ee8a9e001fe --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaControls.h @@ -0,0 +1,97 @@ +/* + * SaControls.h - declaration of SaControls class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef SACONTROLS_H +#define SACONTROLS_H + +#include "ComboBoxModel.h" +#include "EffectControls.h" +#include "lmms_constants.h" + +//#define SA_DEBUG 1 // define SA_DEBUG to enable performance measurements + + +class Analyzer; + +// Holds all the configuration values +class SaControls : public EffectControls +{ + Q_OBJECT +public: + explicit SaControls(Analyzer* effect); + virtual ~SaControls() {} + + EffectControlDialog* createView() override; + + void saveSettings (QDomDocument& doc, QDomElement& parent) override; + void loadSettings (const QDomElement &_this) override; + + QString nodeName() const override {return "Analyzer";} + int controlCount() override {return 20;} + +private: + Analyzer *m_effect; + + // basic settings + BoolModel m_pauseModel; + BoolModel m_refFreezeModel; + + BoolModel m_waterfallModel; + BoolModel m_smoothModel; + BoolModel m_stereoModel; + BoolModel m_peakHoldModel; + + BoolModel m_logXModel; + BoolModel m_logYModel; + + ComboBoxModel m_freqRangeModel; + ComboBoxModel m_ampRangeModel; + ComboBoxModel m_blockSizeModel; + ComboBoxModel m_windowModel; + + // advanced settings + FloatModel m_envelopeResolutionModel; + FloatModel m_spectrumResolutionModel; + FloatModel m_peakDecayFactorModel; + FloatModel m_averagingWeightModel; + FloatModel m_waterfallHeightModel; + FloatModel m_waterfallGammaModel; + FloatModel m_windowOverlapModel; + FloatModel m_zeroPaddingModel; + + // colors (hard-coded, values must add up to specific numbers) + QColor m_colorL; //!< color of the left channel + QColor m_colorR; //!< color of the right channel + QColor m_colorMono; //!< mono color for spectrum display + QColor m_colorMonoW; //!< mono color for waterfall display + QColor m_colorBG; //!< spectrum display background color + QColor m_colorGrid; //!< color of grid lines + QColor m_colorLabels; //!< color of axis labels + + friend class SaControlsDialog; + friend class SaSpectrumView; + friend class SaWaterfallView; + friend class SaProcessor; +}; +#endif // SACONTROLS_H diff --git a/plugins/SpectrumAnalyzer/SaControlsDialog.cpp b/plugins/SpectrumAnalyzer/SaControlsDialog.cpp new file mode 100644 index 00000000000..ddd1489e85d --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaControlsDialog.cpp @@ -0,0 +1,352 @@ +/* + * SaControlsDialog.cpp - definition of SaControlsDialog class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "SaControlsDialog.h" + +#include +#include +#include +#include +#include + +#include "ComboBox.h" +#include "ComboBoxModel.h" +#include "embed.h" +#include "Engine.h" +#include "Knob.h" +#include "LedCheckbox.h" +#include "PixmapButton.h" +#include "SaControls.h" +#include "SaProcessor.h" + + +// The entire GUI layout is built here. +SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor) : + EffectControlDialog(controls), + m_controls(controls), + m_processor(processor) +{ + // Top level placement of sections is handled by QSplitter widget. + QHBoxLayout *master_layout = new QHBoxLayout; + QSplitter *display_splitter = new QSplitter(Qt::Vertical); + master_layout->addWidget(display_splitter); + master_layout->setContentsMargins(2, 6, 2, 8); + setLayout(master_layout); + + // Display splitter top: controls section + QWidget *controls_widget = new QWidget; + QHBoxLayout *controls_layout = new QHBoxLayout; + controls_layout->setContentsMargins(0, 0, 0, 0); + controls_widget->setLayout(controls_layout); + controls_widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); + controls_widget->setMaximumHeight(m_configHeight); + display_splitter->addWidget(controls_widget); + + + // Basic configuration + QWidget *config_widget = new QWidget; + QGridLayout *config_layout = new QGridLayout; + config_widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + config_widget->setMaximumHeight(m_configHeight); + config_widget->setLayout(config_layout); + controls_layout->addWidget(config_widget); + controls_layout->setStretchFactor(config_widget, 10); + + // Pre-compute target pixmap size based on monitor DPI. + // Using setDevicePixelRatio() on pixmap allows the SVG image to be razor + // sharp on High-DPI screens, but the desired size must be manually + // enlarged. No idea how to make Qt do it in a more reasonable way. + QSize iconSize = QSize(22.0 * devicePixelRatio(), 22.0 * devicePixelRatio()); + QSize buttonSize = 1.2 * iconSize; + QSize advButtonSize = QSize((m_configHeight * devicePixelRatio()) / 3, m_configHeight * devicePixelRatio()); + + + // pause and freeze buttons + PixmapButton *pauseButton = new PixmapButton(this, tr("Pause")); + pauseButton->setToolTip(tr("Pause data acquisition")); + QPixmap *pauseOnPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("play").scaled(buttonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + QPixmap *pauseOffPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("pause").scaled(buttonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + pauseOnPixmap->setDevicePixelRatio(devicePixelRatio()); + pauseOffPixmap->setDevicePixelRatio(devicePixelRatio()); + pauseButton->setActiveGraphic(*pauseOnPixmap); + pauseButton->setInactiveGraphic(*pauseOffPixmap); + pauseButton->setCheckable(true); + pauseButton->setModel(&controls->m_pauseModel); + config_layout->addWidget(pauseButton, 0, 0, 2, 1, Qt::AlignHCenter); + + PixmapButton *refFreezeButton = new PixmapButton(this, tr("Reference freeze")); + refFreezeButton->setToolTip(tr("Freeze current input as a reference / disable falloff in peak-hold mode.")); + QPixmap *freezeOnPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("freeze").scaled(buttonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + QPixmap *freezeOffPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("freeze_off").scaled(buttonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + freezeOnPixmap->setDevicePixelRatio(devicePixelRatio()); + freezeOffPixmap->setDevicePixelRatio(devicePixelRatio()); + refFreezeButton->setActiveGraphic(*freezeOnPixmap); + refFreezeButton->setInactiveGraphic(*freezeOffPixmap); + refFreezeButton->setCheckable(true); + refFreezeButton->setModel(&controls->m_refFreezeModel); + config_layout->addWidget(refFreezeButton, 2, 0, 2, 1, Qt::AlignHCenter); + + // misc configuration switches + LedCheckBox *waterfallButton = new LedCheckBox(tr("Waterfall"), this); + waterfallButton->setToolTip(tr("Display real-time spectrogram")); + waterfallButton->setCheckable(true); + waterfallButton->setMinimumSize(70, 12); + waterfallButton->setModel(&controls->m_waterfallModel); + config_layout->addWidget(waterfallButton, 0, 1); + + LedCheckBox *smoothButton = new LedCheckBox(tr("Averaging"), this); + smoothButton->setToolTip(tr("Enable exponential moving average")); + smoothButton->setCheckable(true); + smoothButton->setMinimumSize(70, 12); + smoothButton->setModel(&controls->m_smoothModel); + config_layout->addWidget(smoothButton, 1, 1); + + LedCheckBox *stereoButton = new LedCheckBox(tr("Stereo"), this); + stereoButton->setToolTip(tr("Display stereo channels separately")); + stereoButton->setCheckable(true); + stereoButton->setMinimumSize(70, 12); + stereoButton->setModel(&controls->m_stereoModel); + config_layout->addWidget(stereoButton, 2, 1); + + LedCheckBox *peakHoldButton = new LedCheckBox(tr("Peak hold"), this); + peakHoldButton->setToolTip(tr("Display envelope of peak values")); + peakHoldButton->setCheckable(true); + peakHoldButton->setMinimumSize(70, 12); + peakHoldButton->setModel(&controls->m_peakHoldModel); + config_layout->addWidget(peakHoldButton, 3, 1); + + // frequency: linear / log. switch and range selector + PixmapButton *logXButton = new PixmapButton(this, tr("Logarithmic frequency")); + logXButton->setToolTip(tr("Switch between logarithmic and linear frequency scale")); + QPixmap *logXOnPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("x_log").scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + QPixmap *logXOffPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("x_linear").scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + logXOnPixmap->setDevicePixelRatio(devicePixelRatio()); + logXOffPixmap->setDevicePixelRatio(devicePixelRatio()); + logXButton->setActiveGraphic(*logXOnPixmap); + logXButton->setInactiveGraphic(*logXOffPixmap); + logXButton->setCheckable(true); + logXButton->setModel(&controls->m_logXModel); + config_layout->addWidget(logXButton, 0, 2, 2, 1, Qt::AlignRight); + + ComboBox *freqRangeCombo = new ComboBox(this, tr("Frequency range")); + freqRangeCombo->setToolTip(tr("Frequency range")); + freqRangeCombo->setMinimumSize(100, ComboBox::DEFAULT_HEIGHT); + freqRangeCombo->setMaximumSize(200, ComboBox::DEFAULT_HEIGHT); + freqRangeCombo->setModel(&controls->m_freqRangeModel); + config_layout->addWidget(freqRangeCombo, 0, 3, 2, 1); + + // amplitude: linear / log switch and range selector + PixmapButton *logYButton = new PixmapButton(this, tr("Logarithmic amplitude")); + logYButton->setToolTip(tr("Switch between logarithmic and linear amplitude scale")); + QPixmap *logYOnPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("y_log").scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + QPixmap *logYOffPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("y_linear").scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + logYOnPixmap->setDevicePixelRatio(devicePixelRatio()); + logYOffPixmap->setDevicePixelRatio(devicePixelRatio()); + logYButton->setActiveGraphic(*logYOnPixmap); + logYButton->setInactiveGraphic(*logYOffPixmap); + logYButton->setCheckable(true); + logYButton->setModel(&controls->m_logYModel); + config_layout->addWidget(logYButton, 2, 2, 2, 1, Qt::AlignRight); + + ComboBox *ampRangeCombo = new ComboBox(this, tr("Amplitude range")); + ampRangeCombo->setToolTip(tr("Amplitude range")); + ampRangeCombo->setMinimumSize(100, ComboBox::DEFAULT_HEIGHT); + ampRangeCombo->setMaximumSize(200, ComboBox::DEFAULT_HEIGHT); + ampRangeCombo->setModel(&controls->m_ampRangeModel); + config_layout->addWidget(ampRangeCombo, 2, 3, 2, 1); + + // FFT: block size: icon and selector + QLabel *blockSizeLabel = new QLabel("", this); + QPixmap *blockSizeIcon = new QPixmap(PLUGIN_NAME::getIconPixmap("block_size")); + blockSizeIcon->setDevicePixelRatio(devicePixelRatio()); + blockSizeLabel->setPixmap(blockSizeIcon->scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + config_layout->addWidget(blockSizeLabel, 0, 4, 2, 1, Qt::AlignRight); + + ComboBox *blockSizeCombo = new ComboBox(this, tr("FFT block size")); + blockSizeCombo->setToolTip(tr("FFT block size")); + blockSizeCombo->setMinimumSize(100, 22); + blockSizeCombo->setMaximumSize(200, 22); + blockSizeCombo->setModel(&controls->m_blockSizeModel); + config_layout->addWidget(blockSizeCombo, 0, 5, 2, 1); + processor->reallocateBuffers(); + connect(&controls->m_blockSizeModel, &ComboBoxModel::dataChanged, [=] {processor->reallocateBuffers();}); + + // FFT: window type: icon and selector + QLabel *windowLabel = new QLabel("", this); + QPixmap *windowIcon = new QPixmap(PLUGIN_NAME::getIconPixmap("window")); + windowIcon->setDevicePixelRatio(devicePixelRatio()); + windowLabel->setPixmap(windowIcon->scaled(iconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + config_layout->addWidget(windowLabel, 2, 4, 2, 1, Qt::AlignRight); + + ComboBox *windowCombo = new ComboBox(this, tr("FFT window type")); + windowCombo->setToolTip(tr("FFT window type")); + windowCombo->setMinimumSize(100, ComboBox::DEFAULT_HEIGHT); + windowCombo->setMaximumSize(200, ComboBox::DEFAULT_HEIGHT); + windowCombo->setModel(&controls->m_windowModel); + config_layout->addWidget(windowCombo, 2, 5, 2, 1); + processor->rebuildWindow(); + connect(&controls->m_windowModel, &ComboBoxModel::dataChanged, [=] {processor->rebuildWindow();}); + + // set stretch factors so that combo boxes expand first + config_layout->setColumnStretch(3, 2); + config_layout->setColumnStretch(5, 3); + + + // Advanced configuration + QWidget *advanced_widget = new QWidget; + QGridLayout *advanced_layout = new QGridLayout; + advanced_widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + advanced_widget->setMaximumHeight(m_configHeight); + advanced_widget->setLayout(advanced_layout); + advanced_widget->hide(); + controls_layout->addWidget(advanced_widget); + controls_layout->setStretchFactor(advanced_widget, 10); + + // Peak envelope resolution + Knob *envelopeResolutionKnob = new Knob(knobSmall_17, this); + envelopeResolutionKnob->setModel(&controls->m_envelopeResolutionModel); + envelopeResolutionKnob->setLabel(tr("Envelope res.")); + envelopeResolutionKnob->setToolTip(tr("Increase envelope resolution for better details, decrease for better GUI performance.")); + envelopeResolutionKnob->setHintText(tr("Draw at most"), tr(" envelope points per pixel")); + advanced_layout->addWidget(envelopeResolutionKnob, 0, 0, 1, 1, Qt::AlignCenter); + + // Spectrum graph resolution + Knob *spectrumResolutionKnob = new Knob(knobSmall_17, this); + spectrumResolutionKnob->setModel(&controls->m_spectrumResolutionModel); + spectrumResolutionKnob->setLabel(tr("Spectrum res.")); + spectrumResolutionKnob->setToolTip(tr("Increase spectrum resolution for better details, decrease for better GUI performance.")); + spectrumResolutionKnob->setHintText(tr("Draw at most"), tr(" spectrum points per pixel")); + advanced_layout->addWidget(spectrumResolutionKnob, 1, 0, 1, 1, Qt::AlignCenter); + + // Peak falloff speed + Knob *peakDecayFactorKnob = new Knob(knobSmall_17, this); + peakDecayFactorKnob->setModel(&controls->m_peakDecayFactorModel); + peakDecayFactorKnob->setLabel(tr("Falloff factor")); + peakDecayFactorKnob->setToolTip(tr("Decrease to make peaks fall faster.")); + peakDecayFactorKnob->setHintText(tr("Multiply buffered value by"), ""); + advanced_layout->addWidget(peakDecayFactorKnob, 0, 1, 1, 1, Qt::AlignCenter); + + // Averaging weight + Knob *averagingWeightKnob = new Knob(knobSmall_17, this); + averagingWeightKnob->setModel(&controls->m_averagingWeightModel); + averagingWeightKnob->setLabel(tr("Averaging weight")); + averagingWeightKnob->setToolTip(tr("Decrease to make averaging slower and smoother.")); + averagingWeightKnob->setHintText(tr("New sample contributes"), ""); + advanced_layout->addWidget(averagingWeightKnob, 1, 1, 1, 1, Qt::AlignCenter); + + // Waterfall history size + Knob *waterfallHeightKnob = new Knob(knobSmall_17, this); + waterfallHeightKnob->setModel(&controls->m_waterfallHeightModel); + waterfallHeightKnob->setLabel(tr("Waterfall height")); + waterfallHeightKnob->setToolTip(tr("Increase to get slower scrolling, decrease to see fast transitions better. Warning: medium CPU usage.")); + waterfallHeightKnob->setHintText(tr("Keep"), tr(" lines")); + advanced_layout->addWidget(waterfallHeightKnob, 0, 2, 1, 1, Qt::AlignCenter); + processor->reallocateBuffers(); + connect(&controls->m_waterfallHeightModel, &FloatModel::dataChanged, [=] {processor->reallocateBuffers();}); + + // Waterfall gamma correction + Knob *waterfallGammaKnob = new Knob(knobSmall_17, this); + waterfallGammaKnob->setModel(&controls->m_waterfallGammaModel); + waterfallGammaKnob->setLabel(tr("Waterfall gamma")); + waterfallGammaKnob->setToolTip(tr("Decrease to see very weak signals, increase to get better contrast.")); + waterfallGammaKnob->setHintText(tr("Gamma value:"), ""); + advanced_layout->addWidget(waterfallGammaKnob, 1, 2, 1, 1, Qt::AlignCenter); + + // FFT window overlap + Knob *windowOverlapKnob = new Knob(knobSmall_17, this); + windowOverlapKnob->setModel(&controls->m_windowOverlapModel); + windowOverlapKnob->setLabel(tr("Window overlap")); + windowOverlapKnob->setToolTip(tr("Increase to prevent missing fast transitions arriving near FFT window edges. Warning: high CPU usage.")); + windowOverlapKnob->setHintText(tr("Each sample processed"), tr(" times")); + advanced_layout->addWidget(windowOverlapKnob, 0, 3, 1, 1, Qt::AlignCenter); + + // FFT zero padding + Knob *zeroPaddingKnob = new Knob(knobSmall_17, this); + zeroPaddingKnob->setModel(&controls->m_zeroPaddingModel); + zeroPaddingKnob->setLabel(tr("Zero padding")); + zeroPaddingKnob->setToolTip(tr("Increase to get smoother-looking spectrum. Warning: high CPU usage.")); + zeroPaddingKnob->setHintText(tr("Processing buffer is"), tr(" steps larger than input block")); + advanced_layout->addWidget(zeroPaddingKnob, 1, 3, 1, 1, Qt::AlignCenter); + processor->reallocateBuffers(); + connect(&controls->m_zeroPaddingModel, &FloatModel::dataChanged, [=] {processor->reallocateBuffers();}); + + + // Advanced settings button + PixmapButton *advancedButton = new PixmapButton(this, tr("Advanced settings")); + advancedButton->setToolTip(tr("Access advanced settings")); + QPixmap *advancedOnPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("advanced_on").scaled(advButtonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + QPixmap *advancedOffPixmap = new QPixmap(PLUGIN_NAME::getIconPixmap("advanced_off").scaled(advButtonSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + advancedOnPixmap->setDevicePixelRatio(devicePixelRatio()); + advancedOffPixmap->setDevicePixelRatio(devicePixelRatio()); + advancedButton->setActiveGraphic(*advancedOnPixmap); + advancedButton->setInactiveGraphic(*advancedOffPixmap); + advancedButton->setCheckable(true); + controls_layout->addStretch(0); + controls_layout->addWidget(advancedButton); + + connect(advancedButton, &PixmapButton::toggled, [=](bool checked) + { + if (checked) + { + config_widget->hide(); + advanced_widget->show(); + } + else + { + config_widget->show(); + advanced_widget->hide(); + } + } + ); + + // QSplitter middle and bottom: spectrum display widgets + m_spectrum = new SaSpectrumView(controls, processor, this); + display_splitter->addWidget(m_spectrum); + + m_waterfall = new SaWaterfallView(controls, processor, this); + display_splitter->addWidget(m_waterfall); + m_waterfall->setVisible(m_controls->m_waterfallModel.value()); + connect(&controls->m_waterfallModel, &BoolModel::dataChanged, [=] {m_waterfall->updateVisibility();}); +} + + +// Suggest the best current widget size. +QSize SaControlsDialog::sizeHint() const +{ + // Best width is determined by spectrum display sizeHint. + // Best height depends on whether waterfall is visible and + // consists of heights of the config section, spectrum, waterfall + // and some reserve for margins. + if (m_waterfall->isVisible()) + { + return QSize(m_spectrum->sizeHint().width(), + m_configHeight + m_spectrum->sizeHint().height() + m_waterfall->sizeHint().height() + 50); + } + else + { + return QSize(m_spectrum->sizeHint().width(), + m_configHeight + m_spectrum->sizeHint().height() + 50); + } +} + diff --git a/plugins/SpectrumAnalyzer/SaControlsDialog.h b/plugins/SpectrumAnalyzer/SaControlsDialog.h new file mode 100644 index 00000000000..e5a35f186bc --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaControlsDialog.h @@ -0,0 +1,57 @@ +/* + * SaControlsDialog.h - declatation of SaControlsDialog class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef SACONTROLSDIALOG_H +#define SACONTROLSDIALOG_H + +#include "EffectControlDialog.h" +#include "SaControls.h" +#include "SaSpectrumView.h" +#include "SaProcessor.h" +#include "SaWaterfallView.h" + + +//! Top-level widget holding the configuration GUI and spectrum displays +class SaControlsDialog : public EffectControlDialog +{ + Q_OBJECT +public: + explicit SaControlsDialog(SaControls *controls, SaProcessor *processor); + virtual ~SaControlsDialog() {} + + bool isResizable() const override {return true;} + QSize sizeHint() const override; + +private: + SaControls *m_controls; + SaProcessor *m_processor; + + // Pointers to created widgets are needed to keep track of their sizeHint() changes. + // Config widget is a plain QWidget so it has just a fixed height instead. + const int m_configHeight = 75; + SaSpectrumView *m_spectrum; + SaWaterfallView *m_waterfall; +}; + +#endif // SACONTROLSDIALOG_H diff --git a/plugins/SpectrumAnalyzer/SaProcessor.cpp b/plugins/SpectrumAnalyzer/SaProcessor.cpp new file mode 100644 index 00000000000..9d83f2916f0 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaProcessor.cpp @@ -0,0 +1,692 @@ +/* SaProcessor.cpp - implementation of SaProcessor class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014-2017, David French + * + * This file is part of LMMS - https://lmms.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "SaProcessor.h" + +#include +#ifdef SA_DEBUG + #include +#endif +#include +#ifdef SA_DEBUG + #include + #include +#endif +#include + +#include "lmms_math.h" +#include "LocklessRingBuffer.h" + + +SaProcessor::SaProcessor(const SaControls *controls) : + m_controls(controls), + m_terminate(false), + m_inBlockSize(FFT_BLOCK_SIZES[0]), + m_fftBlockSize(FFT_BLOCK_SIZES[0]), + m_sampleRate(Engine::mixer()->processingSampleRate()), + m_framesFilledUp(0), + m_spectrumActive(false), + m_waterfallActive(false), + m_waterfallNotEmpty(0), + m_reallocating(false) +{ + m_fftWindow.resize(m_inBlockSize, 1.0); + precomputeWindow(m_fftWindow.data(), m_inBlockSize, BLACKMAN_HARRIS); + + m_bufferL.resize(m_inBlockSize, 0); + m_bufferR.resize(m_inBlockSize, 0); + m_filteredBufferL.resize(m_fftBlockSize, 0); + m_filteredBufferR.resize(m_fftBlockSize, 0); + m_spectrumL = (fftwf_complex *) fftwf_malloc(binCount() * sizeof (fftwf_complex)); + m_spectrumR = (fftwf_complex *) fftwf_malloc(binCount() * sizeof (fftwf_complex)); + m_fftPlanL = fftwf_plan_dft_r2c_1d(m_fftBlockSize, m_filteredBufferL.data(), m_spectrumL, FFTW_MEASURE); + m_fftPlanR = fftwf_plan_dft_r2c_1d(m_fftBlockSize, m_filteredBufferR.data(), m_spectrumR, FFTW_MEASURE); + + m_absSpectrumL.resize(binCount(), 0); + m_absSpectrumR.resize(binCount(), 0); + m_normSpectrumL.resize(binCount(), 0); + m_normSpectrumR.resize(binCount(), 0); + + m_waterfallHeight = 100; // a small safe value + m_history_work.resize(waterfallWidth() * m_waterfallHeight * sizeof qRgb(0,0,0), 0); + m_history.resize(waterfallWidth() * m_waterfallHeight * sizeof qRgb(0,0,0), 0); +} + + +SaProcessor::~SaProcessor() +{ + if (m_fftPlanL != NULL) {fftwf_destroy_plan(m_fftPlanL);} + if (m_fftPlanR != NULL) {fftwf_destroy_plan(m_fftPlanR);} + if (m_spectrumL != NULL) {fftwf_free(m_spectrumL);} + if (m_spectrumR != NULL) {fftwf_free(m_spectrumR);} + + m_fftPlanL = NULL; + m_fftPlanR = NULL; + m_spectrumL = NULL; + m_spectrumR = NULL; +} + + +// Load data from audio thread ringbuffer and run FFT analysis if buffer is full enough. +void SaProcessor::analyze(LocklessRingBuffer &ring_buffer) +{ + LocklessRingBufferReader reader(ring_buffer); + + // Processing thread loop + while (!m_terminate) + { + // If there is nothing to read, wait for notification from the writing side. + if (reader.empty()) {reader.waitForData();} + + // skip waterfall render if processing can't keep up with input + bool overload = ring_buffer.free() < ring_buffer.capacity() / 2; + + auto in_buffer = reader.read_max(ring_buffer.capacity() / 4); + std::size_t frame_count = in_buffer.size(); + + // Process received data only if any view is visible and not paused. + // Also, to prevent a momentary GUI freeze under high load (due to lock + // starvation), skip analysis when buffer reallocation is requested. + if ((m_spectrumActive || m_waterfallActive) && !m_controls->m_pauseModel.value() && !m_reallocating) + { + const bool stereo = m_controls->m_stereoModel.value(); + fpp_t in_frame = 0; + while (in_frame < frame_count) + { + // Lock data access to prevent reallocation from changing + // buffers and control variables. + QMutexLocker data_lock(&m_dataAccess); + + // Fill sample buffers and check for zero input. + bool block_empty = true; + for (; in_frame < frame_count && m_framesFilledUp < m_inBlockSize; in_frame++, m_framesFilledUp++) + { + if (stereo) + { + m_bufferL[m_framesFilledUp] = in_buffer[in_frame][0]; + m_bufferR[m_framesFilledUp] = in_buffer[in_frame][1]; + } + else + { + m_bufferL[m_framesFilledUp] = + m_bufferR[m_framesFilledUp] = (in_buffer[in_frame][0] + in_buffer[in_frame][1]) * 0.5f; + } + if (in_buffer[in_frame][0] != 0.f || in_buffer[in_frame][1] != 0.f) + { + block_empty = false; + } + } + + // Run analysis only if buffers contain enough data. + if (m_framesFilledUp < m_inBlockSize) {break;} + + // Print performance analysis once per 2 seconds if debug is enabled + #ifdef SA_DEBUG + unsigned int total_time = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + if (total_time - m_last_dump_time > 2000000000) + { + std::cout << "FFT analysis: " << std::fixed << std::setprecision(2) + << m_sum_execution / m_dump_count << " ms avg / " + << m_max_execution << " ms peak, executing " + << m_dump_count << " times per second (" + << m_sum_execution / 20.0 << " % CPU usage)." << std::endl; + m_last_dump_time = total_time; + m_sum_execution = m_max_execution = m_dump_count = 0; + } + #endif + + // update sample rate + m_sampleRate = Engine::mixer()->processingSampleRate(); + + // apply FFT window + for (unsigned int i = 0; i < m_inBlockSize; i++) + { + m_filteredBufferL[i] = m_bufferL[i] * m_fftWindow[i]; + m_filteredBufferR[i] = m_bufferR[i] * m_fftWindow[i]; + } + + // Run FFT on left channel, convert the result to absolute magnitude + // spectrum and normalize it. + fftwf_execute(m_fftPlanL); + absspec(m_spectrumL, m_absSpectrumL.data(), binCount()); + normalize(m_absSpectrumL, m_normSpectrumL, m_inBlockSize); + + // repeat analysis for right channel if stereo processing is enabled + if (stereo) + { + fftwf_execute(m_fftPlanR); + absspec(m_spectrumR, m_absSpectrumR.data(), binCount()); + normalize(m_absSpectrumR, m_normSpectrumR, m_inBlockSize); + } + + // count empty lines so that empty history does not have to update + if (block_empty && m_waterfallNotEmpty) + { + m_waterfallNotEmpty -= 1; + } + else if (!block_empty) + { + m_waterfallNotEmpty = m_waterfallHeight + 2; + } + + if (m_waterfallActive && m_waterfallNotEmpty) + { + // move waterfall history one line down and clear the top line + QRgb *pixel = (QRgb *)m_history_work.data(); + std::copy(pixel, + pixel + waterfallWidth() * m_waterfallHeight - waterfallWidth(), + pixel + waterfallWidth()); + memset(pixel, 0, waterfallWidth() * sizeof (QRgb)); + + // add newest result on top + int target; // pixel being constructed + float accL = 0; // accumulators for merging multiple bins + float accR = 0; + for (unsigned int i = 0; i < binCount(); i++) + { + // fill line with red color to indicate lost data if CPU cannot keep up + if (overload && i < waterfallWidth()) + { + pixel[i] = qRgb(42, 0, 0); + continue; + } + + // Every frequency bin spans a frequency range that must be + // partially or fully mapped to a pixel. Any inconsistency + // may be seen in the spectrogram as dark or white lines -- + // play white noise to confirm your change did not break it. + float band_start = freqToXPixel(binToFreq(i) - binBandwidth() / 2.0, waterfallWidth()); + float band_end = freqToXPixel(binToFreq(i + 1) - binBandwidth() / 2.0, waterfallWidth()); + if (m_controls->m_logXModel.value()) + { + // Logarithmic scale + if (band_end - band_start > 1.0) + { + // band spans multiple pixels: draw all pixels it covers + for (target = (int)band_start; target < (int)band_end; target++) + { + if (target >= 0 && target < waterfallWidth()) + { + pixel[target] = makePixel(m_normSpectrumL[i], m_normSpectrumR[i]); + } + } + // save remaining portion of the band for the following band / pixel + // (in case the next band uses sub-pixel drawing) + accL = (band_end - (int)band_end) * m_normSpectrumL[i]; + accR = (band_end - (int)band_end) * m_normSpectrumR[i]; + } + else + { + // sub-pixel drawing; add contribution of current band + target = (int)band_start; + if ((int)band_start == (int)band_end) + { + // band ends within current target pixel, accumulate + accL += (band_end - band_start) * m_normSpectrumL[i]; + accR += (band_end - band_start) * m_normSpectrumR[i]; + } + else + { + // Band ends in the next pixel -- finalize the current pixel. + // Make sure contribution is split correctly on pixel boundary. + accL += ((int)band_end - band_start) * m_normSpectrumL[i]; + accR += ((int)band_end - band_start) * m_normSpectrumR[i]; + + if (target >= 0 && target < waterfallWidth()) {pixel[target] = makePixel(accL, accR);} + + // save remaining portion of the band for the following band / pixel + accL = (band_end - (int)band_end) * m_normSpectrumL[i]; + accR = (band_end - (int)band_end) * m_normSpectrumR[i]; + } + } + } + else + { + // Linear: always draws one or more pixels per band + for (target = (int)band_start; target < band_end; target++) + { + if (target >= 0 && target < waterfallWidth()) + { + pixel[target] = makePixel(m_normSpectrumL[i], m_normSpectrumR[i]); + } + } + } + } + + // Copy work buffer to result buffer. Done only if requested, so + // that time isn't wasted on updating faster than display FPS. + // (The copy is about as expensive as the movement.) + if (m_flipRequest) + { + m_history = m_history_work; + m_flipRequest = false; + } + } + // clean up before checking for more data from input buffer + const unsigned int overlaps = m_controls->m_windowOverlapModel.value(); + if (overlaps == 1) // Discard buffer, each sample used only once + { + m_framesFilledUp = 0; + } + else + { + // Drop only a part of the buffer from the beginning, so that new + // data can be added to the end. This means the older samples will + // be analyzed again, but in a different position in the window, + // making short transient signals show up better in the waterfall. + const unsigned int drop = m_inBlockSize / overlaps; + std::move(m_bufferL.begin() + drop, m_bufferL.end(), m_bufferL.begin()); + std::move(m_bufferR.begin() + drop, m_bufferR.end(), m_bufferR.begin()); + m_framesFilledUp -= drop; + } + + #ifdef SA_DEBUG + // measure overall FFT processing speed + total_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - total_time; + m_dump_count++; + m_sum_execution += total_time / 1000000.0; + if (total_time / 1000000.0 > m_max_execution) {m_max_execution = total_time / 1000000.0;} + #endif + } // frame filler and processing + } // process if active + } // thread loop end +} + + +// Produce a spectrogram pixel from normalized spectrum data. +// Values over 1.0 will cause the color components to overflow: this is left +// intentionally untreated as it clearly indicates which frequency is clipping. +// Gamma correction is applied to make small values more visible and to make +// a linear gradient actually appear roughly linear. The correction should be +// around 0.42 to 0.45 for sRGB displays (or lower for bigger visibility boost). +QRgb SaProcessor::makePixel(float left, float right) const +{ + const float gamma_correction = m_controls->m_waterfallGammaModel.value(); + if (m_controls->m_stereoModel.value()) + { + float ampL = pow(left, gamma_correction); + float ampR = pow(right, gamma_correction); + return qRgb(m_controls->m_colorL.red() * ampL + m_controls->m_colorR.red() * ampR, + m_controls->m_colorL.green() * ampL + m_controls->m_colorR.green() * ampR, + m_controls->m_colorL.blue() * ampL + m_controls->m_colorR.blue() * ampR); + } + else + { + float ampL = pow(left, gamma_correction); + // make mono color brighter to compensate for the fact it is not summed + return qRgb(m_controls->m_colorMonoW.red() * ampL, + m_controls->m_colorMonoW.green() * ampL, + m_controls->m_colorMonoW.blue() * ampL); + } +} + + + +// Inform the processor whether any display widgets actually need it. +void SaProcessor::setSpectrumActive(bool active) +{ + m_spectrumActive = active; +} + +void SaProcessor::setWaterfallActive(bool active) +{ + m_waterfallActive = active; +} + + +// Reallocate data buffers according to newly set block size. +void SaProcessor::reallocateBuffers() +{ + unsigned int new_size_index = m_controls->m_blockSizeModel.value(); + unsigned int new_in_size, new_fft_size; + unsigned int new_bins; + + // get new block sizes and bin count based on selected index + if (new_size_index < FFT_BLOCK_SIZES.size()) + { + new_in_size = FFT_BLOCK_SIZES[new_size_index]; + } + else + { + new_in_size = FFT_BLOCK_SIZES.back(); + } + m_zeroPadFactor = m_controls->m_zeroPaddingModel.value(); + if (new_size_index + m_zeroPadFactor < FFT_BLOCK_SIZES.size()) + { + new_fft_size = FFT_BLOCK_SIZES[new_size_index + m_zeroPadFactor]; + } + else + { + new_fft_size = FFT_BLOCK_SIZES.back(); + } + + new_bins = new_fft_size / 2 +1; + + // Use m_reallocating to tell analyze() to avoid asking for the lock. This + // is needed because under heavy load the FFT thread requests data lock so + // often that this routine could end up waiting even for several seconds. + m_reallocating = true; + + // Lock data shared with SaSpectrumView and SaWaterfallView. + // Reallocation lock must be acquired first to avoid deadlock (a view class + // may already have it and request the "stronger" data lock on top of that). + QMutexLocker reloc_lock(&m_reallocationAccess); + QMutexLocker data_lock(&m_dataAccess); + + // destroy old FFT plan and free the result buffer + if (m_fftPlanL != NULL) {fftwf_destroy_plan(m_fftPlanL);} + if (m_fftPlanR != NULL) {fftwf_destroy_plan(m_fftPlanR);} + if (m_spectrumL != NULL) {fftwf_free(m_spectrumL);} + if (m_spectrumR != NULL) {fftwf_free(m_spectrumR);} + + // allocate new space, create new plan and resize containers + m_fftWindow.resize(new_in_size, 1.0); + precomputeWindow(m_fftWindow.data(), new_in_size, (FFT_WINDOWS) m_controls->m_windowModel.value()); + m_bufferL.resize(new_in_size, 0); + m_bufferR.resize(new_in_size, 0); + m_filteredBufferL.resize(new_fft_size, 0); + m_filteredBufferR.resize(new_fft_size, 0); + m_spectrumL = (fftwf_complex *) fftwf_malloc(new_bins * sizeof (fftwf_complex)); + m_spectrumR = (fftwf_complex *) fftwf_malloc(new_bins * sizeof (fftwf_complex)); + m_fftPlanL = fftwf_plan_dft_r2c_1d(new_fft_size, m_filteredBufferL.data(), m_spectrumL, FFTW_MEASURE); + m_fftPlanR = fftwf_plan_dft_r2c_1d(new_fft_size, m_filteredBufferR.data(), m_spectrumR, FFTW_MEASURE); + + if (m_fftPlanL == NULL || m_fftPlanR == NULL) + { + #ifdef SA_DEBUG + std::cerr << "Analyzer: failed to create new FFT plan!" << std::endl; + #endif + } + m_absSpectrumL.resize(new_bins, 0); + m_absSpectrumR.resize(new_bins, 0); + m_normSpectrumL.resize(new_bins, 0); + m_normSpectrumR.resize(new_bins, 0); + + m_waterfallHeight = m_controls->m_waterfallHeightModel.value(); + m_history_work.resize((new_bins < m_waterfallMaxWidth ? new_bins : m_waterfallMaxWidth) + * m_waterfallHeight + * sizeof qRgb(0,0,0), 0); + m_history.resize((new_bins < m_waterfallMaxWidth ? new_bins : m_waterfallMaxWidth) + * m_waterfallHeight + * sizeof qRgb(0,0,0), 0); + + // done; publish new sizes and clean up + m_inBlockSize = new_in_size; + m_fftBlockSize = new_fft_size; + + data_lock.unlock(); + reloc_lock.unlock(); + m_reallocating = false; + + clear(); +} + + +// Precompute a new FFT window based on currently selected type. +void SaProcessor::rebuildWindow() +{ + // computation is done in fft_helpers + QMutexLocker lock(&m_dataAccess); + precomputeWindow(m_fftWindow.data(), m_inBlockSize, (FFT_WINDOWS) m_controls->m_windowModel.value()); +} + + +// Clear all data buffers and replace contents with zeros. +// Note: may take a few milliseconds, do not call in a loop! +void SaProcessor::clear() +{ + const unsigned int overlaps = m_controls->m_windowOverlapModel.value(); + QMutexLocker lock(&m_dataAccess); + // If there is any window overlap, leave space only for the new samples + // and treat the rest at initialized with zeros. Prevents missing + // transients at the start of the very first block. + m_framesFilledUp = m_inBlockSize - m_inBlockSize / overlaps; + std::fill(m_bufferL.begin(), m_bufferL.end(), 0); + std::fill(m_bufferR.begin(), m_bufferR.end(), 0); + std::fill(m_filteredBufferL.begin(), m_filteredBufferL.end(), 0); + std::fill(m_filteredBufferR.begin(), m_filteredBufferR.end(), 0); + std::fill(m_absSpectrumL.begin(), m_absSpectrumL.end(), 0); + std::fill(m_absSpectrumR.begin(), m_absSpectrumR.end(), 0); + std::fill(m_normSpectrumL.begin(), m_normSpectrumL.end(), 0); + std::fill(m_normSpectrumR.begin(), m_normSpectrumR.end(), 0); + std::fill(m_history_work.begin(), m_history_work.end(), 0); + std::fill(m_history.begin(), m_history.end(), 0); +} + +// Clear only history work buffer. Used to flush old data when waterfall +// is shown after a period of inactivity. +void SaProcessor::clearHistory() +{ + QMutexLocker lock(&m_dataAccess); + std::fill(m_history_work.begin(), m_history_work.end(), 0); +} + +// Check if result buffers contain any non-zero values +bool SaProcessor::spectrumNotEmpty() +{ + QMutexLocker lock(&m_reallocationAccess); + return notEmpty(m_normSpectrumL) || notEmpty(m_normSpectrumR); +} + + +// -------------------------------------- +// Frequency conversion helpers +// + +// Get sample rate value that is valid for currently stored results. +unsigned int SaProcessor::getSampleRate() const +{ + return m_sampleRate; +} + + +// Maximum frequency of a sampled signal is equal to half of its sample rate. +float SaProcessor::getNyquistFreq() const +{ + return getSampleRate() / 2.0f; +} + + +// FFTW automatically discards upper half of the symmetric FFT output, so +// the useful bin count is the transform size divided by 2, plus zero. +unsigned int SaProcessor::binCount() const +{ + return m_fftBlockSize / 2 + 1; +} + + +// Return the final width of waterfall display buffer. +// Normally the waterfall width equals the number of frequency bins, but the +// FFT transform can easily produce more bins than can be reasonably useful for +// currently used display resolutions. This function limits width of the final +// image to a given size, which is then used during waterfall render and display. +unsigned int SaProcessor::waterfallWidth() const +{ + return binCount() < m_waterfallMaxWidth ? binCount() : m_waterfallMaxWidth; +} + + +// Return the center frequency of given frequency bin. +float SaProcessor::binToFreq(unsigned int bin_index) const +{ + return getNyquistFreq() * bin_index / binCount(); +} + + +// Return width of the frequency range that falls into one bin. +// The binCount is lowered by one since half of the first and last bin is +// actually outside the frequency range. +float SaProcessor::binBandwidth() const +{ + return getNyquistFreq() / (binCount() - 1); +} + + +float SaProcessor::getFreqRangeMin(bool linear) const +{ + switch (m_controls->m_freqRangeModel.value()) + { + case FRANGE_AUDIBLE: return FRANGE_AUDIBLE_START; + case FRANGE_BASS: return FRANGE_BASS_START; + case FRANGE_MIDS: return FRANGE_MIDS_START; + case FRANGE_HIGH: return FRANGE_HIGH_START; + default: + case FRANGE_FULL: return linear ? 0 : LOWEST_LOG_FREQ; + } +} + + +float SaProcessor::getFreqRangeMax() const +{ + switch (m_controls->m_freqRangeModel.value()) + { + case FRANGE_AUDIBLE: return FRANGE_AUDIBLE_END; + case FRANGE_BASS: return FRANGE_BASS_END; + case FRANGE_MIDS: return FRANGE_MIDS_END; + case FRANGE_HIGH: return FRANGE_HIGH_END; + default: + case FRANGE_FULL: return getNyquistFreq(); + } +} + + +// Map frequency to pixel x position on a display of given width. +float SaProcessor::freqToXPixel(float freq, unsigned int width) const +{ + if (m_controls->m_logXModel.value()) + { + if (freq <= 1) {return 0;} + float min = log10(getFreqRangeMin()); + float range = log10(getFreqRangeMax()) - min; + return (log10(freq) - min) / range * width; + } + else + { + float min = getFreqRangeMin(); + float range = getFreqRangeMax() - min; + return (freq - min) / range * width; + } +} + + +// Map pixel x position on display of given width back to frequency. +float SaProcessor::xPixelToFreq(float x, unsigned int width) const +{ + if (m_controls->m_logXModel.value()) + { + float min = log10(getFreqRangeMin()); + float max = log10(getFreqRangeMax()); + float range = max - min; + return pow(10, min + x / width * range); + } + else + { + float min = getFreqRangeMin(); + float range = getFreqRangeMax() - min; + return min + x / width * range; + } +} + + +// -------------------------------------- +// Amplitude conversion helpers +// +float SaProcessor::getAmpRangeMin(bool linear) const +{ + // return very low limit to make sure zero gets included at linear grid + if (linear) {return -900;} + switch (m_controls->m_ampRangeModel.value()) + { + case ARANGE_EXTENDED: return ARANGE_EXTENDED_START; + case ARANGE_SILENT: return ARANGE_SILENT_START; + case ARANGE_LOUD: return ARANGE_LOUD_START; + default: + case ARANGE_AUDIBLE: return ARANGE_AUDIBLE_START; + } +} + + +float SaProcessor::getAmpRangeMax() const +{ + switch (m_controls->m_ampRangeModel.value()) + { + case ARANGE_EXTENDED: return ARANGE_EXTENDED_END; + case ARANGE_SILENT: return ARANGE_SILENT_END; + case ARANGE_LOUD: return ARANGE_LOUD_END; + default: + case ARANGE_AUDIBLE: return ARANGE_AUDIBLE_END; + } +} + + +// Map linear amplitude to pixel y position on a display of given height. +// Note that display coordinates are flipped: amplitude grows from [height] to zero. +float SaProcessor::ampToYPixel(float amplitude, unsigned int height) const +{ + if (m_controls->m_logYModel.value()) + { + // logarithmic scale: convert linear amplitude to dB (relative to 1.0) + float amplitude_dB = 10 * log10(amplitude); + if (amplitude_dB < getAmpRangeMin()) + { + return height; + } + else + { + float max = getAmpRangeMax(); + float range = getAmpRangeMin() - max; + return (amplitude_dB - max) / range * height; + } + } + else + { + // linear scale: convert returned ranges from dB to linear scale + float max = pow(10, getAmpRangeMax() / 10); + float range = pow(10, getAmpRangeMin() / 10) - max; + return (amplitude - max) / range * height; + } +} + + +// Map pixel y position on display of given height back to amplitude. +// Note that display coordinates are flipped: amplitude grows from [height] to zero. +// Also note that in logarithmic Y mode the returned amplitude is in dB, not linear. +float SaProcessor::yPixelToAmp(float y, unsigned int height) const +{ + if (m_controls->m_logYModel.value()) + { + float max = getAmpRangeMax(); + float range = getAmpRangeMin() - max; + return max + range * (y / height); + } + else + { + // linear scale: convert returned ranges from dB to linear scale + float max = pow(10, getAmpRangeMax() / 10); + float range = pow(10, getAmpRangeMin() / 10) - max; + return max + range * (y / height); + } +} + diff --git a/plugins/SpectrumAnalyzer/SaProcessor.h b/plugins/SpectrumAnalyzer/SaProcessor.h new file mode 100644 index 00000000000..0c396b3c031 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaProcessor.h @@ -0,0 +1,160 @@ +/* SaProcessor.h - declaration of SaProcessor class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014 David French + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef SAPROCESSOR_H +#define SAPROCESSOR_H + +#include +#include +#include +#include + +#include "fft_helpers.h" +#include "SaControls.h" + +template +class LocklessRingBuffer; + +//! Receives audio data, runs FFT analysis and stores the result. +class SaProcessor +{ +public: + explicit SaProcessor(const SaControls *controls); + virtual ~SaProcessor(); + + // analysis thread and a method to terminate it + void analyze(LocklessRingBuffer &ring_buffer); + void terminate() {m_terminate = true;} + + // inform processor if any processing is actually required + void setSpectrumActive(bool active); + void setWaterfallActive(bool active); + void flipRequest() {m_flipRequest = true;} // request refresh of history buffer + + // configuration is taken from models in SaControls; some changes require + // an exlicit update request (reallocation and window rebuild) + void reallocateBuffers(); + void rebuildWindow(); + void clear(); + void clearHistory(); + + const float *getSpectrumL() const {return m_normSpectrumL.data();} + const float *getSpectrumR() const {return m_normSpectrumR.data();} + const uchar *getHistory() const {return m_history.data();} + + // information about results and unit conversion helpers + unsigned int inBlockSize() const {return m_inBlockSize;} + unsigned int binCount() const; //!< size of output (frequency domain) data block + bool spectrumNotEmpty(); //!< check if result buffers contain any non-zero values + + unsigned int waterfallWidth() const; //!< binCount value capped at 3840 (for display) + unsigned int waterfallHeight() const {return m_waterfallHeight;} + bool waterfallNotEmpty() const {return m_waterfallNotEmpty;} + + float binToFreq(unsigned int bin_index) const; + float binBandwidth() const; + + float freqToXPixel(float frequency, unsigned int width) const; + float xPixelToFreq(float x, unsigned int width) const; + + float ampToYPixel(float amplitude, unsigned int height) const; + float yPixelToAmp(float y, unsigned int height) const; + + unsigned int getSampleRate() const; + float getNyquistFreq() const; + + float getFreqRangeMin(bool linear = false) const; + float getFreqRangeMax() const; + float getAmpRangeMin(bool linear = false) const; + float getAmpRangeMax() const; + + // Reallocation lock prevents the processor from changing size of its buffers. + // It is used to keep consistent bin-to-frequency mapping while drawing the + // spectrum and to make sure reading side does not find itself out of bounds. + // The processor is meanwhile free to work on another block. + QMutex m_reallocationAccess; + // Data access lock prevents the processor from changing both size and content + // of its buffers. It is used when writing to a result buffer, or when a friendly + // class reads them and needs guaranteed data consistency. + // It causes FFT analysis to be paused, so this lock should be used sparingly. + // If using both locks at the same time, reallocation lock MUST be acquired first. + QMutex m_dataAccess; + + +private: + const SaControls *m_controls; + + // thread communication and control + bool m_terminate; + + // currently valid configuration + unsigned int m_zeroPadFactor = 2; //!< use n-steps bigger FFT for given block size + std::atomic m_inBlockSize;//!< size of input (time domain) data block + unsigned int m_fftBlockSize; //!< size of padded block for FFT processing + unsigned int m_sampleRate; + + // data buffers (roughly in the order of processing, from input to output) + unsigned int m_framesFilledUp; + std::vector m_bufferL; //!< time domain samples (left) + std::vector m_bufferR; //!< time domain samples (right) + std::vector m_fftWindow; //!< precomputed window function coefficients + std::vector m_filteredBufferL; //!< time domain samples with window function applied (left) + std::vector m_filteredBufferR; //!< time domain samples with window function applied (right) + fftwf_plan m_fftPlanL; + fftwf_plan m_fftPlanR; + fftwf_complex *m_spectrumL; //!< frequency domain samples (complex) (left) + fftwf_complex *m_spectrumR; //!< frequency domain samples (complex) (right) + std::vector m_absSpectrumL; //!< frequency domain samples (absolute) (left) + std::vector m_absSpectrumR; //!< frequency domain samples (absolute) (right) + std::vector m_normSpectrumL; //!< frequency domain samples (normalized) (left) + std::vector m_normSpectrumR; //!< frequency domain samples (normalized) (right) + + // spectrum history for waterfall: new normSpectrum lines are added on top + std::vector m_history_work; //!< local history buffer for render + std::vector m_history; //!< public buffer for reading + bool m_flipRequest; //!< update public buffer only when requested + std::atomic m_waterfallHeight; //!< number of stored lines in history buffer + // Note: high values may make it harder to see transients. + const unsigned int m_waterfallMaxWidth = 3840; + + // book keeping + bool m_spectrumActive; + bool m_waterfallActive; + std::atomic m_waterfallNotEmpty; //!< number of lines remaining visible on display + bool m_reallocating; + + // merge L and R channels and apply gamma correction to make a spectrogram pixel + QRgb makePixel(float left, float right) const; + + #ifdef SA_DEBUG + unsigned int m_last_dump_time; + unsigned int m_dump_count; + float m_sum_execution; + float m_max_execution; + #endif +}; +#endif // SAPROCESSOR_H + diff --git a/plugins/SpectrumAnalyzer/SaSpectrumView.cpp b/plugins/SpectrumAnalyzer/SaSpectrumView.cpp new file mode 100644 index 00000000000..13aaeb72418 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaSpectrumView.cpp @@ -0,0 +1,813 @@ +/* SaSpectrumView.cpp - implementation of SaSpectrumView class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014-2017, David French + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "SaSpectrumView.h" + +#include +#include +#include +#include +#include +#include + +#include "GuiApplication.h" +#include "MainWindow.h" +#include "SaProcessor.h" + +#ifdef SA_DEBUG + #include +#endif + + +SaSpectrumView::SaSpectrumView(SaControls *controls, SaProcessor *processor, QWidget *_parent) : + QWidget(_parent), + m_controls(controls), + m_processor(processor), + m_freezeRequest(false), + m_frozen(false) +{ + setMinimumSize(360, 170); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + + connect(gui->mainWindow(), SIGNAL(periodicUpdate()), this, SLOT(periodicUpdate())); + + m_displayBufferL.resize(m_processor->binCount(), 0); + m_displayBufferR.resize(m_processor->binCount(), 0); + m_peakBufferL.resize(m_processor->binCount(), 0); + m_peakBufferR.resize(m_processor->binCount(), 0); + + m_freqRangeIndex = m_controls->m_freqRangeModel.value(); + m_ampRangeIndex = m_controls->m_ampRangeModel.value(); + + m_logFreqTics = makeLogFreqTics(m_processor->getFreqRangeMin(), m_processor->getFreqRangeMax()); + m_linearFreqTics = makeLinearFreqTics(m_processor->getFreqRangeMin(), m_processor->getFreqRangeMax()); + m_logAmpTics = makeLogAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax()); + m_linearAmpTics = makeLinearAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax()); + + m_cursor = QPointF(0, 0); + + #ifdef SA_DEBUG + m_execution_avg = m_path_avg = m_draw_avg = 0; + #endif +} + + +// Compose and draw all the content; periodically called by Qt. +// NOTE: Performance sensitive! If the drawing takes too long, it will drag +// the FPS down for the entire program! Use SA_DEBUG to display timings. +void SaSpectrumView::paintEvent(QPaintEvent *event) +{ + #ifdef SA_DEBUG + int total_time = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + #endif + + // 0) Constants and init + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, true); + + // drawing and path-making are split into multiple methods for clarity; + // display boundaries are updated here and shared as member variables + m_displayTop = 1; + m_displayBottom = height() -20; + m_displayLeft = 26; + m_displayRight = width() -26; + m_displayWidth = m_displayRight - m_displayLeft; + + // recompute range labels if needed + if (m_freqRangeIndex != m_controls->m_freqRangeModel.value()) + { + m_logFreqTics = makeLogFreqTics(m_processor->getFreqRangeMin(), m_processor->getFreqRangeMax()); + m_linearFreqTics = makeLinearFreqTics(m_processor->getFreqRangeMin(true), m_processor->getFreqRangeMax()); + m_freqRangeIndex = m_controls->m_freqRangeModel.value(); + } + if (m_ampRangeIndex != m_controls->m_ampRangeModel.value()) + { + m_logAmpTics = makeLogAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax()); + m_linearAmpTics = makeLinearAmpTics(m_processor->getAmpRangeMin(true), m_processor->getAmpRangeMax()); + m_ampRangeIndex = m_controls->m_ampRangeModel.value(); + } + + // generate freeze request or clear "frozen" status based on freeze button + if (!m_frozen && m_controls->m_refFreezeModel.value()) + { + m_freezeRequest = true; + } + else if (!m_controls->m_refFreezeModel.value()) + { + m_frozen = false; + } + + // 1) Background, grid and labels + drawGrid(painter); + + // 2) Spectrum display + drawSpectrum(painter); + + // 3) Overlays + // draw cursor (if it is within bounds) + drawCursor(painter); + + // always draw the display outline + painter.setPen(QPen(m_controls->m_colorGrid, 2, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawRoundedRect(m_displayLeft, 1, + m_displayWidth, m_displayBottom, + 2.0, 2.0); + + #ifdef SA_DEBUG + // display performance measurements if enabled + total_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - total_time; + m_execution_avg = 0.95 * m_execution_avg + 0.05 * total_time / 1000000.0; + painter.setPen(QPen(m_controls->m_colorLabels, 1, + Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawText(m_displayRight -150, 10, 130, 16, Qt::AlignLeft, + QString("Exec avg.: ").append(std::to_string(m_execution_avg).substr(0, 5).c_str()).append(" ms")); + painter.drawText(m_displayRight -150, 30, 130, 16, Qt::AlignLeft, + QString("Buff. upd. avg: ").append(std::to_string(m_refresh_avg).substr(0, 5).c_str()).append(" ms")); + painter.drawText(m_displayRight -150, 50, 130, 16, Qt::AlignLeft, + QString("Path build avg: ").append(std::to_string(m_path_avg).substr(0, 5).c_str()).append(" ms")); + painter.drawText(m_displayRight -150, 70, 130, 16, Qt::AlignLeft, + QString("Path draw avg: ").append(std::to_string(m_draw_avg).substr(0, 5).c_str()).append(" ms")); + + #endif +} + + +// Refresh data and draw the spectrum. +void SaSpectrumView::drawSpectrum(QPainter &painter) +{ + #ifdef SA_DEBUG + int draw_time = 0; + #endif + + // draw the graph only if there is any input, averaging residue or peaks + if (m_decaySum > 0 || m_processor->spectrumNotEmpty()) + { + // update data buffers and reconstruct paths + refreshPaths(); + + // draw stored paths + #ifdef SA_DEBUG + draw_time = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + #endif + // in case stereo is disabled, mono data are stored in left channel structures + if (m_controls->m_stereoModel.value()) + { + painter.fillPath(m_pathR, QBrush(m_controls->m_colorR)); + painter.fillPath(m_pathL, QBrush(m_controls->m_colorL)); + } + else + { + painter.fillPath(m_pathL, QBrush(m_controls->m_colorMono)); + } + // draw the peakBuffer only if peak hold or reference freeze is active + if (m_controls->m_peakHoldModel.value() || m_controls->m_refFreezeModel.value()) + { + if (m_controls->m_stereoModel.value()) + { + painter.setPen(QPen(m_controls->m_colorR, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawPath(m_pathPeakR); + painter.setPen(QPen(m_controls->m_colorL, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawPath(m_pathPeakL); + } + else + { + painter.setPen(QPen(m_controls->m_colorL, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawPath(m_pathPeakL); + } + } + #ifdef SA_DEBUG + draw_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - draw_time; + #endif + } + + #ifdef SA_DEBUG + // save performance measurement result + m_draw_avg = 0.95 * m_draw_avg + 0.05 * draw_time / 1000000.0; + #endif +} + + +// Read newest FFT results from SaProcessor, update local display buffers +// and build QPainter paths. +void SaSpectrumView::refreshPaths() +{ + // Reallocation lock is required for the entire function, to keep display + // buffer size consistent with block size. + QMutexLocker reloc_lock(&m_processor->m_reallocationAccess); + + // check if bin count changed and reallocate display buffers accordingly + if (m_processor->binCount() != m_displayBufferL.size()) + { + m_displayBufferL.clear(); + m_displayBufferR.clear(); + m_peakBufferL.clear(); + m_peakBufferR.clear(); + m_displayBufferL.resize(m_processor->binCount(), 0); + m_displayBufferR.resize(m_processor->binCount(), 0); + m_peakBufferL.resize(m_processor->binCount(), 0); + m_peakBufferR.resize(m_processor->binCount(), 0); + } + + // update display buffers for left and right channel + #ifdef SA_DEBUG + int refresh_time = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + #endif + m_decaySum = 0; + updateBuffers(m_processor->getSpectrumL(), m_displayBufferL.data(), m_peakBufferL.data()); + updateBuffers(m_processor->getSpectrumR(), m_displayBufferR.data(), m_peakBufferR.data()); + #ifdef SA_DEBUG + refresh_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - refresh_time; + #endif + + // if there was a freeze request, it was taken care of during the update + if (m_controls->m_refFreezeModel.value() && m_freezeRequest) + { + m_freezeRequest = false; + m_frozen = true; + } + + #ifdef SA_DEBUG + int path_time = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + #endif + // Use updated display buffers to prepare new paths for QPainter. + // This is the second slowest action (first is the subsequent drawing); use + // the resolution parameter to balance display quality and performance. + m_pathL = makePath(m_displayBufferL, m_controls->m_spectrumResolutionModel.value()); + if (m_controls->m_stereoModel.value()) + { + m_pathR = makePath(m_displayBufferR, m_controls->m_spectrumResolutionModel.value()); + } + if (m_controls->m_peakHoldModel.value() || m_controls->m_refFreezeModel.value()) + { + m_pathPeakL = makePath(m_peakBufferL, m_controls->m_envelopeResolutionModel.value()); + if (m_controls->m_stereoModel.value()) + { + m_pathPeakR = makePath(m_peakBufferR, m_controls->m_envelopeResolutionModel.value()); + } + } + #ifdef SA_DEBUG + path_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - path_time; + #endif + + #ifdef SA_DEBUG + // save performance measurement results + m_refresh_avg = 0.95 * m_refresh_avg + 0.05 * refresh_time / 1000000.0; + m_path_avg = .95f * m_path_avg + .05f * path_time / 1000000.f; + #endif +} + + +// Update display buffers: add new data, update average and peaks / reference. +// Output the sum of all displayed values -- draw only if it is non-zero. +// NOTE: The calling function is responsible for acquiring SaProcessor +// reallocation access lock! Data access lock is not needed: the final result +// buffer is updated very quickly and the worst case is that one frame will be +// part new, part old. At reasonable frame rate, such difference is invisible.. +void SaSpectrumView::updateBuffers(const float *spectrum, float *displayBuffer, float *peakBuffer) +{ + for (int n = 0; n < m_processor->binCount(); n++) + { + // Update the exponential average if enabled, or simply copy the value. + if (!m_controls->m_pauseModel.value()) + { + if (m_controls->m_smoothModel.value()) + { + const float smoothFactor = m_controls->m_averagingWeightModel.value(); + displayBuffer[n] = spectrum[n] * smoothFactor + displayBuffer[n] * (1 - smoothFactor); + } + else + { + displayBuffer[n] = spectrum[n]; + } + } + // Update peak-hold and reference freeze data (using a shared curve). + // Peak hold and freeze can be combined: decay only if not frozen. + // Ref. freeze operates on the (possibly averaged) display buffer. + if (m_controls->m_refFreezeModel.value() && m_freezeRequest) + { + peakBuffer[n] = displayBuffer[n]; + } + else if (m_controls->m_peakHoldModel.value() && !m_controls->m_pauseModel.value()) + { + if (spectrum[n] > peakBuffer[n]) + { + peakBuffer[n] = spectrum[n]; + } + else if (!m_controls->m_refFreezeModel.value()) + { + peakBuffer[n] = peakBuffer[n] * m_controls->m_peakDecayFactorModel.value(); + } + } + else if (!m_controls->m_refFreezeModel.value() && !m_controls->m_peakHoldModel.value()) + { + peakBuffer[n] = 0; + } + // take note if there was actually anything to display + m_decaySum += displayBuffer[n] + peakBuffer[n]; + } +} + + +// Use display buffer to build a path that can be drawn or filled by QPainter. +// Resolution controls the performance / quality tradeoff; the value specifies +// number of points in x axis per device pixel. Values over 1.0 still +// contribute to quality and accuracy thanks to anti-aliasing. +QPainterPath SaSpectrumView::makePath(std::vector &displayBuffer, float resolution = 1.0) +{ + // convert resolution to number of path points per logical pixel + float pixel_limit = resolution * window()->devicePixelRatio(); + + QPainterPath path; + path.moveTo(m_displayLeft, m_displayBottom); + + // Translate frequency bins to path points. + // Display is flipped: y values grow towards zero, initial max is bottom. + // Bins falling to interval [x_start, x_next) contribute to a single point. + float max = m_displayBottom; + float x_start = -1; // lower bound of currently constructed point + for (unsigned int n = 0; n < m_processor->binCount(); n++) + { + float x = freqToXPixel(binToFreq(n), m_displayWidth); + float x_next = freqToXPixel(binToFreq(n + 1), m_displayWidth); + float y = ampToYPixel(displayBuffer[n], m_displayBottom); + + // consider making a point only if x falls within display bounds + if (0 < x && x < m_displayWidth) + { + if (x_start == -1) + { + x_start = x; + // the first displayed bin is stretched to the left edge to prevent + // creating a misleading slope leading to zero (at log. scale) + path.lineTo(m_displayLeft, y + m_displayTop); + } + // Opt.: QPainter is very slow -- draw at most [pixel_limit] points + // per logical pixel. As opposed to limiting the bin count, this + // allows high resolution display if user resizes the analyzer. + // Look at bins that share the pixel and use the highest value: + max = y < max ? y : max; + // And make the final point in the middle of current interval. + if ((int)(x * pixel_limit) != (int)(x_next * pixel_limit)) + { + x = (x + x_start) / 2; + path.lineTo(x + m_displayLeft, max + m_displayTop); + max = m_displayBottom; + x_start = x_next; + } + } + else + { + // stop processing after a bin falls outside right edge + // and align it to the edge to prevent a gap + if (n > 0 && x > 0) + { + path.lineTo(m_displayRight, y + m_displayTop); + break; + } + } + } + path.lineTo(m_displayRight, m_displayBottom); + path.closeSubpath(); + return path; +} + + +// Draw background, grid and associated frequency and amplitude labels. +void SaSpectrumView::drawGrid(QPainter &painter) +{ + std::vector> *freqTics = NULL; + std::vector> *ampTics = NULL; + float pos = 0; + float label_width = 24; + float label_height = 15; + float margin = 5; + + // always draw the background + painter.fillRect(m_displayLeft, m_displayTop, + m_displayWidth, m_displayBottom, + m_controls->m_colorBG); + + // select logarithmic or linear frequency grid and draw it + if (m_controls->m_logXModel.value()) + { + freqTics = &m_logFreqTics; + } + else + { + freqTics = &m_linearFreqTics; + } + // draw frequency grid (line.first is display position) + painter.setPen(QPen(m_controls->m_colorGrid, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + for (auto &line: *freqTics) + { + painter.drawLine(m_displayLeft + freqToXPixel(line.first, m_displayWidth), + 2, + m_displayLeft + freqToXPixel(line.first, m_displayWidth), + m_displayBottom); + } + // print frequency labels (line.second is label) + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + for (auto & line: *freqTics) + { + pos = m_displayLeft + freqToXPixel(line.first, m_displayWidth); + // align first and last label to the edge if needed, otherwise center them + if (line == freqTics->front() && pos - label_width / 2 < m_displayLeft) + { + painter.drawText(m_displayLeft, m_displayBottom + margin, + label_width, label_height, Qt::AlignLeft | Qt::TextDontClip, + QString(line.second.c_str())); + } + else if (line == freqTics->back() && pos + label_width / 2 > m_displayRight) + { + painter.drawText(m_displayRight - label_width, m_displayBottom + margin, + label_width, label_height, Qt::AlignRight | Qt::TextDontClip, + QString(line.second.c_str())); + } + else + { + painter.drawText(pos - label_width / 2, m_displayBottom + margin, + label_width, label_height, Qt::AlignHCenter | Qt::TextDontClip, + QString(line.second.c_str())); + } + } + + margin = 2; + // select logarithmic or linear amplitude grid and draw it + if (m_controls->m_logYModel.value()) + { + ampTics = &m_logAmpTics; + } + else + { + ampTics = &m_linearAmpTics; + } + // draw amplitude grid + painter.setPen(QPen(m_controls->m_colorGrid, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + for (auto & line: *ampTics) + { + painter.drawLine(m_displayLeft + 1, + ampToYPixel(line.first, m_displayBottom), + m_displayRight - 1, + ampToYPixel(line.first, m_displayBottom)); + } + // print amplitude labels + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + bool stereo = m_controls->m_stereoModel.value(); + for (auto & line: *ampTics) + { + pos = ampToYPixel(line.first, m_displayBottom); + // align first and last labels to edge if needed, otherwise center them + if (line == ampTics->back() && pos < 8) + { + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorL.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + painter.drawText(m_displayLeft - label_width - margin, m_displayTop - 2, + label_width, label_height, Qt::AlignRight | Qt::AlignTop | Qt::TextDontClip, + QString(line.second.c_str())); + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorR.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + painter.drawText(m_displayRight + margin, m_displayTop - 2, + label_width, label_height, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip, + QString(line.second.c_str())); + } + else if (line == ampTics->front() && pos > m_displayBottom - label_height) + { + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorL.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + painter.drawText(m_displayLeft - label_width - margin, m_displayBottom - label_height + 2, + label_width, label_height, Qt::AlignRight | Qt::AlignBottom | Qt::TextDontClip, + QString(line.second.c_str())); + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorR.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + painter.drawText(m_displayRight + margin, m_displayBottom - label_height + 2, + label_width, label_height, Qt::AlignLeft | Qt::AlignBottom | Qt::TextDontClip, + QString(line.second.c_str())); + } + else + { + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorL.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + painter.drawText(m_displayLeft - label_width - margin, pos - label_height / 2, + label_width, label_height, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, + QString(line.second.c_str())); + if (stereo) + { + painter.setPen(QPen(m_controls->m_colorR.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + } + painter.drawText(m_displayRight + margin, pos - label_height / 2, + label_width, label_height, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, + QString(line.second.c_str())); + } + } +} + + +// Draw cursor and its coordinates if it is within display bounds. +void SaSpectrumView::drawCursor(QPainter &painter) +{ + if ( m_cursor.x() >= m_displayLeft + && m_cursor.x() <= m_displayRight + && m_cursor.y() >= m_displayTop + && m_cursor.y() <= m_displayBottom) + { + // cursor lines + painter.setPen(QPen(m_controls->m_colorGrid.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawLine(QPointF(m_cursor.x(), m_displayTop), QPointF(m_cursor.x(), m_displayBottom)); + painter.drawLine(QPointF(m_displayLeft, m_cursor.y()), QPointF(m_displayRight, m_cursor.y())); + + // coordinates: background box + QFontMetrics fontMetrics = painter.fontMetrics(); + unsigned int const box_left = 5; + unsigned int const box_top = 5; + unsigned int const box_margin = 3; + unsigned int const box_height = 2*(fontMetrics.size(Qt::TextSingleLine, "0 HzdBFS").height() + box_margin); + unsigned int const box_width = fontMetrics.size(Qt::TextSingleLine, "-99.9 dBFS").width() + 2*box_margin; + painter.setPen(QPen(m_controls->m_colorLabels.darker(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.fillRect(m_displayLeft + box_left, m_displayTop + box_top, + box_width, box_height, QColor(0, 0, 0, 64)); + + // coordinates: text + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + QString tmps; + + // frequency + int xFreq = (int)m_processor->xPixelToFreq(m_cursor.x() - m_displayLeft, m_displayWidth); + tmps = QString("%1 Hz").arg(xFreq); + painter.drawText(m_displayLeft + box_left + box_margin, + m_displayTop + box_top + box_margin, + box_width, box_height / 2, Qt::AlignLeft, tmps); + + // amplitude + float yAmp = m_processor->yPixelToAmp(m_cursor.y(), m_displayBottom); + if (m_controls->m_logYModel.value()) + { + tmps = QString(std::to_string(yAmp).substr(0, 5).c_str()).append(" dBFS"); + } + else + { + // add 0.0005 to get proper rounding to 3 decimal places + tmps = QString(std::to_string(0.0005f + yAmp).substr(0, 5).c_str()); + } + painter.drawText(m_displayLeft + box_left + box_margin, + m_displayTop + box_top + box_height / 2, + box_width, box_height / 2, Qt::AlignLeft, tmps); + } +} + + +// Wrappers for most used SaProcessor helpers (to make local code more compact). +float SaSpectrumView::binToFreq(unsigned int bin_index) +{ + return m_processor->binToFreq(bin_index); +} + + +float SaSpectrumView::freqToXPixel(float frequency, unsigned int width) +{ + return m_processor->freqToXPixel(frequency, width); +} + + +float SaSpectrumView::ampToYPixel(float amplitude, unsigned int height) +{ + return m_processor->ampToYPixel(amplitude, height); +} + + +// Generate labels suitable for logarithmic frequency scale. +// Low / high limits are in Hz. Lowest possible label is 10 Hz. +std::vector> SaSpectrumView::makeLogFreqTics(int low, int high) +{ + std::vector> result; + int i, j; + int a[] = {10, 20, 50}; // sparse series multipliers + int b[] = {14, 30, 70}; // additional (denser) series + + // generate main steps (powers of 10); use the series to specify smaller steps + for (i = 1; i <= high; i *= 10) + { + for (j = 0; j < 3; j++) + { + // insert a label from sparse series if it falls within bounds + if (i * a[j] >= low && i * a[j] <= high) + { + if (i * a[j] < 1000) + { + result.emplace_back(i * a[j], std::to_string(i * a[j])); + } + else + { + result.emplace_back(i * a[j], std::to_string(i * a[j] / 1000) + "k"); + } + } + // also insert denser series if high and low values are close + if ((log10(high) - log10(low) < 2) && (i * b[j] >= low && i * b[j] <= high)) + { + if (i * b[j] < 1500) + { + result.emplace_back(i * b[j], std::to_string(i * b[j])); + } + else + { + result.emplace_back(i * b[j], std::to_string(i * b[j] / 1000) + "k"); + } + } + } + } + return result; +} + + +// Generate labels suitable for linear frequency scale. +// Low / high limits are in Hz. +std::vector> SaSpectrumView::makeLinearFreqTics(int low, int high) +{ + std::vector> result; + int i, increment; + + // select a suitable increment based on zoom level + if (high - low < 500) {increment = 50;} + else if (high - low < 1000) {increment = 100;} + else if (high - low < 5000) {increment = 1000;} + else {increment = 2000;} + + // generate steps based on increment, starting at 0 + for (i = 0; i <= high; i += increment) + { + if (i >= low) + { + if (i < 1000) + { + result.emplace_back(i, std::to_string(i)); + } + else + { + result.emplace_back(i, std::to_string(i/1000) + "k"); + } + } + } + return result; +} + + +// Generate labels suitable for logarithmic (dB) amplitude scale. +// Low / high limits are in dB; 0 dB amplitude = 1.0 linear. +// Treating results as power ratio, i.e., 3 dB should be about twice as loud. +std::vector> SaSpectrumView::makeLogAmpTics(int low, int high) +{ + std::vector> result; + float i; + double increment; + + // Base zoom level on selected range and how close is the current height + // to the sizeHint() (denser scale for bigger window). + if ((high - low) < 20 * ((float)height() / sizeHint().height())) + { + increment = pow(10, 0.3); // 3 dB steps when really zoomed in + } + else if (high - low < 45 * ((float)height() / sizeHint().height())) + { + increment = pow(10, 0.6); // 6 dB steps when sufficiently zoomed in + } + else + { + increment = 10; // 10 dB steps otherwise + } + + // Generate n dB increments, start checking at -90 dB. Limits are tweaked + // just a little bit to make sure float comparisons do not miss edges. + for (i = 0.000000001; 10 * log10(i) <= (high + 0.001); i *= increment) + { + if (10 * log10(i) >= (low - 0.001)) + { + result.emplace_back(i, std::to_string((int)std::round(10 * log10(i)))); + } + } + return result; +} + + +// Generate labels suitable for linear amplitude scale. +// Low / high limits are in dB; 0 dB amplitude = 1.0 linear. +// Smallest possible label is 0.001, largest is 999. This includes the majority +// of useful labels; going lower or higher would require increasing margin size +// so that the text can fit. That would be a waste of space -- the linear scale +// would only make the experience worse for the main, logarithmic (dB) scale. +std::vector> SaSpectrumView::makeLinearAmpTics(int low, int high) +{ + std::vector> result; + double i, nearest; + + // make about 5 labels when window is small, 10 if it is big + float split = (float)height() / sizeHint().height() >= 1.5 ? 10.0 : 5.0; + + // convert limits to linear scale + float lin_low = pow(10, low / 10.0); + float lin_high = pow(10, high / 10.0); + + // Linear scale will vary widely, so instead of trying to craft extra nice + // multiples, just generate a few evenly spaced increments across the range, + // paying attention only to the decimal places to keep labels short. + // Limits are shifted a bit so that float comparisons do not miss edges. + for (i = 0; i <= (lin_high + 0.0001); i += (lin_high - lin_low) / split) + { + if (i >= (lin_low - 0.0001)) + { + if (i >= 9.99 && i < 99.9) + { + nearest = std::round(i); + result.emplace_back(nearest, std::to_string(nearest).substr(0, 2)); + } + else if (i >= 0.099) + { // also covers numbers above 100 + nearest = std::round(i * 10) / 10; + result.emplace_back(nearest, std::to_string(nearest).substr(0, 3)); + } + else if (i >= 0.0099) + { + nearest = std::round(i * 1000) / 1000; + result.emplace_back(nearest, std::to_string(nearest).substr(0, 4)); + } + else if (i >= 0.00099) + { + nearest = std::round(i * 10000) / 10000; + result.emplace_back(nearest, std::to_string(nearest).substr(1, 4)); + } + else if (i > -0.01 && i < 0.01) + { + result.emplace_back(i, "0"); // an exception, zero is short.. + } + } + } + return result; +} + + +// Periodic update is called by LMMS. +void SaSpectrumView::periodicUpdate() +{ + // check if the widget is visible; if it is not, processing can be paused + m_processor->setSpectrumActive(isVisible()); + // tell Qt it is time for repaint + update(); +} + + +// Handle mouse input: set new cursor position. +// For some reason (a bug?), localPos() only returns integers. As a workaround +// the fractional part is taken from windowPos() (which works correctly). +void SaSpectrumView::mouseMoveEvent(QMouseEvent *event) +{ + m_cursor = QPointF( event->localPos().x() - (event->windowPos().x() - (long)event->windowPos().x()), + event->localPos().y() - (event->windowPos().y() - (long)event->windowPos().y())); +} + +void SaSpectrumView::mousePressEvent(QMouseEvent *event) +{ + m_cursor = QPointF( event->localPos().x() - (event->windowPos().x() - (long)event->windowPos().x()), + event->localPos().y() - (event->windowPos().y() - (long)event->windowPos().y())); +} + + +// Handle resize event: rebuild grid and labels +void SaSpectrumView::resizeEvent(QResizeEvent *event) +{ + // frequency does not change density with size + // amplitude does: rebuild labels + m_logAmpTics = makeLogAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax()); + m_linearAmpTics = makeLinearAmpTics(m_processor->getAmpRangeMin(), m_processor->getAmpRangeMax()); +} + diff --git a/plugins/SpectrumAnalyzer/SaSpectrumView.h b/plugins/SpectrumAnalyzer/SaSpectrumView.h new file mode 100644 index 00000000000..b59264d9ce7 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaSpectrumView.h @@ -0,0 +1,131 @@ +/* SaSpectrumView.h - declaration of SaSpectrumView class. + * + * Copyright (c) 2019 Martin Pavelek + * + * Based partially on Eq plugin code, + * Copyright (c) 2014 David French + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef SASPECTRUMVIEW_H +#define SASPECTRUMVIEW_H + +#include "SaControls.h" + +#include +#include +#include +#include + +class QMouseEvent; +class QPainter; +class SaProcessor; + +//! Widget that displays a spectrum curve and frequency / amplitude grid +class SaSpectrumView : public QWidget +{ + Q_OBJECT +public: + explicit SaSpectrumView(SaControls *controls, SaProcessor *processor, QWidget *_parent = 0); + virtual ~SaSpectrumView() {} + + QSize sizeHint() const override {return QSize(400, 200);} + +protected: + void paintEvent(QPaintEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private slots: + void periodicUpdate(); + +private: + const SaControls *m_controls; + SaProcessor *m_processor; + + // grid labels (position, label) and methods to generate them + std::vector> m_logFreqTics; // 10-20-50... Hz + std::vector> m_linearFreqTics; // 2k-4k-6k... Hz + std::vector> m_logAmpTics; // dB + std::vector> m_linearAmpTics; // 0..1 + + std::vector> makeLogFreqTics(int low, int high); + std::vector> makeLinearFreqTics(int low, int high); + std::vector> makeLogAmpTics(int low, int high); + std::vector> makeLinearAmpTics(int low, int high); + + // currently selected ranges (see SaControls.h for enum definitions) + int m_freqRangeIndex; + int m_ampRangeIndex; + + // draw the grid and all labels based on selected ranges + void drawGrid(QPainter &painter); + + // local buffers for frequency bin values and a method to update them + // (mainly needed for averaging and to keep track of peak values) + std::vector m_displayBufferL; + std::vector m_displayBufferR; + std::vector m_peakBufferL; + std::vector m_peakBufferR; + void updateBuffers(const float *spectrum, float *displayBuffer, float *peakBuffer); + + // final paths to be drawn by QPainter and methods to build them + QPainterPath m_pathL; + QPainterPath m_pathR; + QPainterPath m_pathPeakL; + QPainterPath m_pathPeakR; + void refreshPaths(); + QPainterPath makePath(std::vector &displayBuffer, float resolution); + + // helper variables for path drawing + float m_decaySum; // indicates if there is anything left to draw + bool m_freezeRequest; // new reference should be acquired + bool m_frozen; // a reference is currently stored in the peakBuffer + + // top level: refresh buffers, make paths and draw the spectrum + void drawSpectrum(QPainter &painter); + + // current cursor location and a method to draw it + QPointF m_cursor; + void drawCursor(QPainter &painter); + + // wrappers for most used SaProcessor conversion helpers + // (to make local code more readable) + float binToFreq(unsigned int bin_index); + float freqToXPixel(float frequency, unsigned int width); + float ampToYPixel(float amplitude, unsigned int height); + + // current boundaries for drawing + unsigned int m_displayTop; + unsigned int m_displayBottom; + unsigned int m_displayLeft; + unsigned int m_displayRight; + unsigned int m_displayWidth; + + #ifdef SA_DEBUG + float m_execution_avg; + float m_refresh_avg; + float m_path_avg; + float m_draw_avg; + #endif +}; +#endif // SASPECTRUMVIEW_H + diff --git a/plugins/SpectrumAnalyzer/SaWaterfallView.cpp b/plugins/SpectrumAnalyzer/SaWaterfallView.cpp new file mode 100644 index 00000000000..e015d31ef74 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaWaterfallView.cpp @@ -0,0 +1,343 @@ +/* SaWaterfallViewView.cpp - implementation of SaWaterfallViewView class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "SaWaterfallView.h" + +#include +#ifdef SA_DEBUG + #include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "EffectControlDialog.h" +#include "GuiApplication.h" +#include "MainWindow.h" +#include "SaProcessor.h" + + +SaWaterfallView::SaWaterfallView(SaControls *controls, SaProcessor *processor, QWidget *_parent) : + QWidget(_parent), + m_controls(controls), + m_processor(processor) +{ + m_controlDialog = (EffectControlDialog*) _parent; + setMinimumSize(300, 150); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + connect(gui->mainWindow(), SIGNAL(periodicUpdate()), this, SLOT(periodicUpdate())); + + m_displayTop = 1; + m_displayBottom = height() -2; + m_displayLeft = 26; + m_displayRight = width() -26; + m_displayWidth = m_displayRight - m_displayLeft; + m_displayHeight = m_displayBottom - m_displayTop; + + m_timeTics = makeTimeTics(); + m_oldSecondsPerLine = 0; + m_oldHeight = 0; + + m_cursor = QPointF(0, 0); + + #ifdef SA_DEBUG + m_execution_avg = 0; + #endif +} + + +// Compose and draw all the content; called by Qt. +// Not as performance sensitive as SaSpectrumView, most of the processing is +// done directly in SaProcessor. +void SaWaterfallView::paintEvent(QPaintEvent *event) +{ + #ifdef SA_DEBUG + unsigned int draw_time = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + #endif + + // update boundary + m_displayBottom = height() -2; + m_displayRight = width() -26; + m_displayWidth = m_displayRight - m_displayLeft; + m_displayHeight = m_displayBottom - m_displayTop; + float label_width = 20; + float label_height = 16; + float margin = 2; + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, true); + + // check if time labels need to be rebuilt + if (secondsPerLine() != m_oldSecondsPerLine || m_processor->waterfallHeight() != m_oldHeight) + { + m_timeTics = makeTimeTics(); + m_oldSecondsPerLine = secondsPerLine(); + m_oldHeight = m_processor->waterfallHeight(); + } + + // print time labels + float pos = 0; + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + for (auto & line: m_timeTics) + { + pos = timeToYPixel(line.first, m_displayHeight); + // align first and last label to the edge if needed, otherwise center them + if (line == m_timeTics.front() && pos < label_height / 2) + { + painter.drawText(m_displayLeft - label_width - margin, m_displayTop - 1, + label_width, label_height, Qt::AlignRight | Qt::AlignTop | Qt::TextDontClip, + QString(line.second.c_str())); + painter.drawText(m_displayRight + margin, m_displayTop - 1, + label_width, label_height, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip, + QString(line.second.c_str())); + } + else if (line == m_timeTics.back() && pos > m_displayBottom - label_height + 2) + { + painter.drawText(m_displayLeft - label_width - margin, m_displayBottom - label_height, + label_width, label_height, Qt::AlignRight | Qt::AlignBottom | Qt::TextDontClip, + QString(line.second.c_str())); + painter.drawText(m_displayRight + margin, m_displayBottom - label_height + 2, + label_width, label_height, Qt::AlignLeft | Qt::AlignBottom | Qt::TextDontClip, + QString(line.second.c_str())); + } + else + { + painter.drawText(m_displayLeft - label_width - margin, pos - label_height / 2, + label_width, label_height, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, + QString(line.second.c_str())); + painter.drawText(m_displayRight + margin, pos - label_height / 2, + label_width, label_height, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, + QString(line.second.c_str())); + } + } + + // draw the spectrogram precomputed in SaProcessor + if (m_processor->waterfallNotEmpty()) + { + QMutexLocker lock(&m_processor->m_reallocationAccess); + QImage temp = QImage(m_processor->getHistory(), // raw pixel data to display + m_processor->waterfallWidth(), // width = number of frequency bins + m_processor->waterfallHeight(), // height = number of history lines + QImage::Format_RGB32); + lock.unlock(); + temp.setDevicePixelRatio(devicePixelRatio()); // display at native resolution + painter.drawImage(m_displayLeft, m_displayTop, + temp.scaled(m_displayWidth * devicePixelRatio(), + m_displayHeight * devicePixelRatio(), + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation)); + m_processor->flipRequest(); + } + else + { + painter.fillRect(m_displayLeft, m_displayTop, m_displayWidth, m_displayHeight, QColor(0,0,0)); + } + + // draw cursor (if it is within bounds) + drawCursor(painter); + + // always draw the outline + painter.setPen(QPen(m_controls->m_colorGrid, 2, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawRoundedRect(m_displayLeft, m_displayTop, m_displayWidth, m_displayHeight, 2.0, 2.0); + + #ifdef SA_DEBUG + draw_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - draw_time; + m_execution_avg = 0.95 * m_execution_avg + 0.05 * draw_time / 1000000.0; + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawText(m_displayRight -150, 10, 100, 16, Qt::AlignLeft, + QString("Exec avg.: ").append(std::to_string(m_execution_avg).substr(0, 5).c_str()).append(" ms")); + #endif +} + + +// Helper functions for time conversion +float SaWaterfallView::samplesPerLine() +{ + return (float)m_processor->inBlockSize() / m_controls->m_windowOverlapModel.value(); +} + +float SaWaterfallView::secondsPerLine() +{ + return samplesPerLine() / m_processor->getSampleRate(); +} + + +// Convert time value to Y coordinate for display of given height. +float SaWaterfallView::timeToYPixel(float time, int height) +{ + float pixels_per_line = (float)height / m_processor->waterfallHeight(); + + return pixels_per_line * time / secondsPerLine(); +} + + +// Convert Y coordinate on display of given height back to time value. +float SaWaterfallView::yPixelToTime(float position, int height) +{ + if (height == 0) {height = 1;} + float pixels_per_line = (float)height / m_processor->waterfallHeight(); + + return (position / pixels_per_line) * secondsPerLine(); +} + + +// Generate labels for linear time scale. +std::vector> SaWaterfallView::makeTimeTics() +{ + std::vector> result; + float i; + + // get time value of the last line + float limit = yPixelToTime(m_displayBottom, m_displayHeight); + + // set increment to about 30 pixels (but min. 0.1 s) + float increment = std::round(10 * limit / (m_displayHeight / 30)) / 10; + if (increment < 0.1) {increment = 0.1;} + + // NOTE: labels positions are rounded to match the (rounded) label value + for (i = 0; i <= limit; i += increment) + { + if (i > 99) + { + result.emplace_back(std::round(i), std::to_string(std::round(i)).substr(0, 3)); + } + else if (i < 10) + { + result.emplace_back(std::round(i * 10) / 10, std::to_string(std::round(i * 10) / 10).substr(0, 3)); + } + else + { + result.emplace_back(std::round(i), std::to_string(std::round(i)).substr(0, 2)); + } + } + return result; +} + + +// Periodically trigger repaint and check if the widget is visible. +// If it is not, stop drawing and inform the processor. +void SaWaterfallView::periodicUpdate() +{ + m_processor->setWaterfallActive(isVisible()); + if (isVisible()) {update();} +} + + +// Adjust window size and widget visibility when waterfall is enabled or disabbled. +void SaWaterfallView::updateVisibility() +{ + // get container of the control dialog to be resized if needed + QWidget *subWindow = m_controlDialog->parentWidget(); + + + if (m_controls->m_waterfallModel.value()) + { + // clear old data before showing the waterfall + m_processor->clearHistory(); + setVisible(true); + + // increase window size if it is too small + if (subWindow->size().height() < m_controlDialog->sizeHint().height()) + { + subWindow->resize(subWindow->size().width(), m_controlDialog->sizeHint().height()); + } + } + else + { + setVisible(false); + // decrease window size only if it does not violate sizeHint + subWindow->resize(subWindow->size().width(), m_controlDialog->sizeHint().height()); + } +} + + +// Draw cursor and its coordinates if it is within display bounds. +void SaWaterfallView::drawCursor(QPainter &painter) +{ + if ( m_cursor.x() >= m_displayLeft + && m_cursor.x() <= m_displayRight + && m_cursor.y() >= m_displayTop + && m_cursor.y() <= m_displayBottom) + { + // cursor lines + painter.setPen(QPen(m_controls->m_colorGrid.lighter(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawLine(QPointF(m_cursor.x(), m_displayTop), QPointF(m_cursor.x(), m_displayBottom)); + painter.drawLine(QPointF(m_displayLeft, m_cursor.y()), QPointF(m_displayRight, m_cursor.y())); + + // coordinates: background box + QFontMetrics fontMetrics = painter.fontMetrics(); + unsigned int const box_left = 5; + unsigned int const box_top = 5; + unsigned int const box_margin = 3; + unsigned int const box_height = 2*(fontMetrics.size(Qt::TextSingleLine, "0 Hz").height() + box_margin); + unsigned int const box_width = fontMetrics.size(Qt::TextSingleLine, "20000 Hz ").width() + 2*box_margin; + painter.setPen(QPen(m_controls->m_colorLabels.darker(), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.fillRect(m_displayLeft + box_left, m_displayTop + box_top, + box_width, box_height, QColor(0, 0, 0, 64)); + + // coordinates: text + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + QString tmps; + + // frequency + int freq = (int)m_processor->xPixelToFreq(m_cursor.x() - m_displayLeft, m_displayWidth); + tmps = QString("%1 Hz").arg(freq); + painter.drawText(m_displayLeft + box_left + box_margin, + m_displayTop + box_top + box_margin, + box_width, box_height / 2, Qt::AlignLeft, tmps); + + // time + float time = yPixelToTime(m_cursor.y(), m_displayBottom); + tmps = QString(std::to_string(time).substr(0, 5).c_str()).append(" s"); + painter.drawText(m_displayLeft + box_left + box_margin, + m_displayTop + box_top + box_height / 2, + box_width, box_height / 2, Qt::AlignLeft, tmps); + } +} + + +// Handle mouse input: set new cursor position. +// For some reason (a bug?), localPos() only returns integers. As a workaround +// the fractional part is taken from windowPos() (which works correctly). +void SaWaterfallView::mouseMoveEvent(QMouseEvent *event) +{ + m_cursor = QPointF( event->localPos().x() - (event->windowPos().x() - (long)event->windowPos().x()), + event->localPos().y() - (event->windowPos().y() - (long)event->windowPos().y())); +} + +void SaWaterfallView::mousePressEvent(QMouseEvent *event) +{ + m_cursor = QPointF( event->localPos().x() - (event->windowPos().x() - (long)event->windowPos().x()), + event->localPos().y() - (event->windowPos().y() - (long)event->windowPos().y())); +} + + +// Handle resize event: rebuild time labels +void SaWaterfallView::resizeEvent(QResizeEvent *event) +{ + m_timeTics = makeTimeTics(); +} diff --git a/plugins/SpectrumAnalyzer/SaWaterfallView.h b/plugins/SpectrumAnalyzer/SaWaterfallView.h new file mode 100644 index 00000000000..bd91d6d1641 --- /dev/null +++ b/plugins/SpectrumAnalyzer/SaWaterfallView.h @@ -0,0 +1,90 @@ +/* SaWaterfallView.h - declaration of SaWaterfallView class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ +#ifndef SAWATERFALLVIEW_H +#define SAWATERFALLVIEW_H + +#include +#include +#include +#include +#include + +#include "SaControls.h" +#include "SaProcessor.h" + +class QMouseEvent; + +// Widget that displays a spectrum waterfall (spectrogram) and time labels. +class SaWaterfallView : public QWidget +{ + Q_OBJECT +public: + explicit SaWaterfallView(SaControls *controls, SaProcessor *processor, QWidget *_parent = 0); + virtual ~SaWaterfallView() {} + + QSize sizeHint() const override {return QSize(400, 350);} + + // Check if waterfall should be displayed and adjust window size if needed. + void updateVisibility(); + +protected: + void paintEvent(QPaintEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private slots: + void periodicUpdate(); + +private: + const SaControls *m_controls; + SaProcessor *m_processor; + const EffectControlDialog *m_controlDialog; + + // Methods and data used to make time labels + float m_oldSecondsPerLine; + float m_oldHeight; + float samplesPerLine(); + float secondsPerLine(); + float timeToYPixel(float time, int height); + float yPixelToTime(float position, int height); + std::vector> makeTimeTics(); + std::vector> m_timeTics; // 0..n (s) + + // current cursor location and a method to draw it + QPointF m_cursor; + void drawCursor(QPainter &painter); + + // current boundaries for drawing + unsigned int m_displayTop; + unsigned int m_displayBottom; + unsigned int m_displayLeft; + unsigned int m_displayRight; + unsigned int m_displayWidth; + unsigned int m_displayHeight; + + #ifdef SA_DEBUG + float m_execution_avg; + #endif +}; +#endif // SAWATERFALLVIEW_H diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzer.cpp b/plugins/SpectrumAnalyzer/SpectrumAnalyzer.cpp deleted file mode 100644 index 0b947a3ba36..00000000000 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzer.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * SpectrumAnalyzer.cpp - spectrum analyzer effect plugin - * - * Copyright (c) 2008-2014 Tobias Doerffel - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#include "SpectrumAnalyzer.h" - -#include "embed.h" -#include "plugin_export.h" - -extern "C" -{ - -Plugin::Descriptor PLUGIN_EXPORT spectrumanalyzer_plugin_descriptor = -{ - STRINGIFY( PLUGIN_NAME ), - "Spectrum Analyzer", - QT_TRANSLATE_NOOP( "pluginBrowser", "Graphical spectrum analyzer plugin" ), - "Tobias Doerffel ", - 0x0100, - Plugin::Effect, - new PluginPixmapLoader(), - NULL, - NULL -} ; - -} - - - -SpectrumAnalyzer::SpectrumAnalyzer( Model * _parent, - const Descriptor::SubPluginFeatures::Key * _key ) : - Effect( &spectrumanalyzer_plugin_descriptor, _parent, _key ), - m_saControls( this ), - m_framesFilledUp( 0 ), - m_energy( 0 ) -{ - memset( m_buffer, 0, sizeof( m_buffer ) ); - - m_specBuf = (fftwf_complex *) fftwf_malloc( ( FFT_BUFFER_SIZE + 1 ) * sizeof( fftwf_complex ) ); - m_fftPlan = fftwf_plan_dft_r2c_1d( FFT_BUFFER_SIZE*2, m_buffer, m_specBuf, FFTW_MEASURE ); -} - - - - -SpectrumAnalyzer::~SpectrumAnalyzer() -{ - fftwf_destroy_plan( m_fftPlan ); - fftwf_free( m_specBuf ); -} - - - - -bool SpectrumAnalyzer::processAudioBuffer( sampleFrame* _buf, const fpp_t _frames ) -{ - if( !isEnabled() || !isRunning () ) - { - return false; - } - - if( !m_saControls.isViewVisible() ) - { - return true; - } - - fpp_t f = 0; - if( _frames > FFT_BUFFER_SIZE ) - { - m_framesFilledUp = 0; - f = _frames - FFT_BUFFER_SIZE; - } - - const int cm = m_saControls.m_channelMode.value(); - - switch( cm ) - { - case MergeChannels: - for( ; f < _frames; ++f ) - { - m_buffer[m_framesFilledUp] = - ( _buf[f][0] + _buf[f][1] ) * 0.5; - ++m_framesFilledUp; - } - break; - case LeftChannel: - for( ; f < _frames; ++f ) - { - m_buffer[m_framesFilledUp] = _buf[f][0]; - ++m_framesFilledUp; - } - break; - case RightChannel: - for( ; f < _frames; ++f ) - { - m_buffer[m_framesFilledUp] = _buf[f][1]; - ++m_framesFilledUp; - } - break; - } - - if( m_framesFilledUp < FFT_BUFFER_SIZE ) - { - return isRunning(); - } - - -// hanming( m_buffer, FFT_BUFFER_SIZE, HAMMING ); - - const sample_rate_t sr = Engine::mixer()->processingSampleRate(); - const int LOWEST_FREQ = 0; - const int HIGHEST_FREQ = sr / 2; - - fftwf_execute( m_fftPlan ); - absspec( m_specBuf, m_absSpecBuf, FFT_BUFFER_SIZE+1 ); - if( m_saControls.m_linearSpec.value() ) - { - compressbands( m_absSpecBuf, m_bands, FFT_BUFFER_SIZE+1, - MAX_BANDS, - (int)(LOWEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(sr/2)), - (int)(HIGHEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(sr/2))); - m_energy = maximum( m_bands, MAX_BANDS ) / maximum( m_buffer, FFT_BUFFER_SIZE ); - } - else - { - calc13octaveband31( m_absSpecBuf, m_bands, FFT_BUFFER_SIZE+1, sr/2.0 ); - m_energy = signalpower( m_buffer, FFT_BUFFER_SIZE ) / maximum( m_buffer, FFT_BUFFER_SIZE ); - } - - - m_framesFilledUp = 0; - - checkGate( 1 ); - - return isRunning(); -} - - - - - -extern "C" -{ - -// necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* parent, void* data ) -{ - return new SpectrumAnalyzer( parent, static_cast( data ) ); -} - -} - diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzer.h b/plugins/SpectrumAnalyzer/SpectrumAnalyzer.h deleted file mode 100644 index c9235117680..00000000000 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzer.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * SpectrumAnalyzer.h - spectrum anaylzer effect plugin - * - * Copyright (c) 2008-2014 Tobias Doerffel - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - - -#ifndef _SPECTRUM_ANALYZER_H -#define _SPECTRUM_ANALYZER_H - -#include "Effect.h" -#include "fft_helpers.h" -#include "SpectrumAnalyzerControls.h" - - -const int MAX_BANDS = 249; - - -class SpectrumAnalyzer : public Effect -{ -public: - enum ChannelModes - { - MergeChannels, - LeftChannel, - RightChannel - } ; - - SpectrumAnalyzer( Model * _parent, - const Descriptor::SubPluginFeatures::Key * _key ); - virtual ~SpectrumAnalyzer(); - virtual bool processAudioBuffer( sampleFrame * _buf, - const fpp_t _frames ); - - virtual EffectControls * controls() - { - return( &m_saControls ); - } - - -private: - SpectrumAnalyzerControls m_saControls; - - fftwf_plan m_fftPlan; - - fftwf_complex * m_specBuf; - float m_absSpecBuf[FFT_BUFFER_SIZE+1]; - float m_buffer[FFT_BUFFER_SIZE*2]; - int m_framesFilledUp; - - float m_bands[MAX_BANDS]; - float m_energy; - - friend class SpectrumAnalyzerControls; - friend class SpectrumView; - -} ; - - -#endif diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.cpp b/plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.cpp deleted file mode 100644 index 05b1ed08a5d..00000000000 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * SpectrumAnalyzerControlDialog.cpp - view for spectrum analyzer - * - * Copyright (c) 2008-2014 Tobias Doerffel - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#include - -#include -#include - -#include "SpectrumAnalyzer.h" -#include "MainWindow.h" -#include "GuiApplication.h" -#include "LedCheckbox.h" -#include "embed.h" - - -static inline void darken( QImage& img, int x, int y, int w, int h ) -{ - int imgWidth = img.width(); - QRgb * base = ( (QRgb *) img.bits() ) + y*imgWidth + x; - for( int y = 0; y < h; ++y ) - { - QRgb * d = base + y*imgWidth; - for( int x = 0; x < w; ++x ) - { - // shift each color component by 1 bit and set alpha - // to 0xff - d[x] = ( ( d[x] >> 1 ) & 0x7f7f7f7f ) | 0xff000000; - } - } -} - - - -class SpectrumView : public QWidget -{ -public: - SpectrumView( SpectrumAnalyzer* s, QWidget * _parent ) : - QWidget( _parent ), - m_sa( s ), - m_backgroundPlain( PLUGIN_NAME::getIconPixmap( "spectrum_background_plain" ).toImage() ), - m_background( PLUGIN_NAME::getIconPixmap( "spectrum_background" ).toImage() ) - { - setFixedSize( 249, 151 ); - connect( gui->mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( update() ) ); - setAttribute( Qt::WA_OpaquePaintEvent, true ); - } - - virtual ~SpectrumView() - { - } - - virtual void paintEvent( QPaintEvent* event ) - { - QPainter p( this ); - QImage i = m_sa->m_saControls.m_linearSpec.value() ? - m_backgroundPlain : m_background; - const float e = m_sa->m_energy; - if( e <= 0 ) - { - darken( i, 0, 0, i.width(), i.height() ); - p.drawImage( 0, 0, i ); - return; - } - - const bool lin_y = m_sa->m_saControls.m_linearYAxis.value(); - float * b = m_sa->m_bands; - const int LOWER_Y = -60; // dB - int h; - const int fh = height(); - if( m_sa->m_saControls.m_linearSpec.value() ) - { - if( lin_y ) - { - for( int x = 0; x < MAX_BANDS; ++x, ++b ) - { - h = fh * 2.0 / 3.0 * (*b / e ); - if( h < 0 ) h = 0; else if( h >= fh ) continue; - darken( i, x, 0, 1, fh-h ); - } - } - else - { - for( int x = 0; x < MAX_BANDS; ++x, ++b ) - { - h = (int)( fh * 2.0 / 3.0 * (20*(log10( *b / e ) ) - LOWER_Y ) / (-LOWER_Y ) ); - if( h < 0 ) h = 0; else if( h >= fh ) continue; - darken( i, x, 0, 1, fh-h ); - } - } - } - else - { - if( lin_y ) - { - for( int x = 0; x < 31; ++x, ++b ) - { - h = fh * 2.0 / 3.0 * ( 1.2 * *b / e ); - if( h < 0 ) h = 0; else if( h >= fh ) continue; else h = ( h / 3 ) * 3; - darken( i, x*8, 0, 8, fh-h ); - } - } - else - { - for( int x = 0; x < 31; ++x, ++b ) - { - h = (int)( fh * 2.0 / 3.0 * (20*(log10( *b / e ) ) - LOWER_Y ) / (-LOWER_Y ) ); - if( h < 0 ) h = 0; else if( h >= fh ) continue; else h = ( h / 3 ) * 3; - darken( i, x*8, 0, 8, fh-h ); - } - } - darken( i, 31*8, 0, 1, fh ); - } - p.drawImage( 0, 0, i ); - } - - -private: - SpectrumAnalyzer * m_sa; - QImage m_backgroundPlain; - QImage m_background; - -} ; - - - - -SpectrumAnalyzerControlDialog::SpectrumAnalyzerControlDialog( SpectrumAnalyzerControls* controls ) : - EffectControlDialog( controls ), - m_controls( controls ), - m_logXAxis( PLUGIN_NAME::getIconPixmap( "log_x_axis" ) ), - m_logYAxis( PLUGIN_NAME::getIconPixmap( "log_y_axis" ) ) -{ - setAutoFillBackground( true ); - QPalette pal; - pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "background" ) ); - setFixedSize( 293, 205 ); - setPalette( pal ); -/* QVBoxLayout * l = new QVBoxLayout( this );*/ - SpectrumView* v = new SpectrumView( controls->m_effect, this ); - v->move( 34, 10 ); - - LedCheckBox * lin_spec = new LedCheckBox( tr( "Linear spectrum" ), this ); - lin_spec->move( 32, 182 ); - lin_spec->setModel( &controls->m_linearSpec ); - - LedCheckBox * lin_y = new LedCheckBox( tr( "Linear Y axis" ), this ); - lin_y->move( 137, 182 ); - lin_y->setModel( &controls->m_linearYAxis ); - - connect( &controls->m_linearSpec, SIGNAL( dataChanged() ), this, SLOT( update() ) ); - connect( &controls->m_linearYAxis, SIGNAL( dataChanged() ), this, SLOT( update() ) ); -/* l->addWidget( v ); - l->addWidget( lin_spec ); - l->addWidget( lin_y );*/ - -} - - -void SpectrumAnalyzerControlDialog::paintEvent( QPaintEvent * ) -{ - QPainter p( this ); - - if( !m_controls->m_linearSpec.value() ) - { - p.drawPixmap( 33, 165, m_logXAxis ); - } - - if( !m_controls->m_linearYAxis.value() ) - { - p.drawPixmap( 10, 29, m_logYAxis); - } - -} diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.h b/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.h deleted file mode 100644 index e46407863ae..00000000000 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControls.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * SpectrumAnalyzerControls.h - controls for spectrum-analyzer - * - * Copyright (c) 2008-2014 Tobias Doerffel - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#ifndef SPECTRUM_ANALYZER_CONTROLS_H -#define SPECTRUM_ANALYZER_CONTROLS_H - -#include "EffectControls.h" -#include "SpectrumAnalyzerControlDialog.h" -#include "Knob.h" - - -class SpectrumAnalyzer; - - -class SpectrumAnalyzerControls : public EffectControls -{ - Q_OBJECT -public: - SpectrumAnalyzerControls( SpectrumAnalyzer* effect ); - virtual ~SpectrumAnalyzerControls() - { - } - - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const - { - return "spectrumanaylzercontrols"; - } - - virtual int controlCount() - { - return 1; - } - - virtual EffectControlDialog * createView() - { - return new SpectrumAnalyzerControlDialog( this ); - } - - -private: - SpectrumAnalyzer* m_effect; - BoolModel m_linearSpec; - BoolModel m_linearYAxis; - IntModel m_channelMode; - - friend class SpectrumAnalyzer; - friend class SpectrumAnalyzerControlDialog; - friend class SpectrumView; - -} ; - -#endif diff --git a/plugins/SpectrumAnalyzer/advanced_off.svg b/plugins/SpectrumAnalyzer/advanced_off.svg new file mode 100644 index 00000000000..6d3ed82b105 --- /dev/null +++ b/plugins/SpectrumAnalyzer/advanced_off.svg @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/advanced_on.svg b/plugins/SpectrumAnalyzer/advanced_on.svg new file mode 100644 index 00000000000..9e6b1ca3fb2 --- /dev/null +++ b/plugins/SpectrumAnalyzer/advanced_on.svg @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/advanced_src.svg b/plugins/SpectrumAnalyzer/advanced_src.svg new file mode 100644 index 00000000000..ae201aad0a8 --- /dev/null +++ b/plugins/SpectrumAnalyzer/advanced_src.svg @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + ADV. + + + diff --git a/plugins/SpectrumAnalyzer/background.png b/plugins/SpectrumAnalyzer/background.png deleted file mode 100644 index e375f7d3403..00000000000 Binary files a/plugins/SpectrumAnalyzer/background.png and /dev/null differ diff --git a/plugins/SpectrumAnalyzer/block_size.svg b/plugins/SpectrumAnalyzer/block_size.svg new file mode 100644 index 00000000000..e9c4806ec94 --- /dev/null +++ b/plugins/SpectrumAnalyzer/block_size.svg @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/freeze.svg b/plugins/SpectrumAnalyzer/freeze.svg new file mode 100644 index 00000000000..4c9a43c1284 --- /dev/null +++ b/plugins/SpectrumAnalyzer/freeze.svg @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/freeze_off.svg b/plugins/SpectrumAnalyzer/freeze_off.svg new file mode 100644 index 00000000000..b6353d7a768 --- /dev/null +++ b/plugins/SpectrumAnalyzer/freeze_off.svg @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/log_x_axis.png b/plugins/SpectrumAnalyzer/log_x_axis.png deleted file mode 100644 index 97c5e729dff..00000000000 Binary files a/plugins/SpectrumAnalyzer/log_x_axis.png and /dev/null differ diff --git a/plugins/SpectrumAnalyzer/log_y_axis.png b/plugins/SpectrumAnalyzer/log_y_axis.png deleted file mode 100644 index e20d27001fa..00000000000 Binary files a/plugins/SpectrumAnalyzer/log_y_axis.png and /dev/null differ diff --git a/plugins/SpectrumAnalyzer/pause.svg b/plugins/SpectrumAnalyzer/pause.svg new file mode 100644 index 00000000000..d28a93aa515 --- /dev/null +++ b/plugins/SpectrumAnalyzer/pause.svg @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/play.svg b/plugins/SpectrumAnalyzer/play.svg new file mode 100644 index 00000000000..eb3178284b9 --- /dev/null +++ b/plugins/SpectrumAnalyzer/play.svg @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/spectrum_background.png b/plugins/SpectrumAnalyzer/spectrum_background.png deleted file mode 100644 index b65491bc39a..00000000000 Binary files a/plugins/SpectrumAnalyzer/spectrum_background.png and /dev/null differ diff --git a/plugins/SpectrumAnalyzer/spectrum_background_plain.png b/plugins/SpectrumAnalyzer/spectrum_background_plain.png deleted file mode 100644 index ba9bcd1c89d..00000000000 Binary files a/plugins/SpectrumAnalyzer/spectrum_background_plain.png and /dev/null differ diff --git a/plugins/SpectrumAnalyzer/window.svg b/plugins/SpectrumAnalyzer/window.svg new file mode 100644 index 00000000000..5d0bd7dbdf7 --- /dev/null +++ b/plugins/SpectrumAnalyzer/window.svg @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/x_linear.svg b/plugins/SpectrumAnalyzer/x_linear.svg new file mode 100644 index 00000000000..cef7886709f --- /dev/null +++ b/plugins/SpectrumAnalyzer/x_linear.svg @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/x_log.svg b/plugins/SpectrumAnalyzer/x_log.svg new file mode 100644 index 00000000000..8b8dc8b5a26 --- /dev/null +++ b/plugins/SpectrumAnalyzer/x_log.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/y_linear.svg b/plugins/SpectrumAnalyzer/y_linear.svg new file mode 100644 index 00000000000..69c39bb0592 --- /dev/null +++ b/plugins/SpectrumAnalyzer/y_linear.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/SpectrumAnalyzer/y_log.svg b/plugins/SpectrumAnalyzer/y_log.svg new file mode 100644 index 00000000000..645e09e5ac6 --- /dev/null +++ b/plugins/SpectrumAnalyzer/y_log.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/Vectorscope/CMakeLists.txt b/plugins/Vectorscope/CMakeLists.txt new file mode 100644 index 00000000000..b73ff76d589 --- /dev/null +++ b/plugins/Vectorscope/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) +BUILD_PLUGIN(vectorscope Vectorscope.cpp VecControls.cpp VecControlsDialog.cpp VectorView.cpp +MOCFILES VecControls.h VecControlsDialog.h VectorView.h EMBEDDED_RESOURCES logo.png) diff --git a/plugins/Vectorscope/README.md b/plugins/Vectorscope/README.md new file mode 100644 index 00000000000..18b218f6d9d --- /dev/null +++ b/plugins/Vectorscope/README.md @@ -0,0 +1,14 @@ +# Vectorscope plugin + +## Overview + +Vectorscope is a simple stereo field visualizer. Samples are plotted into a graph, with left and right channels providing the coordinates. Previously drawn samples quickly fade away and are continuously replaced by new samples, creating a real-time plot of the most recently played samples. + +Similar to other effect plugins, the top-level widget is VecControlDialog. It displays configuration knobs and the main VectorView widget. The back-end configuration class is VecControls, which holds all models and configuration values. + +VectorView computes and shows the plot. It gets data for processing from the Vectorscope class, which handles the interface with LMMS. In order to avoid any stalling of the realtime-sensitive audio thread, data are exchanged through a lockless ring buffer. + +## Changelog + + 1.0.0 2019-11-21 + - initial release diff --git a/plugins/Vectorscope/VecControls.cpp b/plugins/Vectorscope/VecControls.cpp new file mode 100644 index 00000000000..0e7a2d06160 --- /dev/null +++ b/plugins/Vectorscope/VecControls.cpp @@ -0,0 +1,70 @@ +/* + * VecControls.cpp - definition of VecControls class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "VecControls.h" + +#include + +#include "VecControlsDialog.h" +#include "Vectorscope.h" + + +VecControls::VecControls(Vectorscope *effect) : + EffectControls(effect), + m_effect(effect), + + // initialize models and set default values + m_persistenceModel(0.5f, 0.0f, 1.0f, 0.05f, this, tr("Display persistence amount")), + m_logarithmicModel(false, this, tr("Logarithmic scale")), + m_highQualityModel(false, this, tr("High quality")) +{ + // Colors (percentages include sRGB gamma correction) + m_colorFG = QColor(60, 255, 130, 255); // ~LMMS green + m_colorGrid = QColor(76, 80, 84, 128); // ~60 % gray (slightly cold / blue), 50 % transparent + m_colorLabels = QColor(76, 80, 84, 255); // ~60 % gray (slightly cold / blue) + m_colorOutline = QColor(30, 34, 38, 255); // ~40 % gray (slightly cold / blue) +} + + +// Create the VecControlDialog widget which handles display of GUI elements. +EffectControlDialog* VecControls::createView() +{ + return new VecControlsDialog(this); +} + + +void VecControls::loadSettings(const QDomElement &element) +{ + m_persistenceModel.loadSettings(element, "Persistence"); + m_logarithmicModel.loadSettings(element, "Logarithmic"); + m_highQualityModel.loadSettings(element, "HighQuality"); +} + + +void VecControls::saveSettings(QDomDocument &document, QDomElement &element) +{ + m_persistenceModel.saveSettings(document, element, "Persistence"); + m_logarithmicModel.saveSettings(document, element, "Logarithmic"); + m_highQualityModel.saveSettings(document, element, "HighQuality"); +} diff --git a/plugins/Vectorscope/VecControls.h b/plugins/Vectorscope/VecControls.h new file mode 100644 index 00000000000..04b688e5a5b --- /dev/null +++ b/plugins/Vectorscope/VecControls.h @@ -0,0 +1,66 @@ +/* + * VecControls.h - declaration of VecControls class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef VECCONTROLS_H +#define VECCONTROLS_H + +#include + +#include "EffectControls.h" + + +class Vectorscope; + +// Holds all the configuration values +class VecControls : public EffectControls +{ + Q_OBJECT +public: + explicit VecControls(Vectorscope *effect); + virtual ~VecControls() {} + + EffectControlDialog *createView() override; + + void saveSettings (QDomDocument &document, QDomElement &element) override; + void loadSettings (const QDomElement &element) override; + + QString nodeName() const override {return "Vectorscope";} + int controlCount() override {return 3;} + +private: + Vectorscope *m_effect; + + FloatModel m_persistenceModel; + BoolModel m_logarithmicModel; + BoolModel m_highQualityModel; + + QColor m_colorFG; + QColor m_colorGrid; + QColor m_colorLabels; + QColor m_colorOutline; + + friend class VecControlsDialog; + friend class VectorView; +}; +#endif // VECCONTROLS_H diff --git a/plugins/Vectorscope/VecControlsDialog.cpp b/plugins/Vectorscope/VecControlsDialog.cpp new file mode 100644 index 00000000000..9916d775605 --- /dev/null +++ b/plugins/Vectorscope/VecControlsDialog.cpp @@ -0,0 +1,94 @@ +/* + * VecControlsDialog.cpp - definition of VecControlsDialog class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "VecControlsDialog.h" + +#include +#include +#include +#include +#include + +#include "embed.h" +#include "LedCheckbox.h" +#include "VecControls.h" +#include "Vectorscope.h" +#include "VectorView.h" + + +// The entire GUI layout is built here. +VecControlsDialog::VecControlsDialog(VecControls *controls) : + EffectControlDialog(controls), + m_controls(controls) +{ + QVBoxLayout *master_layout = new QVBoxLayout; + master_layout->setContentsMargins(0, 2, 0, 0); + setLayout(master_layout); + + // Visualizer widget + // The size of 768 pixels seems to offer a good balance of speed, accuracy and trace thickness. + VectorView *display = new VectorView(controls, m_controls->m_effect->getBuffer(), 768, this); + master_layout->addWidget(display); + + // Config area located inside visualizer + QVBoxLayout *internal_layout = new QVBoxLayout(display); + QHBoxLayout *config_layout = new QHBoxLayout(); + QVBoxLayout *switch_layout = new QVBoxLayout(); + internal_layout->addStretch(); + internal_layout->addLayout(config_layout); + config_layout->addLayout(switch_layout); + + // High-quality switch + LedCheckBox *highQualityButton = new LedCheckBox(tr("HQ"), this); + highQualityButton->setToolTip(tr("Double the resolution and simulate continuous analog-like trace.")); + highQualityButton->setCheckable(true); + highQualityButton->setMinimumSize(70, 12); + highQualityButton->setModel(&controls->m_highQualityModel); + switch_layout->addWidget(highQualityButton); + + // Log. scale switch + LedCheckBox *logarithmicButton = new LedCheckBox(tr("Log. scale"), this); + logarithmicButton->setToolTip(tr("Display amplitude on logarithmic scale to better see small values.")); + logarithmicButton->setCheckable(true); + logarithmicButton->setMinimumSize(70, 12); + logarithmicButton->setModel(&controls->m_logarithmicModel); + switch_layout->addWidget(logarithmicButton); + + config_layout->addStretch(); + + // Persistence knob + Knob *persistenceKnob = new Knob(knobSmall_17, this); + persistenceKnob->setModel(&controls->m_persistenceModel); + persistenceKnob->setLabel(tr("Persist.")); + persistenceKnob->setToolTip(tr("Trace persistence: higher amount means the trace will stay bright for longer time.")); + persistenceKnob->setHintText(tr("Trace persistence"), ""); + config_layout->addWidget(persistenceKnob); +} + + +// Suggest the best widget size. +QSize VecControlsDialog::sizeHint() const +{ + return QSize(275, 300); +} diff --git a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.h b/plugins/Vectorscope/VecControlsDialog.h similarity index 59% rename from plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.h rename to plugins/Vectorscope/VecControlsDialog.h index 17e2f772489..b76c06ad001 100644 --- a/plugins/SpectrumAnalyzer/SpectrumAnalyzerControlDialog.h +++ b/plugins/Vectorscope/VecControlsDialog.h @@ -1,7 +1,7 @@ /* - * SpectrumAnalyzerControlDialog.h - view for spectrum analyzer + * VecControlsDialog.h - declatation of VecControlsDialog class. * - * Copyright (c) 2008-2014 Tobias Doerffel + * Copyright (c) 2019 Martin Pavelek * * This file is part of LMMS - https://lmms.io * @@ -22,32 +22,26 @@ * */ -#ifndef _SPECTRUM_ANALYZER_CONTROL_DIALOG_H -#define _SPECTRUM_ANALYZER_CONTROL_DIALOG_H +#ifndef VECCONTROLSDIALOG_H +#define VECCONTROLSDIALOG_H #include "EffectControlDialog.h" +class VecControls; -class SpectrumAnalyzerControls; - - -class SpectrumAnalyzerControlDialog : public EffectControlDialog +//! Top-level widget holding the configuration GUI and vector display +class VecControlsDialog : public EffectControlDialog { Q_OBJECT public: - SpectrumAnalyzerControlDialog( SpectrumAnalyzerControls* controls ); - virtual ~SpectrumAnalyzerControlDialog() - { - } - -private: - virtual void paintEvent( QPaintEvent* event ); - - SpectrumAnalyzerControls* m_controls; + explicit VecControlsDialog(VecControls *controls); + virtual ~VecControlsDialog() {} - QPixmap m_logXAxis; - QPixmap m_logYAxis; + bool isResizable() const override {return true;} + QSize sizeHint() const override; -} ; +private: + VecControls *m_controls; +}; -#endif +#endif // VECCONTROLSDIALOG_H diff --git a/plugins/Vectorscope/VectorView.cpp b/plugins/Vectorscope/VectorView.cpp new file mode 100644 index 00000000000..9a3f855eb98 --- /dev/null +++ b/plugins/Vectorscope/VectorView.cpp @@ -0,0 +1,328 @@ +/* VectorView.cpp - implementation of VectorView class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "VectorView.h" + +#include +#include +#include +#include +#include + +#include "ColorChooser.h" +#include "GuiApplication.h" +#include "MainWindow.h" + + +VectorView::VectorView(VecControls *controls, LocklessRingBuffer *inputBuffer, unsigned short displaySize, QWidget *parent) : + QWidget(parent), + m_controls(controls), + m_inputBuffer(inputBuffer), + m_bufferReader(*inputBuffer), + m_displaySize(displaySize), + m_zoom(1.f), + m_persistTimestamp(0), + m_zoomTimestamp(0), + m_oldHQ(m_controls->m_highQualityModel.value()), + m_oldX(m_displaySize / 2), + m_oldY(m_displaySize / 2) +{ + setMinimumSize(200, 200); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + connect(gui->mainWindow(), SIGNAL(periodicUpdate()), this, SLOT(periodicUpdate())); + + m_displayBuffer.resize(sizeof qRgb(0,0,0) * m_displaySize * m_displaySize, 0); + +#ifdef VEC_DEBUG + m_executionAvg = 0; +#endif +} + + +// Compose and draw all the content; called by Qt. +void VectorView::paintEvent(QPaintEvent *event) +{ +#ifdef VEC_DEBUG + unsigned int drawTime = std::chrono::high_resolution_clock::now().time_since_epoch().count(); +#endif + + // All drawing done in this method, local variables are sufficient for the boundary + const int displayTop = 2; + const int displayBottom = height() - 2; + const int displayLeft = 2; + const int displayRight = width() - 2; + const int displayWidth = displayRight - displayLeft; + const int displayHeight = displayBottom - displayTop; + + const float centerX = displayLeft + (displayWidth / 2.f); + const float centerY = displayTop + (displayWidth / 2.f); + + const int margin = 4; + const int gridCorner = 30; + + // Setup QPainter and font sizes + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, true); + + QFont normalFont, boldFont; + boldFont.setPixelSize(26); + boldFont.setBold(true); + const int labelWidth = 26; + const int labelHeight = 26; + + bool hq = m_controls->m_highQualityModel.value(); + + // Clear display buffer if quality setting was changed + if (hq != m_oldHQ) + { + m_oldHQ = hq; + for (std::size_t i = 0; i < m_displayBuffer.size(); i++) + { + m_displayBuffer.data()[i] = 0; + } + } + + // Dim stored image based on persistence setting and elapsed time. + // Update period is limited to 50 ms (20 FPS) for non-HQ mode and 10 ms (100 FPS) for HQ mode. + const unsigned int currentTimestamp = std::chrono::duration_cast + ( + std::chrono::high_resolution_clock::now().time_since_epoch() + ).count(); + const unsigned int elapsed = currentTimestamp - m_persistTimestamp; + const unsigned int threshold = hq ? 10 : 50; + if (elapsed > threshold) + { + m_persistTimestamp = currentTimestamp; + // Non-HQ mode uses half the resolution → use limited buffer space. + const std::size_t useableBuffer = hq ? m_displayBuffer.size() : m_displayBuffer.size() / 4; + // The knob value is interpreted on log. scale, otherwise the effect would ramp up too slowly. + // Persistence value specifies fraction of light intensity that remains after 10 ms. + // → Compensate it based on elapsed time (exponential decay). + const float persist = log10(1 + 9 * m_controls->m_persistenceModel.value()); + const float persistPerFrame = pow(persist, elapsed / 10.f); + // Note that for simplicity and performance reasons, this implementation only dims all stored + // values by a given factor. A true simulation would also do the inverse of desaturation that + // occurs in high-intensity traces in HQ mode. + for (std::size_t i = 0; i < useableBuffer; i++) + { + m_displayBuffer.data()[i] *= persistPerFrame; + } + } + + // Get new samples from the lockless input FIFO buffer + auto inBuffer = m_bufferReader.read_max(m_inputBuffer->capacity()); + std::size_t frameCount = inBuffer.size(); + + // Draw new points on top + float left, right; + int x, y; + + const bool logScale = m_controls->m_logarithmicModel.value(); + const unsigned short activeSize = hq ? m_displaySize : m_displaySize / 2; + + // Helper lambda functions for better readability + // Make sure pixel stays within display bounds: + auto saturate = [=](short pixelPos) {return qBound((short)0, pixelPos, (short)(activeSize - 1));}; + // Take existing pixel and brigthen it. Very bright light should reduce saturation and become + // white. This effect is easily approximated by capping elementary colors to 255 individually. + auto updatePixel = [&](unsigned short x, unsigned short y, QColor addedColor) + { + QColor currentColor = ((QRgb*)m_displayBuffer.data())[x + y * activeSize]; + currentColor.setRed(std::min(currentColor.red() + addedColor.red(), 255)); + currentColor.setGreen(std::min(currentColor.green() + addedColor.green(), 255)); + currentColor.setBlue(std::min(currentColor.blue() + addedColor.blue(), 255)); + ((QRgb*)m_displayBuffer.data())[x + y * activeSize] = currentColor.rgb(); + }; + + if (hq) + { + // High quality mode: check distance between points and draw a line. + // The longer the line is, the dimmer, simulating real electron trace on luminescent screen. + for (std::size_t frame = 0; frame < frameCount; frame++) + { + float inLeft = inBuffer[frame][0] * m_zoom; + float inRight = inBuffer[frame][1] * m_zoom; + // Scale left and right channel from (-1.0, 1.0) to display range + if (logScale) + { + // To better preserve shapes, the log scale is applied to the distance from origin, + // not the individual channels. + const float distance = sqrt(inLeft * inLeft + inRight * inRight); + const float distanceLog = log10(1 + 9 * abs(distance)); + const float angleCos = inLeft / distance; + const float angleSin = inRight / distance; + left = distanceLog * angleCos * (activeSize - 1) / 4; + right = distanceLog * angleSin * (activeSize - 1) / 4; + } + else + { + left = inLeft * (activeSize - 1) / 4; + right = inRight * (activeSize - 1) / 4; + } + + // Rotate display coordinates 45 degrees, flip Y axis and make sure the result stays within bounds + x = saturate(right - left + activeSize / 2.f); + y = saturate(activeSize - (right + left + activeSize / 2.f)); + + // Estimate number of points needed to fill space between the old and new pixel. Cap at 100. + unsigned char points = std::min((int)sqrt((m_oldX - x) * (m_oldX - x) + (m_oldY - y) * (m_oldY - y)), 100); + + // Large distance = dim trace. The curve for darker() is choosen so that: + // - no movement (0 points) actually _increases_ brightness slightly, + // - one point between samples = returns exactly the specified color, + // - one to 99 points between samples = follows a sharp "1/x" decaying curve, + // - 100 points between samples = returns approximately 5 % brightness. + // Everything else is discarded (by the 100 point cap) because there is not much to see anyway. + QColor addedColor = m_controls->m_colorFG.darker(75 + 20 * points).rgb(); + + // Draw the new pixel: the beam sweeps across area that may have been excited before + // → add new value to existing pixel state. + updatePixel(x, y, addedColor); + + // Draw interpolated points between the old pixel and the new one + int newX = right - left + activeSize / 2.f; + int newY = activeSize - (right + left + activeSize / 2.f); + for (unsigned char i = 1; i < points; i++) + { + x = saturate(((points - i) * m_oldX + i * newX) / points); + y = saturate(((points - i) * m_oldY + i * newY) / points); + updatePixel(x, y, addedColor); + } + m_oldX = newX; + m_oldY = newY; + } + } + else + { + // To improve performance, non-HQ mode uses smaller display size and only + // one full-color pixel per sample. + for (std::size_t frame = 0; frame < frameCount; frame++) + { + float inLeft = inBuffer[frame][0] * m_zoom; + float inRight = inBuffer[frame][1] * m_zoom; + if (logScale) { + const float distance = sqrt(inLeft * inLeft + inRight * inRight); + const float distanceLog = log10(1 + 9 * abs(distance)); + const float angleCos = inLeft / distance; + const float angleSin = inRight / distance; + left = distanceLog * angleCos * (activeSize - 1) / 4; + right = distanceLog * angleSin * (activeSize - 1) / 4; + } else { + left = inLeft * (activeSize - 1) / 4; + right = inRight * (activeSize - 1) / 4; + } + x = saturate(right - left + activeSize / 2.f); + y = saturate(activeSize - (right + left + activeSize / 2.f)); + ((QRgb*)m_displayBuffer.data())[x + y * activeSize] = m_controls->m_colorFG.rgb(); + } + } + + // Draw background + painter.fillRect(displayLeft, displayTop, displayWidth, displayHeight, QColor(0,0,0)); + + // Draw the final image + QImage temp = QImage(m_displayBuffer.data(), + activeSize, + activeSize, + QImage::Format_RGB32); + temp.setDevicePixelRatio(devicePixelRatio()); + painter.drawImage(displayLeft, displayTop, + temp.scaledToWidth(displayWidth * devicePixelRatio(), + Qt::SmoothTransformation)); + + // Draw the grid and labels + painter.setPen(QPen(m_controls->m_colorGrid, 1.5, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawEllipse(QPointF(centerX, centerY), displayWidth / 2.f, displayWidth / 2.f); + painter.setPen(QPen(m_controls->m_colorGrid, 1.5, Qt::DotLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawLine(QPointF(centerX, centerY), QPointF(displayLeft + gridCorner, displayTop + gridCorner)); + painter.drawLine(QPointF(centerX, centerY), QPointF(displayRight - gridCorner, displayTop + gridCorner)); + + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.setFont(boldFont); + painter.drawText(displayLeft + margin, displayTop, + labelWidth, labelHeight, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip, + QString("L")); + painter.drawText(displayRight - margin - labelWidth, displayTop, + labelWidth, labelHeight, Qt::AlignRight| Qt::AlignTop | Qt::TextDontClip, + QString("R")); + + // Draw the outline + painter.setPen(QPen(m_controls->m_colorOutline, 2, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.drawRoundedRect(1, 1, width() - 2, height() - 2, 2.f, 2.f); + + // Draw zoom info if changed within last second (re-using timestamp acquired for dimming) + if (currentTimestamp - m_zoomTimestamp < 1000) + { + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.setFont(normalFont); + painter.drawText(displayWidth / 2 - 50, displayBottom - 20, 100, 16, Qt::AlignCenter, + QString("Zoom: ").append(std::to_string((int)round(m_zoom * 100)).c_str()).append(" %")); + } + + // Optionally measure drawing performance +#ifdef VEC_DEBUG + drawTime = std::chrono::high_resolution_clock::now().time_since_epoch().count() - drawTime; + m_executionAvg = 0.95f * m_executionAvg + 0.05f * drawTime / 1000000.f; + painter.setPen(QPen(m_controls->m_colorLabels, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin)); + painter.setFont(normalFont); + painter.drawText(displayWidth / 2 - 50, displayBottom - 16, 100, 16, Qt::AlignLeft, + QString("Exec avg.: ").append(std::to_string(m_executionAvg).substr(0, 5).c_str()).append(" ms")); +#endif +} + + +// Periodically trigger repaint and check if the widget is visible +void VectorView::periodicUpdate() +{ + m_visible = isVisible(); + if (m_visible) {update();} +} + + +// Allow to change color on double-click. +// More of an Easter egg, to avoid cluttering the interface with non-essential functionality. +void VectorView::mouseDoubleClickEvent(QMouseEvent *event) +{ + ColorChooser *colorDialog = new ColorChooser(m_controls->m_colorFG, this); + if (colorDialog->exec()) + { + m_controls->m_colorFG = colorDialog->currentColor(); + } +} + + +// Change zoom level using the mouse wheel +void VectorView::wheelEvent(QWheelEvent *event) +{ + // Go through integers to avoid accumulating errors + const unsigned short old_zoom = round(100 * m_zoom); + // Min-max bounds are 20 and 1000 %, step for 15°-increment mouse wheel is 20 % + const unsigned short new_zoom = qBound(20, old_zoom + event->angleDelta().y() / 6, 1000); + m_zoom = new_zoom / 100.f; + event->accept(); + m_zoomTimestamp = std::chrono::duration_cast + ( + std::chrono::high_resolution_clock::now().time_since_epoch() + ).count(); + +} diff --git a/plugins/Vectorscope/VectorView.h b/plugins/Vectorscope/VectorView.h new file mode 100644 index 00000000000..066e306a0a0 --- /dev/null +++ b/plugins/Vectorscope/VectorView.h @@ -0,0 +1,80 @@ +/* VectorView.h - declaration of VectorView class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ +#ifndef VECTORVIEW_H +#define VECTORVIEW_H + +#include +#include +#include + +#include "Knob.h" +#include "LedCheckbox.h" +#include "LocklessRingBuffer.h" +#include "VecControls.h" + +//#define VEC_DEBUG + + +// Widget that displays a vectorscope visualization of stereo signal. +class VectorView : public QWidget +{ + Q_OBJECT +public: + explicit VectorView(VecControls *controls, LocklessRingBuffer *inputBuffer, unsigned short displaySize, QWidget *parent = 0); + virtual ~VectorView() {} + + QSize sizeHint() const override {return QSize(300, 300);} + +protected: + void paintEvent(QPaintEvent *event) override; + void mouseDoubleClickEvent(QMouseEvent *event) override; + void wheelEvent(QWheelEvent *event) override; + +private slots: + void periodicUpdate(); + +private: + VecControls *m_controls; + + LocklessRingBuffer *m_inputBuffer; + LocklessRingBufferReader m_bufferReader; + + std::vector m_displayBuffer; + const unsigned short m_displaySize; + + bool m_visible; + + float m_zoom; + + // State variables for comparison with previous repaint + unsigned int m_persistTimestamp; + unsigned int m_zoomTimestamp; + bool m_oldHQ; + int m_oldX; + int m_oldY; + +#ifdef VEC_DEBUG + float m_executionAvg = 0; +#endif +}; +#endif // VECTORVIEW_H diff --git a/plugins/Vectorscope/Vectorscope.cpp b/plugins/Vectorscope/Vectorscope.cpp new file mode 100644 index 00000000000..f8bc30c40df --- /dev/null +++ b/plugins/Vectorscope/Vectorscope.cpp @@ -0,0 +1,80 @@ +/* + * Vectorscope.cpp - definition of Vectorscope class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Vectorscope.h" + +#include "embed.h" +#include "plugin_export.h" + + +extern "C" { + Plugin::Descriptor PLUGIN_EXPORT vectorscope_plugin_descriptor = + { + STRINGIFY(PLUGIN_NAME), + "Vectorscope", + QT_TRANSLATE_NOOP("pluginBrowser", "A stereo field visualizer."), + "Martin Pavelek ", + 0x0100, + Plugin::Effect, + new PluginPixmapLoader("logo"), + NULL, + NULL + }; +} + + +Vectorscope::Vectorscope(Model *parent, const Plugin::Descriptor::SubPluginFeatures::Key *key) : + Effect(&vectorscope_plugin_descriptor, parent, key), + m_controls(this), + // Buffer is sized to cover 4* the current maximum LMMS audio buffer size, + // so that it has some reserve space in case GUI thresd is busy. + m_inputBuffer(4 * m_maxBufferSize) +{ +} + + +// Take audio data and store them for processing and display in the GUI thread. +bool Vectorscope::processAudioBuffer(sampleFrame *buffer, const fpp_t frame_count) +{ + if (!isEnabled() || !isRunning ()) {return false;} + + // Skip processing if the controls dialog isn't visible, it would only waste CPU cycles. + if (m_controls.isViewVisible()) + { + // To avoid processing spikes on audio thread, data are stored in + // a lockless ringbuffer and processed in a separate thread. + m_inputBuffer.write(buffer, frame_count); + } + return isRunning(); +} + + +extern "C" { + // needed for getting plugin out of shared lib + PLUGIN_EXPORT Plugin *lmms_plugin_main(Model *parent, void *data) + { + return new Vectorscope(parent, static_cast(data)); + } +} + diff --git a/plugins/Vectorscope/Vectorscope.h b/plugins/Vectorscope/Vectorscope.h new file mode 100644 index 00000000000..b45ff6de4ab --- /dev/null +++ b/plugins/Vectorscope/Vectorscope.h @@ -0,0 +1,52 @@ +/* Vectorscope.h - declaration of Vectorscope class. + * + * Copyright (c) 2019 Martin Pavelek + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef VECTORSCOPE_H +#define VECTORSCOPE_H + +#include "Effect.h" +#include "LocklessRingBuffer.h" +#include "VecControls.h" + + +//! Top level class; handles LMMS interface and accumulates data for processing. +class Vectorscope : public Effect +{ +public: + Vectorscope(Model *parent, const Descriptor::SubPluginFeatures::Key *key); + virtual ~Vectorscope() {}; + + bool processAudioBuffer(sampleFrame *buffer, const fpp_t frame_count) override; + EffectControls *controls() override {return &m_controls;} + LocklessRingBuffer *getBuffer() {return &m_inputBuffer;} + +private: + VecControls m_controls; + + // Maximum LMMS buffer size (hard coded, the actual constant is hard to get) + const unsigned int m_maxBufferSize = 4096; + LocklessRingBuffer m_inputBuffer; +}; + +#endif // VECTORSCOPE_H + diff --git a/plugins/Vectorscope/logo.png b/plugins/Vectorscope/logo.png new file mode 100644 index 00000000000..9340da708dd Binary files /dev/null and b/plugins/Vectorscope/logo.png differ diff --git a/plugins/VstEffect/VstEffect.cpp b/plugins/VstEffect/VstEffect.cpp index 80f209a7b1c..f72bf10dbc8 100644 --- a/plugins/VstEffect/VstEffect.cpp +++ b/plugins/VstEffect/VstEffect.cpp @@ -58,9 +58,9 @@ VstEffect::VstEffect( Model * _parent, const Descriptor::SubPluginFeatures::Key * _key ) : Effect( &vsteffect_plugin_descriptor, _parent, _key ), m_pluginMutex(), - m_key( *_key ), m_vstControls( this ) { + m_key = *_key; if( !m_key.attributes["file"].isEmpty() ) { openPlugin( m_key.attributes["file"] ); @@ -153,6 +153,22 @@ void VstEffect::openPlugin( const QString & _plugin ) +void VstEffect::loadFile(const QString & file) +{ + openPlugin(file); +} + + + + +void VstEffect::loadPluginPresetFile(const QString& file) +{ + m_plugin->openPreset(file); +} + + + + extern "C" { diff --git a/plugins/VstEffect/VstEffect.h b/plugins/VstEffect/VstEffect.h index 95834e86294..dcdcd396b3b 100644 --- a/plugins/VstEffect/VstEffect.h +++ b/plugins/VstEffect/VstEffect.h @@ -54,6 +54,8 @@ class VstEffect : public Effect return m_plugin->name(); } + void loadFile(const QString & file) override; + void loadPluginPresetFile(const QString & file) override; private: void openPlugin( const QString & _plugin ); @@ -61,7 +63,6 @@ class VstEffect : public Effect QSharedPointer m_plugin; QMutex m_pluginMutex; - EffectKey m_key; VstEffectControls m_vstControls; diff --git a/plugins/VstEffect/VstEffectControlDialog.h b/plugins/VstEffect/VstEffectControlDialog.h index 3cd9af360ab..930f514c9b3 100644 --- a/plugins/VstEffect/VstEffectControlDialog.h +++ b/plugins/VstEffect/VstEffectControlDialog.h @@ -49,8 +49,8 @@ class VstEffectControlDialog : public EffectControlDialog virtual ~VstEffectControlDialog(); protected: - virtual void paintEvent( QPaintEvent * _pe ); - virtual void showEvent( QShowEvent* _se ) override; + void paintEvent( QPaintEvent * _pe ) override; + void showEvent( QShowEvent* _se ) override; private: QWidget * m_pluginWidget; diff --git a/plugins/VstEffect/VstEffectControls.cpp b/plugins/VstEffect/VstEffectControls.cpp index a0f97ce715e..04583a641c6 100644 --- a/plugins/VstEffect/VstEffectControls.cpp +++ b/plugins/VstEffect/VstEffectControls.cpp @@ -180,7 +180,7 @@ void VstEffectControls::savePreset( void ) { if ( m_effect->m_plugin != NULL ) { - m_effect->m_plugin->savePreset( ); + m_effect->m_plugin->guiSavePreset(); /* bool converted; QString str = m_vi->m_plugin->currentProgramName().section("/", 0, 0); if (str != "") @@ -232,7 +232,7 @@ void VstEffectControls::openPreset( void ) { if ( m_effect->m_plugin != NULL ) { - m_effect->m_plugin->openPreset( ); + m_effect->m_plugin->guiOpenPreset(); bool converted; QString str = m_effect->m_plugin->currentProgramName().section("/", 0, 0); if (str != "") @@ -350,7 +350,7 @@ manageVSTEffectView::manageVSTEffectView( VstEffect * _eff, VstEffectControls * const QMap & dump = m_effect->m_plugin->parameterDump(); m_vi->paramCount = dump.size(); - vstKnobs = new Knob *[ m_vi->paramCount ]; + vstKnobs = new CustomTextKnob *[ m_vi->paramCount ]; bool hasKnobModel = true; if (m_vi->knobFModel == NULL) { @@ -366,8 +366,8 @@ manageVSTEffectView::manageVSTEffectView( VstEffect * _eff, VstEffectControls * sprintf( paramStr, "param%d", i); s_dumpValues = dump[ paramStr ].split( ":" ); - vstKnobs[ i ] = new Knob( knobBright_26, widget, s_dumpValues.at( 1 ) ); - vstKnobs[ i ]->setHintText( s_dumpValues.at( 1 ) + ":", "" ); + vstKnobs[ i ] = new CustomTextKnob( knobBright_26, widget, s_dumpValues.at( 1 ) ); + vstKnobs[ i ]->setDescription( s_dumpValues.at( 1 ) + ":" ); vstKnobs[ i ]->setLabel( s_dumpValues.at( 1 ).left( 15 ) ); if( !hasKnobModel ) @@ -382,6 +382,7 @@ manageVSTEffectView::manageVSTEffectView( VstEffect * _eff, VstEffectControls * [this, model]() { setParameter( model ); }, Qt::DirectConnection); vstKnobs[ i ] ->setModel( model ); } + syncParameterText(); int i = 0; for( int lrow = 1; lrow < ( int( m_vi->paramCount / 10 ) + 1 ) + 1; lrow++ ) @@ -444,6 +445,7 @@ void manageVSTEffectView::syncPlugin( void ) m_vi2->knobFModel[ i ]->setInitValue( f_value ); } } + syncParameterText(); } @@ -479,9 +481,40 @@ void manageVSTEffectView::setParameter( Model * action ) if ( m_effect->m_plugin != NULL ) { m_effect->m_plugin->setParam( knobUNID, m_vi2->knobFModel[knobUNID]->value() ); + syncParameterText(); } } +void manageVSTEffectView::syncParameterText() +{ + m_effect->m_plugin->loadParameterLabels(); + m_effect->m_plugin->loadParameterDisplays(); + + QString paramLabelStr = m_effect->m_plugin->allParameterLabels(); + QString paramDisplayStr = m_effect->m_plugin->allParameterDisplays(); + + QStringList paramLabelList; + QStringList paramDisplayList; + + for( int i = 0; i < paramLabelStr.size(); ) + { + const int length = paramLabelStr[i].digitValue(); + paramLabelList.append(paramLabelStr.mid(i + 1, length)); + i += length + 1; + } + + for( int i = 0; i < paramDisplayStr.size(); ) + { + const int length = paramDisplayStr[i].digitValue(); + paramDisplayList.append(paramDisplayStr.mid(i + 1, length)); + i += length + 1; + } + + for( int i = 0; i < paramLabelList.size(); ++i ) + { + vstKnobs[i]->setValueText(paramDisplayList[i] + ' ' + paramLabelList[i]); + } +} diff --git a/plugins/VstEffect/VstEffectControls.h b/plugins/VstEffect/VstEffectControls.h index 092669f949f..cb98d0f439a 100644 --- a/plugins/VstEffect/VstEffectControls.h +++ b/plugins/VstEffect/VstEffectControls.h @@ -34,7 +34,7 @@ #include #include -#include "Knob.h" +#include "CustomTextKnob.h" #include #include #include @@ -111,6 +111,7 @@ protected slots: void syncPlugin( void ); void displayAutomatedOnly( void ); void setParameter( Model * action ); + void syncParameterText(); void closeWindow(); private: @@ -129,7 +130,7 @@ protected slots: QPushButton * m_syncButton; QPushButton * m_displayAutomatedOnly; QPushButton * m_closeButton; - Knob ** vstKnobs; + CustomTextKnob ** vstKnobs; } ; diff --git a/plugins/Xpressive/Xpressive.cpp b/plugins/Xpressive/Xpressive.cpp index f0154f75b02..6e648edd481 100644 --- a/plugins/Xpressive/Xpressive.cpp +++ b/plugins/Xpressive/Xpressive.cpp @@ -53,9 +53,9 @@ extern "C" { Plugin::Descriptor PLUGIN_EXPORT xpressive_plugin_descriptor = { STRINGIFY( - PLUGIN_NAME), "X-Pressive", QT_TRANSLATE_NOOP("pluginBrowser", - "Mathematical expression parser"), "Orr Dvori", 0x0100, - Plugin::Instrument, new PluginPixmapLoader("logo"), NULL, NULL }; + PLUGIN_NAME), "Xpressive", QT_TRANSLATE_NOOP("pluginBrowser", + "Mathematical expression parser"), "Orr Dvori", 0x0100, + Plugin::Instrument, new PluginPixmapLoader("logo"), NULL, NULL }; } @@ -257,7 +257,6 @@ class XpressiveKnob: public Knob { setCenterPointY(14.5); setInnerRadius(4); setOuterRadius(9); - setOuterColor(QColor(0x519fff)); setTotalAngle(300.0); setLineWidth(3); } @@ -274,17 +273,21 @@ class XpressiveKnob: public Knob { XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : - InstrumentView(_instrument, _parent) + InstrumentViewFixedSize(_instrument, _parent) { - const int COL_KNOBS = 194; - const int ROW_KNOBSA1 = 26; - const int ROW_KNOBSA2 = 26 + 32; - const int ROW_KNOBSA3 = 26 + 64; - const int ROW_KNOBSP1 = 126; - const int ROW_KNOBSP2 = 126 + 32; - const int ROW_KNOBREL = 126 + 64; - const int ROW_WAVEBTN = 234; + const int COL_KNOBS = 191; + const int BASE_START = 2; + const int ROW_KNOBSA1 = BASE_START; + const int ROW_KNOBSA2 = BASE_START + 32; + const int ROW_KNOBSA3 = BASE_START + 64; + const int ROW_KNOBSP1 = BASE_START + 100; + const int ROW_KNOBSP2 = BASE_START + 100 + 32; + const int ROW_KNOBREL = BASE_START + 100 + 64; + const int ROW_BTN = BASE_START + 85; + const int ROW_WAVEBTN = BASE_START + 233 - 26; + const int EXPR_TEXT_Y = BASE_START + 102; + const int EXPR_TEXT_H = 90; setAutoFillBackground(true); QPalette pal; @@ -293,7 +296,7 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : setPalette(pal); m_graph = new Graph(this, Graph::LinearStyle, 180, 81); - m_graph->move(9, 27); + m_graph->move(3, BASE_START + 1); m_graph->setAutoFillBackground(true); m_graph->setGraphColor(QColor(255, 255, 255)); m_graph->setEnabled(false); @@ -313,37 +316,37 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : PixmapButton * m_helpBtn; m_w1Btn = new PixmapButton(this, NULL); - m_w1Btn->move(9, 111); + m_w1Btn->move(3, ROW_BTN); m_w1Btn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("w1_active")); m_w1Btn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("w1_inactive")); ToolTip::add(m_w1Btn, tr("Select oscillator W1")); m_w2Btn = new PixmapButton(this, NULL); - m_w2Btn->move(32, 111); + m_w2Btn->move(26, ROW_BTN); m_w2Btn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("w2_active")); m_w2Btn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("w2_inactive")); ToolTip::add(m_w2Btn, tr("Select oscillator W2")); m_w3Btn = new PixmapButton(this, NULL); - m_w3Btn->move(55, 111); + m_w3Btn->move(49, ROW_BTN); m_w3Btn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("w3_active")); m_w3Btn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("w3_inactive")); ToolTip::add(m_w3Btn, tr("Select oscillator W3")); m_o1Btn = new PixmapButton(this, NULL); - m_o1Btn->move(85, 111); + m_o1Btn->move(79, ROW_BTN); m_o1Btn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("o1_active")); m_o1Btn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("o1_inactive")); ToolTip::add(m_o1Btn, tr("Select output O1")); m_o2Btn = new PixmapButton(this, NULL); - m_o2Btn->move(107, 111); + m_o2Btn->move(101, ROW_BTN); m_o2Btn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("o2_active")); m_o2Btn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("o2_inactive")); ToolTip::add(m_o2Btn, tr("Select output O2")); m_helpBtn = new PixmapButton(this, NULL); - m_helpBtn->move(139, 111); + m_helpBtn->move(133, ROW_BTN); m_helpBtn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("help_active")); m_helpBtn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("help_inactive")); ToolTip::add(m_helpBtn, tr("Open help window")); @@ -359,38 +362,38 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : m_selectedGraphGroup->setModel(&e->selectedGraph()); m_sinWaveBtn = new PixmapButton(this, tr("Sine wave")); - m_sinWaveBtn->move(10, ROW_WAVEBTN); + m_sinWaveBtn->move(4, ROW_WAVEBTN); m_sinWaveBtn->setActiveGraphic(embed::getIconPixmap("sin_wave_active")); m_sinWaveBtn->setInactiveGraphic(embed::getIconPixmap("sin_wave_inactive")); ToolTip::add(m_sinWaveBtn, tr("Sine wave")); m_moogWaveBtn = new PixmapButton(this, tr("Moog-saw wave")); - m_moogWaveBtn->move(10, ROW_WAVEBTN-14); + m_moogWaveBtn->move(4, ROW_WAVEBTN-14); m_moogWaveBtn->setActiveGraphic( embed::getIconPixmap( "moog_saw_wave_active" ) ); m_moogWaveBtn->setInactiveGraphic(embed::getIconPixmap("moog_saw_wave_inactive")); ToolTip::add(m_moogWaveBtn, tr("Moog-saw wave")); m_expWaveBtn = new PixmapButton(this, tr("Exponential wave")); - m_expWaveBtn->move(10 +14, ROW_WAVEBTN-14); + m_expWaveBtn->move(4 +14, ROW_WAVEBTN-14); m_expWaveBtn->setActiveGraphic(embed::getIconPixmap( "exp_wave_active" ) ); m_expWaveBtn->setInactiveGraphic(embed::getIconPixmap( "exp_wave_inactive" ) ); ToolTip::add(m_expWaveBtn, tr("Exponential wave")); m_sawWaveBtn = new PixmapButton(this, tr("Saw wave")); - m_sawWaveBtn->move(10 + 14 * 2, ROW_WAVEBTN-14); + m_sawWaveBtn->move(4 + 14 * 2, ROW_WAVEBTN-14); m_sawWaveBtn->setActiveGraphic(embed::getIconPixmap("saw_wave_active")); m_sawWaveBtn->setInactiveGraphic(embed::getIconPixmap("saw_wave_inactive")); ToolTip::add(m_sawWaveBtn, tr("Saw wave")); m_usrWaveBtn = new PixmapButton(this, tr("User-defined wave")); - m_usrWaveBtn->move(10 + 14 * 3, ROW_WAVEBTN-14); + m_usrWaveBtn->move(4 + 14 * 3, ROW_WAVEBTN-14); m_usrWaveBtn->setActiveGraphic(embed::getIconPixmap("usr_wave_active")); m_usrWaveBtn->setInactiveGraphic(embed::getIconPixmap("usr_wave_inactive")); ToolTip::add(m_usrWaveBtn, tr("User-defined wave")); m_triangleWaveBtn = new PixmapButton(this, tr("Triangle wave")); - m_triangleWaveBtn->move(10 + 14, ROW_WAVEBTN); + m_triangleWaveBtn->move(4 + 14, ROW_WAVEBTN); m_triangleWaveBtn->setActiveGraphic( embed::getIconPixmap("triangle_wave_active")); m_triangleWaveBtn->setInactiveGraphic( @@ -398,14 +401,14 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : ToolTip::add(m_triangleWaveBtn, tr("Triangle wave")); m_sqrWaveBtn = new PixmapButton(this, tr("Square wave")); - m_sqrWaveBtn->move(10 + 14 * 2, ROW_WAVEBTN); + m_sqrWaveBtn->move(4 + 14 * 2, ROW_WAVEBTN); m_sqrWaveBtn->setActiveGraphic(embed::getIconPixmap("square_wave_active")); m_sqrWaveBtn->setInactiveGraphic( embed::getIconPixmap("square_wave_inactive")); ToolTip::add(m_sqrWaveBtn, tr("Square wave")); m_whiteNoiseWaveBtn = new PixmapButton(this, tr("White noise")); - m_whiteNoiseWaveBtn->move(10 + 14 * 3, ROW_WAVEBTN); + m_whiteNoiseWaveBtn->move(4 + 14 * 3, ROW_WAVEBTN); m_whiteNoiseWaveBtn->setActiveGraphic( embed::getIconPixmap("white_noise_wave_active")); m_whiteNoiseWaveBtn->setInactiveGraphic( @@ -415,16 +418,16 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : m_waveInterpolate = new LedCheckBox("Interpolate", this, tr("WaveInterpolate"), LedCheckBox::Green); - m_waveInterpolate->move(120, 230); + m_waveInterpolate->move(2, 230); m_expressionValidToggle = new LedCheckBox("", this, tr("ExpressionValid"), LedCheckBox::Red); - m_expressionValidToggle->move(174, 216); + m_expressionValidToggle->move(168, EXPR_TEXT_Y+EXPR_TEXT_H-2); m_expressionValidToggle->setEnabled( false ); m_expressionEditor = new QPlainTextEdit(this); - m_expressionEditor->move(9, 128); - m_expressionEditor->resize(180, 90); + m_expressionEditor->move(3, EXPR_TEXT_Y); + m_expressionEditor->resize(180, EXPR_TEXT_H); m_generalPurposeKnob[0] = new XpressiveKnob(this,"A1"); m_generalPurposeKnob[0]->setHintText(tr("General purpose 1:"), ""); @@ -452,9 +455,16 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : - m_smoothKnob=new Knob(this,"Smoothness"); + m_smoothKnob=new Knob(knobStyled, this, "Smoothness"); + m_smoothKnob->setFixedSize(25, 25); + m_smoothKnob->setCenterPointX(12.5); + m_smoothKnob->setCenterPointY(12.5); + m_smoothKnob->setInnerRadius(4); + m_smoothKnob->setOuterRadius(9); + m_smoothKnob->setTotalAngle(280.0); + m_smoothKnob->setLineWidth(3); m_smoothKnob->setHintText(tr("Smoothness"), ""); - m_smoothKnob->move(80, 220); + m_smoothKnob->move(66, EXPR_TEXT_Y + EXPR_TEXT_H + 4); connect(m_generalPurposeKnob[0], SIGNAL(sliderMoved(float)), this, SLOT(expressionChanged())); @@ -748,7 +758,7 @@ void XpressiveView::updateLayout() { void XpressiveView::sinWaveClicked() { if (m_output_expr) - m_expressionEditor->appendPlainText("sinew(t*f)"); + m_expressionEditor->appendPlainText("sinew(integrate(f))"); else m_expressionEditor->appendPlainText("sinew(t)"); Engine::getSong()->setModified(); @@ -756,7 +766,7 @@ void XpressiveView::sinWaveClicked() { void XpressiveView::triangleWaveClicked() { if (m_output_expr) - m_expressionEditor->appendPlainText("trianglew(t*f)"); + m_expressionEditor->appendPlainText("trianglew(integrate(f))"); else m_expressionEditor->appendPlainText("trianglew(t)"); Engine::getSong()->setModified(); @@ -764,7 +774,7 @@ void XpressiveView::triangleWaveClicked() { void XpressiveView::sawWaveClicked() { if (m_output_expr) - m_expressionEditor->appendPlainText("saww(t*f)"); + m_expressionEditor->appendPlainText("saww(integrate(f))"); else m_expressionEditor->appendPlainText("saww(t)"); Engine::getSong()->setModified(); @@ -772,7 +782,7 @@ void XpressiveView::sawWaveClicked() { void XpressiveView::sqrWaveClicked() { if (m_output_expr) - m_expressionEditor->appendPlainText("squarew(t*f)"); + m_expressionEditor->appendPlainText("squarew(integrate(f))"); else m_expressionEditor->appendPlainText("squarew(t)"); Engine::getSong()->setModified(); @@ -786,7 +796,7 @@ void XpressiveView::noiseWaveClicked() { void XpressiveView::moogSawWaveClicked() { if (m_output_expr) - m_expressionEditor->appendPlainText("moogsaww(t*f)"); + m_expressionEditor->appendPlainText("moogsaww(integrate(f))"); else m_expressionEditor->appendPlainText("moogsaww(t)"); Engine::getSong()->setModified(); @@ -794,7 +804,7 @@ void XpressiveView::moogSawWaveClicked() void XpressiveView::expWaveClicked() { if (m_output_expr) - m_expressionEditor->appendPlainText("expw(t*f)"); + m_expressionEditor->appendPlainText("expw(integrate(f))"); else m_expressionEditor->appendPlainText("expw(t)"); Engine::getSong()->setModified(); @@ -808,7 +818,7 @@ void XpressiveView::usrWaveClicked() { } QString XpressiveHelpView::s_helpText= -"O1, O2 - Two output waves. Panning is controled by PN1 and PN2.
" +"O1, O2 - Two output waves. Panning is controlled by PN1 and PN2.
" "W1, W2, W3 - Wave samples evaluated by expression. In these samples, t variable ranges [0,1).
" "These waves can be used as functions inside the output waves (O1, O2). The wave period is 1.
" "

Available variables:


" @@ -819,10 +829,10 @@ QString XpressiveHelpView::s_helpText= "srate - Sample rate. In wave expression it returns the wave's number of samples.
" "tempo - Song's Tempo. Available only in the output expressions.
" "v - Note's volume. Note that the output is already multiplied by the volume. Available only in the output expressions.
" -"rel - Gives 0.0 while the key is holded, and 1.0 after the key release. Available only in the output expressions.
" -"trel - Time after release. While the note is holded, it gives 0.0. Afterwards, it start counting seconds.
" +"rel - Gives 0.0 while the key is held, and 1.0 after the key release. Available only in the output expressions.
" +"trel - Time after release. While the note is held, it gives 0.0. Afterwards, it starts counting seconds.
" "The time it takes to shift from 0.0 to 1.0 after key release is determined by the REL knob
" -"seed - A random value that remains consistent in the lifetime of a single wave. meant to be used with randsv
" +"seed - A random value that remains consistent in the lifetime of a single wave. Meant to be used with randsv
" "A1, A2, A3 - General purpose knobs. You can reference them only in O1 and O2. In range [-1,1].
" "

Available functions:


" "W1, W2, W3 - As mentioned before. You can reference them only in O1 and O2.
" @@ -861,12 +871,17 @@ QString XpressiveHelpView::s_helpText= XpressiveHelpView::XpressiveHelpView():QTextEdit(s_helpText) { - setWindowTitle ( "X-Pressive Help" ); + setWindowTitle ( "Xpressive Help" ); setTextInteractionFlags ( Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse ); gui->mainWindow()->addWindowedWidget( this ); parentWidget()->setAttribute( Qt::WA_DeleteOnClose, false ); parentWidget()->setWindowIcon( PLUGIN_NAME::getIconPixmap( "logo" ) ); parentWidget()->setFixedSize( 300, 500); + + // No maximize button + Qt::WindowFlags flags = parentWidget()->windowFlags(); + flags &= ~Qt::WindowMaximizeButtonHint; + parentWidget()->setWindowFlags( flags ); } void XpressiveView::helpClicked() { diff --git a/plugins/Xpressive/Xpressive.h b/plugins/Xpressive/Xpressive.h index ca80f2b785c..5abee26912c 100644 --- a/plugins/Xpressive/Xpressive.h +++ b/plugins/Xpressive/Xpressive.h @@ -139,7 +139,7 @@ protected slots: } ; -class XpressiveView : public InstrumentView +class XpressiveView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/Xpressive/Xpressive.svg b/plugins/Xpressive/Xpressive.svg new file mode 100644 index 00000000000..ef3029c0d90 --- /dev/null +++ b/plugins/Xpressive/Xpressive.svg @@ -0,0 +1,130 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/Xpressive/Xpressive_logo.svg b/plugins/Xpressive/Xpressive_logo.svg new file mode 100644 index 00000000000..fca1f0d981b --- /dev/null +++ b/plugins/Xpressive/Xpressive_logo.svg @@ -0,0 +1,106 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/plugins/Xpressive/artwork.png b/plugins/Xpressive/artwork.png index d5b39acee2e..1f4e35ad51e 100644 Binary files a/plugins/Xpressive/artwork.png and b/plugins/Xpressive/artwork.png differ diff --git a/plugins/Xpressive/help_active.png b/plugins/Xpressive/help_active.png index 4e991ad54af..8d8b49d4327 100644 Binary files a/plugins/Xpressive/help_active.png and b/plugins/Xpressive/help_active.png differ diff --git a/plugins/Xpressive/help_inactive.png b/plugins/Xpressive/help_inactive.png index 4b77af24fb3..d08f6d9a7b5 100644 Binary files a/plugins/Xpressive/help_inactive.png and b/plugins/Xpressive/help_inactive.png differ diff --git a/plugins/Xpressive/logo.png b/plugins/Xpressive/logo.png index 68b613176d6..555c3f13e68 100644 Binary files a/plugins/Xpressive/logo.png and b/plugins/Xpressive/logo.png differ diff --git a/plugins/Xpressive/o1_active.png b/plugins/Xpressive/o1_active.png index 6370769dd27..8e31a8322c0 100644 Binary files a/plugins/Xpressive/o1_active.png and b/plugins/Xpressive/o1_active.png differ diff --git a/plugins/Xpressive/o1_inactive.png b/plugins/Xpressive/o1_inactive.png index 0fd4f8b2989..7a6b603e3e7 100644 Binary files a/plugins/Xpressive/o1_inactive.png and b/plugins/Xpressive/o1_inactive.png differ diff --git a/plugins/Xpressive/o2_active.png b/plugins/Xpressive/o2_active.png index 51897412d42..4e3b5f214d7 100644 Binary files a/plugins/Xpressive/o2_active.png and b/plugins/Xpressive/o2_active.png differ diff --git a/plugins/Xpressive/o2_inactive.png b/plugins/Xpressive/o2_inactive.png index 20158d72575..35851d5533f 100644 Binary files a/plugins/Xpressive/o2_inactive.png and b/plugins/Xpressive/o2_inactive.png differ diff --git a/plugins/Xpressive/w1_active.png b/plugins/Xpressive/w1_active.png index 49a3a2b6ec8..68d8e9ae088 100644 Binary files a/plugins/Xpressive/w1_active.png and b/plugins/Xpressive/w1_active.png differ diff --git a/plugins/Xpressive/w1_inactive.png b/plugins/Xpressive/w1_inactive.png index 266e4206fa7..7159b49799d 100644 Binary files a/plugins/Xpressive/w1_inactive.png and b/plugins/Xpressive/w1_inactive.png differ diff --git a/plugins/Xpressive/w2_active.png b/plugins/Xpressive/w2_active.png index cd4729949e1..17d7b53d935 100644 Binary files a/plugins/Xpressive/w2_active.png and b/plugins/Xpressive/w2_active.png differ diff --git a/plugins/Xpressive/w2_inactive.png b/plugins/Xpressive/w2_inactive.png index 8d54929da7b..412482bb0e4 100644 Binary files a/plugins/Xpressive/w2_inactive.png and b/plugins/Xpressive/w2_inactive.png differ diff --git a/plugins/Xpressive/w3_active.png b/plugins/Xpressive/w3_active.png index 9e4facb2cfa..579b997dd69 100644 Binary files a/plugins/Xpressive/w3_active.png and b/plugins/Xpressive/w3_active.png differ diff --git a/plugins/Xpressive/w3_inactive.png b/plugins/Xpressive/w3_inactive.png index e5b0bc7d9e1..d45d8b497ab 100644 Binary files a/plugins/Xpressive/w3_inactive.png and b/plugins/Xpressive/w3_inactive.png differ diff --git a/plugins/Xpressive/wavegraph.png b/plugins/Xpressive/wavegraph.png index 9d58e8fe732..ea7bc3761f1 100644 Binary files a/plugins/Xpressive/wavegraph.png and b/plugins/Xpressive/wavegraph.png differ diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index c1cd725c10e..95c4e60a875 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -22,6 +22,7 @@ * */ +#include "audio_file_processor.h" #include #include @@ -31,18 +32,18 @@ #include -#include "audio_file_processor.h" #include "ConfigManager.h" +#include "DataFile.h" #include "Engine.h" -#include "Song.h" +#include "gui_templates.h" #include "InstrumentTrack.h" +#include "interpolation.h" #include "Mixer.h" #include "NotePlayHandle.h" -#include "interpolation.h" -#include "gui_templates.h" -#include "ToolTip.h" +#include "PathUtil.h" +#include "Song.h" #include "StringPairDrag.h" -#include "DataFile.h" +#include "ToolTip.h" #include "embed.h" #include "plugin_export.h" @@ -97,13 +98,13 @@ audioFileProcessor::audioFileProcessor( InstrumentTrack * _instrument_track ) : this, SLOT( loopPointChanged() ) ); connect( &m_stutterModel, SIGNAL( dataChanged() ), this, SLOT( stutterModelChanged() ) ); - + //interpolation modes m_interpolationModel.addItem( tr( "None" ) ); m_interpolationModel.addItem( tr( "Linear" ) ); m_interpolationModel.addItem( tr( "Sinc" ) ); m_interpolationModel.setValue( 1 ); - + pointChanged(); } @@ -237,7 +238,7 @@ void audioFileProcessor::loadSettings( const QDomElement & _this ) { setAudioFile( _this.attribute( "src" ), false ); - QString absolutePath = m_sampleBuffer.tryToMakeAbsolute( m_sampleBuffer.audioFile() ); + QString absolutePath = PathUtil::toAbsolute( m_sampleBuffer.audioFile() ); if ( !QFileInfo( absolutePath ).exists() ) { QString message = tr( "Sample not found: %1" ).arg( m_sampleBuffer.audioFile() ); @@ -253,17 +254,16 @@ void audioFileProcessor::loadSettings( const QDomElement & _this ) m_loopModel.loadSettings( _this, "looped" ); m_ampModel.loadSettings( _this, "amp" ); m_endPointModel.loadSettings( _this, "eframe" ); + m_startPointModel.loadSettings( _this, "sframe" ); // compat code for not having a separate loopback point - if( _this.hasAttribute( "lframe" ) ) + if (_this.hasAttribute("lframe") || !(_this.firstChildElement("lframe").isNull())) { m_loopPointModel.loadSettings( _this, "lframe" ); - m_startPointModel.loadSettings( _this, "sframe" ); } else { m_loopPointModel.loadSettings( _this, "sframe" ); - m_startPointModel.setValue( m_loopPointModel.value() ); } m_reverseModel.loadSettings( _this, "reversed" ); @@ -330,7 +330,7 @@ void audioFileProcessor::setAudioFile( const QString & _audio_file, m_sampleBuffer.audioFile().isEmpty() ) ) { // then set it to new one - instrumentTrack()->setName( QFileInfo( _audio_file).fileName() ); + instrumentTrack()->setName( PathUtil::cleanName( _audio_file ) ); } // else we don't touch the track-name, because the user named it self @@ -364,7 +364,7 @@ void audioFileProcessor::stutterModelChanged() } -void audioFileProcessor::startPointChanged( void ) +void audioFileProcessor::startPointChanged( void ) { // check if start is over end and swap values if so if( m_startPointModel.value() > m_endPointModel.value() ) @@ -391,7 +391,7 @@ void audioFileProcessor::startPointChanged( void ) { m_endPointModel.setValue( qMin( m_endPointModel.value() + 0.001f, 1.0f ) ); } - + pointChanged(); } @@ -449,7 +449,7 @@ QPixmap * AudioFileProcessorView::s_artwork = NULL; AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { if( s_artwork == NULL ) { @@ -541,7 +541,7 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, // interpolation selector m_interpBox = new ComboBox( this ); - m_interpBox->setGeometry( 142, 62, 82, 22 ); + m_interpBox->setGeometry( 142, 62, 82, ComboBox::DEFAULT_HEIGHT ); m_interpBox->setFont( pointSize<8>( m_interpBox->font() ) ); // wavegraph @@ -1285,7 +1285,3 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main(Model * model, void *) } - - - - diff --git a/plugins/audio_file_processor/audio_file_processor.h b/plugins/audio_file_processor/audio_file_processor.h index d17be147c0c..0df7eeaf15c 100644 --- a/plugins/audio_file_processor/audio_file_processor.h +++ b/plugins/audio_file_processor/audio_file_processor.h @@ -111,7 +111,7 @@ private slots: class AudioFileProcessorWaveView; -class AudioFileProcessorView : public InstrumentView +class AudioFileProcessorView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/bit_invader/bit_invader.cpp b/plugins/bit_invader/bit_invader.cpp index 0d62bc2e612..caa272fa7f0 100644 --- a/plugins/bit_invader/bit_invader.cpp +++ b/plugins/bit_invader/bit_invader.cpp @@ -64,17 +64,16 @@ Plugin::Descriptor PLUGIN_EXPORT bitinvader_plugin_descriptor = } -bSynth::bSynth( float * _shape, int _length, NotePlayHandle * _nph, bool _interpolation, +bSynth::bSynth( float * _shape, NotePlayHandle * _nph, bool _interpolation, float _factor, const sample_rate_t _sample_rate ) : sample_index( 0 ), sample_realindex( 0 ), nph( _nph ), - sample_length( _length ), sample_rate( _sample_rate ), interpolation( _interpolation) { - sample_shape = new float[sample_length]; - for (int i=0; i < _length; ++i) + sample_shape = new float[200]; + for (int i=0; i < 200; ++i) { sample_shape[i] = _shape[i] * _factor; } @@ -87,7 +86,7 @@ bSynth::~bSynth() } -sample_t bSynth::nextStringSample() +sample_t bSynth::nextStringSample( float sample_length ) { float sample_step = static_cast( sample_length / ( sample_rate / nph->frequency() ) ); @@ -140,10 +139,12 @@ sample_t bSynth::nextStringSample() bitInvader::bitInvader( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &bitinvader_plugin_descriptor ), m_sampleLength( 128, 4, 200, 1, this, tr( "Sample length" ) ), - m_graph( -1.0f, 1.0f, 128, this ), + m_graph( -1.0f, 1.0f, 200, this ), m_interpolation( false, this ), m_normalize( false, this ) { + + lengthChanged(); m_graph.setWaveToSine(); @@ -278,7 +279,6 @@ void bitInvader::playNote( NotePlayHandle * _n, _n->m_pluginData = new bSynth( const_cast( m_graph.samples() ), - m_graph.length(), _n, m_interpolation.value(), factor, Engine::mixer()->processingSampleRate() ); @@ -290,7 +290,7 @@ void bitInvader::playNote( NotePlayHandle * _n, bSynth * ps = static_cast( _n->m_pluginData ); for( fpp_t frame = offset; frame < frames + offset; ++frame ) { - const sample_t cur = ps->nextStringSample(); + const sample_t cur = ps->nextStringSample( m_graph.length() ); for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) { _working_buffer[frame][chnl] = cur; @@ -326,7 +326,7 @@ PluginView * bitInvader::instantiateView( QWidget * _parent ) bitInvaderView::bitInvaderView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); QPalette pal; @@ -572,7 +572,3 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) } - - - - diff --git a/plugins/bit_invader/bit_invader.h b/plugins/bit_invader/bit_invader.h index 1489ab10434..ae9c92cb264 100644 --- a/plugins/bit_invader/bit_invader.h +++ b/plugins/bit_invader/bit_invader.h @@ -42,12 +42,12 @@ class bSynth { MM_OPERATORS public: - bSynth( float * sample, int length, NotePlayHandle * _nph, + bSynth( float * sample, NotePlayHandle * _nph, bool _interpolation, float factor, const sample_rate_t _sample_rate ); virtual ~bSynth(); - sample_t nextStringSample(); + sample_t nextStringSample( float sample_length ); private: @@ -55,7 +55,6 @@ class bSynth float sample_realindex; float* sample_shape; NotePlayHandle* nph; - const int sample_length; const sample_rate_t sample_rate; bool interpolation; @@ -108,7 +107,7 @@ protected slots: -class bitInvaderView : public InstrumentView +class bitInvaderView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/carlabase/CMakeLists.txt b/plugins/carlabase/CMakeLists.txt index 0311ca8ee2b..28a1bc88c51 100644 --- a/plugins/carlabase/CMakeLists.txt +++ b/plugins/carlabase/CMakeLists.txt @@ -6,15 +6,45 @@ IF(NOT CMAKE_VERSION VERSION_LESS 3.9) CMAKE_POLICY(SET CMP0068 OLD) ENDIF() -if(LMMS_HAVE_CARLA) +# If Carla was not provided by the system, make a dummy library instead +if(LMMS_HAVE_WEAKCARLA) + SET(CARLA_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/carla/source + ${CMAKE_CURRENT_SOURCE_DIR}/carla/source/includes + ${CMAKE_CURRENT_SOURCE_DIR}/carla/source/utils + ${CMAKE_CURRENT_SOURCE_DIR}/carla/source/backend + ) + ADD_LIBRARY(carla_native-plugin SHARED DummyCarla.cpp) + TARGET_INCLUDE_DIRECTORIES(carla_native-plugin PUBLIC ${CARLA_INCLUDE_DIRS}) + INSTALL(TARGETS carla_native-plugin + LIBRARY DESTINATION "${PLUGIN_DIR}/optional" + RUNTIME DESTINATION "${PLUGIN_DIR}/optional" + ) + SET(CARLA_LIBRARIES carla_native-plugin) + # Set parent scope variables so carlarack and carlapatchbay can see them + SET(CARLA_LIBRARIES ${CARLA_LIBRARIES} PARENT_SCOPE) +endif() + +if(LMMS_HAVE_CARLA OR LMMS_HAVE_WEAKCARLA) + # Mimic the missing "config.h" + SET(CARLA_INCLUDE_DIRS ${CARLA_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/CarlaConfig) + SET(CARLA_INCLUDE_DIRS ${CARLA_INCLUDE_DIRS} PARENT_SCOPE) + INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS}) LINK_DIRECTORIES(${CARLA_LIBRARY_DIRS}) LINK_LIBRARIES(${CARLA_LIBRARIES}) - BUILD_PLUGIN(carlabase carla.cpp carla.h MOCFILES carla.h EMBEDDED_RESOURCES artwork-patchbay.png artwork-rack.png LINK SHARED) + BUILD_PLUGIN(carlabase carla.cpp carla.h + MOCFILES carla.h + EMBEDDED_RESOURCES artwork-patchbay.png artwork-rack.png + EXPORT_BASE_NAME carlabase + LINK SHARED) SET_TARGET_PROPERTIES(carlabase PROPERTIES SKIP_BUILD_RPATH TRUE BUILD_WITH_INSTALL_RPATH TRUE INSTALL_RPATH_USE_LINK_PATH TRUE INSTALL_RPATH "${CARLA_RPATH}") -endif(LMMS_HAVE_CARLA) + IF(LMMS_HAVE_WEAKCARLA) + ADD_DEPENDENCIES(carlabase carla_native-plugin) + ENDIF() +endif() diff --git a/plugins/carlabase/CarlaConfig/config.h b/plugins/carlabase/CarlaConfig/config.h new file mode 100644 index 00000000000..46b3f34649c --- /dev/null +++ b/plugins/carlabase/CarlaConfig/config.h @@ -0,0 +1,9 @@ +// config.h for Carla +#ifndef FOR_CARLA_CONFIG_H +#define FOR_CARLA_CONFIG_H + +#ifdef _MSC_VER +#define HAVE_CPP11_SUPPORT 1 +#endif + +#endif diff --git a/plugins/carlabase/DummyCarla.cpp b/plugins/carlabase/DummyCarla.cpp new file mode 100644 index 00000000000..8fd9ef6d7e6 --- /dev/null +++ b/plugins/carlabase/DummyCarla.cpp @@ -0,0 +1,13 @@ +// A dummy Carla interface +#define BUILDING_CARLA +#include "CarlaNativePlugin.h" + +CARLA_EXPORT const char* carla_get_library_filename() { return nullptr; } +CARLA_EXPORT const char* carla_get_library_folder() { return nullptr; } +CARLA_EXPORT const NativePluginDescriptor* carla_get_native_rack_plugin() { return nullptr; } +CARLA_EXPORT const NativePluginDescriptor* carla_get_native_patchbay_plugin() { return nullptr; } +CARLA_EXPORT const NativePluginDescriptor* carla_get_native_patchbay16_plugin() { return nullptr; } +CARLA_EXPORT const NativePluginDescriptor* carla_get_native_patchbay32_plugin() { return nullptr; } +CARLA_EXPORT const NativePluginDescriptor* carla_get_native_patchbay64_plugin() { return nullptr; } +CARLA_EXPORT const NativePluginDescriptor* carla_get_native_patchbay_cv_plugin() { return nullptr; } +CARLA_EXPORT CarlaBackend::CarlaEngine* carla_get_native_plugin_engine(const NativePluginDescriptor* desc, NativePluginHandle handle) { return nullptr; } diff --git a/plugins/carlabase/carla b/plugins/carlabase/carla new file mode 160000 index 00000000000..4ac8ff2ef41 --- /dev/null +++ b/plugins/carlabase/carla @@ -0,0 +1 @@ +Subproject commit 4ac8ff2ef412d4ab190d2e285e318b1f339af4ae diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp index 578c3ac6597..a6faa4d275d 100644 --- a/plugins/carlabase/carla.cpp +++ b/plugins/carlabase/carla.cpp @@ -324,17 +324,23 @@ void CarlaInstrument::play(sampleFrame* workingBuffer) fTimeInfo.playing = s->isPlaying(); fTimeInfo.frame = s->getPlayPos(s->playMode()).frames(Engine::framesPerTick()); fTimeInfo.usecs = s->getMilliseconds()*1000; - fTimeInfo.bbt.bar = s->getTacts() + 1; + fTimeInfo.bbt.bar = s->getBars() + 1; fTimeInfo.bbt.beat = s->getBeat() + 1; fTimeInfo.bbt.tick = s->getBeatTicks(); - fTimeInfo.bbt.barStartTick = ticksPerBeat*s->getTimeSigModel().getNumerator()*s->getTacts(); + fTimeInfo.bbt.barStartTick = ticksPerBeat*s->getTimeSigModel().getNumerator()*s->getBars(); fTimeInfo.bbt.beatsPerBar = s->getTimeSigModel().getNumerator(); fTimeInfo.bbt.beatType = s->getTimeSigModel().getDenominator(); fTimeInfo.bbt.ticksPerBeat = ticksPerBeat; fTimeInfo.bbt.beatsPerMinute = s->getTempo(); +#ifndef _MSC_VER float buf1[bufsize]; float buf2[bufsize]; +#else + float *buf1 = static_cast(_alloca(bufsize * sizeof(float))); + float *buf2 = static_cast(_alloca(bufsize * sizeof(float))); +#endif + float* rBuf[] = { buf1, buf2 }; std::memset(buf1, 0, sizeof(float)*bufsize); std::memset(buf2, 0, sizeof(float)*bufsize); @@ -438,7 +444,8 @@ PluginView* CarlaInstrument::instantiateView(QWidget* parent) // Disable plugin focus per https://bugreports.qt.io/browse/QTBUG-30181 #ifndef CARLA_OS_MAC if (QWidget* const window = parent->window()) - fHost.uiParentId = window->winId(); + // TODO: Remove cast; Only needed for Qt4 + fHost.uiParentId = (uintptr_t)window->winId(); else #endif fHost.uiParentId = 0; @@ -460,7 +467,7 @@ void CarlaInstrument::sampleRateChanged() // ------------------------------------------------------------------- CarlaInstrumentView::CarlaInstrumentView(CarlaInstrument* const instrument, QWidget* const parent) - : InstrumentView(instrument, parent), + : InstrumentViewFixedSize(instrument, parent), fHandle(instrument->fHandle), fDescriptor(instrument->fDescriptor), fTimerId(fHandle != NULL && fDescriptor->ui_idle != NULL ? startTimer(30) : 0) diff --git a/plugins/carlabase/carla.h b/plugins/carlabase/carla.h index a4efb67e0f5..2c683add935 100644 --- a/plugins/carlabase/carla.h +++ b/plugins/carlabase/carla.h @@ -26,10 +26,9 @@ #define CARLA_H #include -#include "plugin_export.h" +#include "carlabase_export.h" #include "CarlaNative.h" -#define REAL_BUILD // FIXME this shouldn't be needed #if CARLA_VERSION_HEX >= 0x010911 #include "CarlaNativePlugin.h" #else @@ -48,7 +47,7 @@ class QPushButton; -class PLUGIN_EXPORT CarlaInstrument : public Instrument +class CARLABASE_EXPORT CarlaInstrument : public Instrument { Q_OBJECT @@ -99,7 +98,7 @@ private slots: friend class CarlaInstrumentView; }; -class CarlaInstrumentView : public InstrumentView +class CarlaInstrumentView : public InstrumentViewFixedSize { Q_OBJECT diff --git a/plugins/carlabase/logo.png b/plugins/carlabase/logo.png new file mode 100644 index 00000000000..353d5d718d6 Binary files /dev/null and b/plugins/carlabase/logo.png differ diff --git a/plugins/carlapatchbay/CMakeLists.txt b/plugins/carlapatchbay/CMakeLists.txt index 64a21a605c9..70d3beec780 100644 --- a/plugins/carlapatchbay/CMakeLists.txt +++ b/plugins/carlapatchbay/CMakeLists.txt @@ -1,4 +1,4 @@ -if(LMMS_HAVE_CARLA) +if(LMMS_HAVE_CARLA OR LMMS_HAVE_WEAKCARLA) ADD_DEFINITIONS(-DCARLA_PLUGIN_PATCHBAY -DCARLA_PLUGIN_SYNTH) INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../carlabase") @@ -6,4 +6,4 @@ if(LMMS_HAVE_CARLA) ${CARLA_LIBRARY_DIRS}) LINK_LIBRARIES(carlabase) BUILD_PLUGIN(carlapatchbay carlapatchbay.cpp EMBEDDED_RESOURCES logo.png) -endif(LMMS_HAVE_CARLA) +endif() diff --git a/plugins/carlapatchbay/carlapatchbay.cpp b/plugins/carlapatchbay/carlapatchbay.cpp index ac00630d44d..ad0c1f6aef5 100644 --- a/plugins/carlapatchbay/carlapatchbay.cpp +++ b/plugins/carlapatchbay/carlapatchbay.cpp @@ -25,6 +25,7 @@ #include "carla.h" #include "embed.h" +#include "plugin_export.h" #include "InstrumentTrack.h" extern "C" diff --git a/plugins/carlarack/CMakeLists.txt b/plugins/carlarack/CMakeLists.txt index 1d9cb975a12..ea0262199f2 100644 --- a/plugins/carlarack/CMakeLists.txt +++ b/plugins/carlarack/CMakeLists.txt @@ -1,4 +1,4 @@ -if(LMMS_HAVE_CARLA) +if(LMMS_HAVE_CARLA OR LMMS_HAVE_WEAKCARLA) ADD_DEFINITIONS(-DCARLA_PLUGIN_RACK -DCARLA_PLUGIN_SYNTH) INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../carlabase") @@ -6,4 +6,4 @@ if(LMMS_HAVE_CARLA) ${CARLA_LIBRARY_DIRS}) LINK_LIBRARIES(carlabase) BUILD_PLUGIN(carlarack carlarack.cpp EMBEDDED_RESOURCES logo.png) -endif(LMMS_HAVE_CARLA) +endif() diff --git a/plugins/carlarack/carlarack.cpp b/plugins/carlarack/carlarack.cpp index c0a39f9c258..ee2a788354f 100644 --- a/plugins/carlarack/carlarack.cpp +++ b/plugins/carlarack/carlarack.cpp @@ -25,6 +25,7 @@ #include "carla.h" #include "embed.h" +#include "plugin_export.h" #include "InstrumentTrack.h" extern "C" diff --git a/plugins/dynamics_processor/dynamics_processor.cpp b/plugins/dynamics_processor/dynamics_processor.cpp index 8c02b827da4..9bf7d9b3c90 100644 --- a/plugins/dynamics_processor/dynamics_processor.cpp +++ b/plugins/dynamics_processor/dynamics_processor.cpp @@ -215,10 +215,10 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf, s[0] *= outputGain; s[1] *= outputGain; - out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1]; // mix wet/dry signals _buf[f][0] = d * _buf[f][0] + w * s[0]; _buf[f][1] = d * _buf[f][1] + w * s[1]; + out_sum += _buf[f][0] * _buf[f][0] + _buf[f][1] * _buf[f][1]; } checkGate( out_sum / _frames ); diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index d204babab23..5f36aae93f1 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -267,7 +267,7 @@ class kickerLargeKnob : public Knob kickerInstrumentView::kickerInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { const int ROW1 = 14; const int ROW2 = ROW1 + 56; diff --git a/plugins/kicker/kicker.h b/plugins/kicker/kicker.h index 295887c2f4f..22b2b854fa7 100644 --- a/plugins/kicker/kicker.h +++ b/plugins/kicker/kicker.h @@ -94,7 +94,7 @@ class kickerInstrument : public Instrument -class kickerInstrumentView : public InstrumentView +class kickerInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/lb302/README b/plugins/lb302/README index 2a8058e56d8..b556d80d406 100644 --- a/plugins/lb302/README +++ b/plugins/lb302/README @@ -15,7 +15,7 @@ BUG: to be caused by 'unexhausted buffers' That is, the problem manifests itself to a greater degree when the user "buffer size" configuration is increased to over 1024 frames or so. The problem is much less - noticable when the buffer size is set to 64 frames. + noticeable when the buffer size is set to 64 frames. BUG: The synth does not make accomodations for sampling rates other than diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 91e811276d3..ad3d33b0a04 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -803,7 +803,7 @@ PluginView * lb302Synth::instantiateView( QWidget * _parent ) lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { // GUI m_vcfCutKnob = new Knob( knobBright_26, this ); diff --git a/plugins/lb302/lb302.h b/plugins/lb302/lb302.h index 3ca22c78bb7..557d958d462 100644 --- a/plugins/lb302/lb302.h +++ b/plugins/lb302/lb302.h @@ -256,7 +256,7 @@ public slots: } ; -class lb302SynthView : public InstrumentView +class lb302SynthView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 4ea679347de..d4fb372a4a5 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -328,7 +328,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) float o1l_f; float o1r_f; float o1l_p = m_osc1l_phase + o1lpo; // we add phase offset here so we don't have to do it every frame - float o1r_p = m_osc1r_phase + o1rpo; // then substract it again after loop... + float o1r_p = m_osc1r_phase + o1rpo; // then subtract it again after loop... float o1_pw; // osc2 vars @@ -1447,7 +1447,7 @@ void MonstroInstrument::updateSlope2() MonstroView::MonstroView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { m_operatorsView = setupOperatorsView( this ); setWidgetBackground( m_operatorsView, "artwork_op" ); @@ -1664,7 +1664,7 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) m_osc2VolKnob -> setVolumeKnob( true ); m_osc2WaveBox = new ComboBox( view ); - m_osc2WaveBox -> setGeometry( 204, O2ROW + 7, 42, 22 ); + m_osc2WaveBox -> setGeometry( 204, O2ROW + 7, 42, ComboBox::DEFAULT_HEIGHT ); m_osc2WaveBox->setFont( pointSize<8>( m_osc2WaveBox->font() ) ); maketinyled( m_osc2SyncHButton, 212, O2ROW - 3, tr( "Hard sync oscillator 2" ) ) @@ -1679,18 +1679,18 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) m_osc3VolKnob -> setVolumeKnob( true ); m_osc3Wave1Box = new ComboBox( view ); - m_osc3Wave1Box -> setGeometry( 160, O3ROW + 7, 42, 22 ); + m_osc3Wave1Box -> setGeometry( 160, O3ROW + 7, 42, ComboBox::DEFAULT_HEIGHT ); m_osc3Wave1Box->setFont( pointSize<8>( m_osc3Wave1Box->font() ) ); m_osc3Wave2Box = new ComboBox( view ); - m_osc3Wave2Box -> setGeometry( 204, O3ROW + 7, 42, 22 ); + m_osc3Wave2Box -> setGeometry( 204, O3ROW + 7, 42, ComboBox::DEFAULT_HEIGHT ); m_osc3Wave2Box->setFont( pointSize<8>( m_osc3Wave2Box->font() ) ); maketinyled( m_osc3SyncHButton, 212, O3ROW - 3, tr( "Hard sync oscillator 3" ) ) maketinyled( m_osc3SyncRButton, 191, O3ROW - 3, tr( "Reverse sync oscillator 3" ) ) m_lfo1WaveBox = new ComboBox( view ); - m_lfo1WaveBox -> setGeometry( 2, LFOROW + 7, 42, 22 ); + m_lfo1WaveBox -> setGeometry( 2, LFOROW + 7, 42, ComboBox::DEFAULT_HEIGHT ); m_lfo1WaveBox->setFont( pointSize<8>( m_lfo1WaveBox->font() ) ); maketsknob( m_lfo1AttKnob, LFOCOL1, LFOROW, tr( "Attack" ), " ms", "lfoKnob" ) @@ -1698,7 +1698,7 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) makeknob( m_lfo1PhsKnob, LFOCOL3, LFOROW, tr( "Phase" ), tr( " deg" ), "lfoKnob" ) m_lfo2WaveBox = new ComboBox( view ); - m_lfo2WaveBox -> setGeometry( 127, LFOROW + 7, 42, 22 ); + m_lfo2WaveBox -> setGeometry( 127, LFOROW + 7, 42, ComboBox::DEFAULT_HEIGHT ); m_lfo2WaveBox->setFont( pointSize<8>( m_lfo2WaveBox->font() ) ); maketsknob( m_lfo2AttKnob, LFOCOL4, LFOROW, tr( "Attack" ), " ms", "lfoKnob" ) diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index a8b1869044e..fc0cc13b06d 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -569,7 +569,7 @@ public slots: }; -class MonstroView : public InstrumentView +class MonstroView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/nes/Nes.cpp b/plugins/nes/Nes.cpp index b973f435625..d4bcc6881d1 100644 --- a/plugins/nes/Nes.cpp +++ b/plugins/nes/Nes.cpp @@ -731,7 +731,7 @@ QPixmap * NesInstrumentView::s_artwork = NULL; NesInstrumentView::NesInstrumentView( Instrument * instrument, QWidget * parent ) : - InstrumentView( instrument, parent ) + InstrumentViewFixedSize( instrument, parent ) { setAutoFillBackground( true ); QPalette pal; diff --git a/plugins/nes/Nes.h b/plugins/nes/Nes.h index 20f70373932..bbf326d3271 100644 --- a/plugins/nes/Nes.h +++ b/plugins/nes/Nes.h @@ -294,7 +294,7 @@ public slots: }; -class NesInstrumentView : public InstrumentView +class NesInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/organic/organic.cpp b/plugins/organic/organic.cpp index de5f08ff7f0..6eb933afad3 100644 --- a/plugins/organic/organic.cpp +++ b/plugins/organic/organic.cpp @@ -306,7 +306,7 @@ void organicInstrument::playNote( NotePlayHandle * _n, // fxKnob is [0;1] float t = m_fx1Model.value(); - for (int i=0 ; i < frames ; i++) + for (int i=0 ; i < frames + offset ; i++) { _working_buffer[i][0] = waveshape( _working_buffer[i][0], t ) * m_volModel.value() / 100.0f; @@ -417,7 +417,7 @@ class organicKnob : public Knob organicInstrumentView::organicInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ), + InstrumentViewFixedSize( _instrument, _parent ), m_oscKnobs( NULL ) { organicInstrument * oi = castModel(); diff --git a/plugins/organic/organic.h b/plugins/organic/organic.h index 86b25ea7719..c0bc29f16e8 100644 --- a/plugins/organic/organic.h +++ b/plugins/organic/organic.h @@ -173,7 +173,7 @@ private slots: } ; -class organicInstrumentView : public InstrumentView +class organicInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/patman/patman.cpp b/plugins/patman/patman.cpp index 0ea9968dae7..e5170383438 100644 --- a/plugins/patman/patman.cpp +++ b/plugins/patman/patman.cpp @@ -3,7 +3,7 @@ * * Copyright (c) 2007-2008 Javier Serrano Polo * Copyright (c) 2009-2014 Tobias Doerffel - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -32,15 +32,15 @@ #include "ConfigManager.h" #include "endian_handling.h" #include "Engine.h" +#include "FileDialog.h" #include "gui_templates.h" #include "InstrumentTrack.h" #include "NotePlayHandle.h" +#include "PathUtil.h" #include "PixmapButton.h" #include "Song.h" #include "StringPairDrag.h" #include "ToolTip.h" -#include "FileDialog.h" -#include "ConfigManager.h" #include "embed.h" @@ -192,14 +192,13 @@ void patmanInstrument::setFile( const QString & _patch_file, bool _rename ) m_patchFile == "" ) ) { // then set it to new one - instrumentTrack()->setName( QFileInfo( _patch_file - ).fileName() ); + instrumentTrack()->setName( PathUtil::cleanName( _patch_file ) ); } // else we don't touch the instrument-track-name, because the user // named it self - m_patchFile = SampleBuffer::tryToMakeRelative( _patch_file ); - LoadErrors error = loadPatch( SampleBuffer::tryToMakeAbsolute( _patch_file ) ); + m_patchFile = PathUtil::toShortestRelative( _patch_file ); + LoadErrors error = loadPatch( PathUtil::toAbsolute( _patch_file ) ); if( error ) { printf("Load error\n"); @@ -443,7 +442,7 @@ PluginView * patmanInstrument::instantiateView( QWidget * _parent ) PatmanView::PatmanView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ), + InstrumentViewFixedSize( _instrument, _parent ), m_pi( NULL ) { setAutoFillBackground( true ); @@ -625,8 +624,8 @@ void PatmanView::paintEvent( QPaintEvent * ) QPainter p( this ); p.setFont( pointSize<8>( font() ) ); - p.drawText( 8, 116, 235, 16, - Qt::AlignLeft | Qt::TextSingleLine | Qt::AlignVCenter, + p.drawText( 8, 116, 235, 16, + Qt::AlignLeft | Qt::TextSingleLine | Qt::AlignVCenter, m_displayFilename ); } @@ -641,8 +640,3 @@ void PatmanView::modelChanged( void ) connect( m_pi, SIGNAL( fileChanged() ), this, SLOT( updateFilename() ) ); } - - - - - diff --git a/plugins/patman/patman.h b/plugins/patman/patman.h index a3b5a39b898..8d5689b7363 100644 --- a/plugins/patman/patman.h +++ b/plugins/patman/patman.h @@ -116,7 +116,7 @@ public slots: -class PatmanView : public InstrumentView +class PatmanView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/peak_controller_effect/peak_controller_effect.h b/plugins/peak_controller_effect/peak_controller_effect.h index 093b564379e..a872e2b8b46 100644 --- a/plugins/peak_controller_effect/peak_controller_effect.h +++ b/plugins/peak_controller_effect/peak_controller_effect.h @@ -36,9 +36,9 @@ class PeakControllerEffect : public Effect const Descriptor::SubPluginFeatures::Key * _key ); virtual ~PeakControllerEffect(); virtual bool processAudioBuffer( sampleFrame * _buf, - const fpp_t _frames ); + const fpp_t _frames ) override; - virtual EffectControls * controls() + EffectControls * controls() override { return &m_peakControls; } diff --git a/plugins/peak_controller_effect/peak_controller_effect_controls.h b/plugins/peak_controller_effect/peak_controller_effect_controls.h index 784df4d8d20..fe90eddca85 100644 --- a/plugins/peak_controller_effect/peak_controller_effect_controls.h +++ b/plugins/peak_controller_effect/peak_controller_effect_controls.h @@ -41,18 +41,18 @@ class PeakControllerEffectControls : public EffectControls { } - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const + void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; + void loadSettings( const QDomElement & _this ) override; + inline QString nodeName() const override { return "peakcontrollereffectcontrols"; } - virtual int controlCount() + int controlCount() override { return 1; } - virtual EffectControlDialog * createView() + EffectControlDialog * createView() override { return new PeakControllerEffectControlDialog( this ); } diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 138e8165d17..7065a08002c 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -23,6 +23,8 @@ * */ +#include "sf2_player.h" + #include #include #include @@ -30,14 +32,14 @@ #include "ConfigManager.h" #include "FileDialog.h" -#include "sf2_player.h" #include "ConfigManager.h" #include "Engine.h" #include "InstrumentTrack.h" #include "InstrumentPlayHandle.h" +#include "Knob.h" #include "Mixer.h" #include "NotePlayHandle.h" -#include "Knob.h" +#include "PathUtil.h" #include "SampleBuffer.h" #include "Song.h" @@ -151,7 +153,7 @@ sf2Instrument::sf2Instrument( InstrumentTrack * _instrument_track ) : m_chorusDepth.setInitValue(settingVal); #endif - loadFile( ConfigManager::inst()->defaultSoundfont() ); + loadFile( ConfigManager::inst()->sf2File() ); updateSampleRate(); updateReverbOn(); @@ -267,6 +269,43 @@ void sf2Instrument::loadFile( const QString & _file ) // soundfont for the first time fails updateSampleRate(); } + + // setting the first bank and patch number that is found + auto sSoundCount = ::fluid_synth_sfcount( m_synth ); + for ( int i = 0; i < sSoundCount; ++i ) { + int iBank = 0; + int iProg = 0; + fluid_sfont_t *pSoundFont = ::fluid_synth_get_sfont( m_synth, i ); + + if ( pSoundFont ) { +#ifdef CONFIG_FLUID_BANK_OFFSET + int iBankOff = ::fluid_synth_get_bank_offset( m_synth, fluid_sfont_get_id( pSoundFont ) ); +#endif + + fluid_sfont_iteration_start( pSoundFont ); +#if FLUIDSYNTH_VERSION_MAJOR < 2 + fluid_preset_t preset; + fluid_preset_t *pCurPreset = &preset; +#else + fluid_preset_t *pCurPreset; +#endif + + if ( ( pCurPreset = fluid_sfont_iteration_next_wrapper( pSoundFont, pCurPreset ) ) ) { + iBank = fluid_preset_get_banknum( pCurPreset ); + iProg = fluid_preset_get_num( pCurPreset ); + +#ifdef CONFIG_FLUID_BANK_OFFSET + iBank += iBankOff; +#endif + + ::fluid_synth_bank_select( m_synth, 1, iBank ); + ::fluid_synth_program_change( m_synth, 1, iProg ); + m_bankNum.setValue( iBank ); + m_patchNum.setValue ( iProg ); + break; + } + } + } } @@ -335,8 +374,8 @@ void sf2Instrument::openFile( const QString & _sf2File, bool updateTrackName ) emit fileLoading(); // Used for loading file - char * sf2Ascii = qstrdup( qPrintable( SampleBuffer::tryToMakeAbsolute( _sf2File ) ) ); - QString relativePath = SampleBuffer::tryToMakeRelative( _sf2File ); + char * sf2Ascii = qstrdup( qPrintable( PathUtil::toAbsolute( _sf2File ) ) ); + QString relativePath = PathUtil::toShortestRelative( _sf2File ); // free reference to soundfont if one is selected freeFont(); @@ -359,18 +398,24 @@ void sf2Instrument::openFile( const QString & _sf2File, bool updateTrackName ) // Add to map, if doesn't exist. else { - m_fontId = fluid_synth_sfload( m_synth, sf2Ascii, true ); - - if( fluid_synth_sfcount( m_synth ) > 0 ) + bool loaded = false; + if( fluid_is_soundfont( sf2Ascii ) ) { - // Grab this sf from the top of the stack and add to list - m_font = new sf2Font( fluid_synth_get_sfont( m_synth, 0 ) ); - s_fonts.insert( relativePath, m_font ); + m_fontId = fluid_synth_sfload( m_synth, sf2Ascii, true ); + + if( fluid_synth_sfcount( m_synth ) > 0 ) + { + // Grab this sf from the top of the stack and add to list + m_font = new sf2Font( fluid_synth_get_sfont( m_synth, 0 ) ); + s_fonts.insert( relativePath, m_font ); + loaded = true; + } } - else + + if(!loaded) { - collectErrorForUI( sf2Instrument::tr( "A soundfont %1 could not be loaded." ).arg( QFileInfo( _sf2File ).baseName() ) ); - // TODO: Why is the filename missing when the file does not exist? + collectErrorForUI( sf2Instrument::tr( "A soundfont %1 could not be loaded." ). + arg( QFileInfo( _sf2File ).baseName() ) ); } } @@ -392,7 +437,7 @@ void sf2Instrument::openFile( const QString & _sf2File, bool updateTrackName ) if( updateTrackName || instrumentTrack()->displayName() == displayName() ) { - instrumentTrack()->setName( QFileInfo( _sf2File ).baseName() ); + instrumentTrack()->setName( PathUtil::cleanName( _sf2File ) ); } } @@ -678,7 +723,6 @@ void sf2Instrument::noteOff( SF2PluginData * n ) fluid_synth_noteoff( m_synth, m_channel, n->midiNote ); m_synthMutex.unlock(); } - } @@ -694,7 +738,6 @@ void sf2Instrument::play( sampleFrame * _working_buffer ) m_synthMutex.lock(); fluid_synth_pitch_bend( m_synth, m_channel, m_lastMidiPitch ); m_synthMutex.unlock(); - } const int currentMidiPitchRange = instrumentTrack()->midiPitchRange(); @@ -859,7 +902,7 @@ class sf2Knob : public Knob sf2InstrumentView::sf2InstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { // QVBoxLayout * vl = new QVBoxLayout( this ); // QHBoxLayout * hl = new QHBoxLayout(); @@ -1006,7 +1049,6 @@ sf2InstrumentView::sf2InstrumentView( Instrument * _instrument, QWidget * _paren setPalette( pal ); updateFilename(); - } @@ -1045,7 +1087,6 @@ void sf2InstrumentView::modelChanged() connect( k, SIGNAL( fileLoading() ), this, SLOT( invalidateFile() ) ); updateFilename(); - } @@ -1106,7 +1147,7 @@ void sf2InstrumentView::showFileDialog() if( k->m_filename != "" ) { - QString f = SampleBuffer::tryToMakeAbsolute( k->m_filename ); + QString f = PathUtil::toAbsolute( k->m_filename ); ofd.setDirectory( QFileInfo( f ).absolutePath() ); ofd.selectFile( QFileInfo( f ).fileName() ); } @@ -1157,6 +1198,3 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) } - - - diff --git a/plugins/sf2_player/sf2_player.h b/plugins/sf2_player/sf2_player.h index eed7e24ab3d..1dde587ad5e 100644 --- a/plugins/sf2_player/sf2_player.h +++ b/plugins/sf2_player/sf2_player.h @@ -187,7 +187,7 @@ class sf2Font -class sf2InstrumentView : public InstrumentView +class sf2InstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/sfxr/sfxr.cpp b/plugins/sfxr/sfxr.cpp index cdace1a30e2..1aacdc12c3b 100644 --- a/plugins/sfxr/sfxr.cpp +++ b/plugins/sfxr/sfxr.cpp @@ -600,7 +600,7 @@ class sfxrKnob : public Knob sfxrInstrumentView::sfxrInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { srand(time(NULL)); setAutoFillBackground( true ); diff --git a/plugins/sfxr/sfxr.h b/plugins/sfxr/sfxr.h index 27246a1b8fc..20ae54c96fe 100644 --- a/plugins/sfxr/sfxr.h +++ b/plugins/sfxr/sfxr.h @@ -223,7 +223,7 @@ class sfxrInstrument : public Instrument -class sfxrInstrumentView : public InstrumentView +class sfxrInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/sid/envelope.cc b/plugins/sid/envelope.cc index 7be289c53e3..e466bd67dc4 100644 --- a/plugins/sid/envelope.cc +++ b/plugins/sid/envelope.cc @@ -134,7 +134,7 @@ reg16 EnvelopeGenerator::rate_counter_period[] = { // of ENV3 with another timed loop to fully synchronize with ENV3. // // At the first period when an exponential counter period larger than one -// is used (decay or relase), one extra cycle is spent before the envelope is +// is used (decay or release), one extra cycle is spent before the envelope is // decremented. The envelope output is then delayed one cycle until the state // is changed to attack. Now one cycle less will be spent before the envelope // is incremented, and the situation is normalized. diff --git a/plugins/sid/sid_instrument.cpp b/plugins/sid/sid_instrument.cpp index fcb0b82a790..27f874e12dc 100644 --- a/plugins/sid/sid_instrument.cpp +++ b/plugins/sid/sid_instrument.cpp @@ -483,7 +483,7 @@ class sidKnob : public Knob sidInstrumentView::sidInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); diff --git a/plugins/sid/sid_instrument.h b/plugins/sid/sid_instrument.h index 6128bf91c11..479d09c5df1 100644 --- a/plugins/sid/sid_instrument.h +++ b/plugins/sid/sid_instrument.h @@ -132,7 +132,7 @@ class sidInstrument : public Instrument -class sidInstrumentView : public InstrumentView +class sidInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/stk/mallets/mallets.cpp b/plugins/stk/mallets/mallets.cpp index ee1e1fbc371..96bc5f63e9b 100644 --- a/plugins/stk/mallets/mallets.cpp +++ b/plugins/stk/mallets/mallets.cpp @@ -338,6 +338,7 @@ void malletsInstrument::playNote( NotePlayHandle * _n, Engine::mixer()->processingSampleRate() ); } m.unlock(); + static_cast(_n->m_pluginData)->setPresetIndex(p); } const fpp_t frames = _n->framesLeftForCurrentPeriod(); @@ -345,6 +346,7 @@ void malletsInstrument::playNote( NotePlayHandle * _n, malletsSynth * ps = static_cast( _n->m_pluginData ); ps->setFrequency( freq ); + p = ps->presetIndex(); sample_t add_scale = 0.0f; if( p == 10 && m_isOldVersionModel.value() == true ) @@ -355,9 +357,9 @@ void malletsInstrument::playNote( NotePlayHandle * _n, for( fpp_t frame = offset; frame < frames + offset; ++frame ) { _working_buffer[frame][0] = ps->nextSampleLeft() * - ( m_scalers[m_presetsModel.value()] + add_scale ); + ( m_scalers[p] + add_scale ); _working_buffer[frame][1] = ps->nextSampleRight() * - ( m_scalers[m_presetsModel.value()] + add_scale ); + ( m_scalers[p] + add_scale ); } instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); @@ -384,7 +386,7 @@ PluginView * malletsInstrument::instantiateView( QWidget * _parent ) malletsInstrumentView::malletsInstrumentView( malletsInstrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { m_modalBarWidget = setupModalBarControls( this ); setWidgetBackground( m_modalBarWidget, "artwork" ); @@ -401,7 +403,7 @@ malletsInstrumentView::malletsInstrumentView( malletsInstrument * _instrument, changePreset(); // Show widget m_presetsCombo = new ComboBox( this, tr( "Instrument" ) ); - m_presetsCombo->setGeometry( 140, 50, 99, 22 ); + m_presetsCombo->setGeometry( 140, 50, 99, ComboBox::DEFAULT_HEIGHT ); m_presetsCombo->setFont( pointSize<8>( m_presetsCombo->font() ) ); connect( &_instrument->m_presetsModel, SIGNAL( dataChanged() ), @@ -579,7 +581,6 @@ void malletsInstrumentView::modelChanged() void malletsInstrumentView::changePreset() { malletsInstrument * inst = castModel(); - inst->instrumentTrack()->silenceAllNotes(); int _preset = inst->m_presetsModel.value(); if( _preset < 9 ) @@ -614,7 +615,8 @@ malletsSynth::malletsSynth( const StkFloat _pitch, const StkFloat _control11, const int _control16, const uint8_t _delay, - const sample_rate_t _sample_rate ) + const sample_rate_t _sample_rate ) : + m_presetIndex(0) { try { @@ -664,7 +666,8 @@ malletsSynth::malletsSynth( const StkFloat _pitch, const StkFloat _control11, const StkFloat _control128, const uint8_t _delay, - const sample_rate_t _sample_rate ) + const sample_rate_t _sample_rate ) : + m_presetIndex(0) { try { @@ -712,7 +715,8 @@ malletsSynth::malletsSynth( const StkFloat _pitch, const StkFloat _control64, const StkFloat _control128, const uint8_t _delay, - const sample_rate_t _sample_rate ) + const sample_rate_t _sample_rate ) : + m_presetIndex(0) { try { diff --git a/plugins/stk/mallets/mallets.h b/plugins/stk/mallets/mallets.h index 3928c531c5c..f50d20c67bb 100644 --- a/plugins/stk/mallets/mallets.h +++ b/plugins/stk/mallets/mallets.h @@ -120,8 +120,19 @@ class malletsSynth } } + inline int presetIndex() + { + return m_presetIndex; + } + + inline void setPresetIndex(int presetIndex) + { + m_presetIndex = presetIndex; + } + protected: + int m_presetIndex; Instrmnt * m_voice; StkFloat * m_delay; @@ -187,7 +198,7 @@ class malletsInstrument : public Instrument } ; -class malletsInstrumentView: public InstrumentView +class malletsInstrumentView: public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/triple_oscillator/TripleOscillator.cpp b/plugins/triple_oscillator/TripleOscillator.cpp index a883f75fa32..8093d218c04 100644 --- a/plugins/triple_oscillator/TripleOscillator.cpp +++ b/plugins/triple_oscillator/TripleOscillator.cpp @@ -364,6 +364,7 @@ void TripleOscillator::playNote( NotePlayHandle * _n, osc_l->update( _working_buffer + offset, frames, 0 ); osc_r->update( _working_buffer + offset, frames, 1 ); + applyFadeIn(_working_buffer, _n); applyRelease( _working_buffer, _n ); instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); @@ -419,7 +420,7 @@ class TripleOscKnob : public Knob TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); QPalette pal; diff --git a/plugins/triple_oscillator/TripleOscillator.h b/plugins/triple_oscillator/TripleOscillator.h index fb2b48a410b..815fa350589 100644 --- a/plugins/triple_oscillator/TripleOscillator.h +++ b/plugins/triple_oscillator/TripleOscillator.h @@ -136,7 +136,7 @@ protected slots: -class TripleOscillatorView : public InstrumentView +class TripleOscillatorView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 1d54538b63e..0b309e94c8d 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -38,24 +38,26 @@ #include #include -#include "ConfigManager.h" +#include + #include "BufferManager.h" #include "ConfigManager.h" #include "Engine.h" +#include "FileDialog.h" +#include "GuiApplication.h" #include "gui_templates.h" #include "InstrumentPlayHandle.h" #include "InstrumentTrack.h" #include "LocaleHelper.h" #include "MainWindow.h" #include "Mixer.h" -#include "GuiApplication.h" +#include "PathUtil.h" #include "PixmapButton.h" #include "SampleBuffer.h" #include "Song.h" #include "StringPairDrag.h" #include "TextFloat.h" #include "ToolTip.h" -#include "FileDialog.h" #include "embed.h" @@ -82,11 +84,11 @@ Plugin::Descriptor Q_DECL_EXPORT vestige_plugin_descriptor = } -class vstSubWin : public QMdiSubWindow +class vstSubWin : public SubWindow { public: vstSubWin( QWidget * _parent ) : - QMdiSubWindow( _parent ) + SubWindow( _parent ) { setAttribute( Qt::WA_DeleteOnClose, false ); setWindowFlags( Qt::WindowCloseButtonHint ); @@ -198,9 +200,15 @@ void vestigeInstrument::loadSettings( const QDomElement & _this ) { m_plugin->loadSettings( _this ); - if ( _this.attribute( "guivisible" ).toInt() ) { + if (instrumentTrack() != NULL && instrumentTrack()->isPreviewMode()) + { + m_plugin->hideUI(); + } + else if (_this.attribute( "guivisible" ).toInt()) + { m_plugin->showUI(); - } else { + } else + { m_plugin->hideUI(); } @@ -263,7 +271,7 @@ void vestigeInstrument::reloadPlugin() void vestigeInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) { - _this.setAttribute( "plugin", m_pluginDLL ); + _this.setAttribute( "plugin", PathUtil::toShortestRelative(m_pluginDLL) ); m_pluginMutex.lock(); if( m_plugin != NULL ) { @@ -322,17 +330,22 @@ void vestigeInstrument::loadFile( const QString & _file ) { m_pluginMutex.lock(); const bool set_ch_name = ( m_plugin != NULL && - instrumentTrack()->name() == m_plugin->name() ) || - instrumentTrack()->name() == InstrumentTrack::tr( "Default preset" ) || - instrumentTrack()->name() == displayName(); + instrumentTrack()->name() == m_plugin->name() ) || + instrumentTrack()->name() == InstrumentTrack::tr( "Default preset" ) || + instrumentTrack()->name() == displayName(); m_pluginMutex.unlock(); + // if the same is loaded don't load again (for preview) + if (instrumentTrack() != NULL && instrumentTrack()->isPreviewMode() && + m_pluginDLL == PathUtil::toShortestRelative( _file )) + return; + if ( m_plugin != NULL ) { closePlugin(); } - m_pluginDLL = SampleBuffer::tryToMakeRelative( _file ); + m_pluginDLL = PathUtil::toShortestRelative( _file ); TextFloat * tf = NULL; if( gui ) { @@ -354,8 +367,11 @@ void vestigeInstrument::loadFile( const QString & _file ) return; } - m_plugin->createUI(nullptr); - m_plugin->showUI(); + if ( !(instrumentTrack() != NULL && instrumentTrack()->isPreviewMode())) + { + m_plugin->createUI(nullptr); + m_plugin->showUI(); + } if( set_ch_name ) { @@ -372,6 +388,15 @@ void vestigeInstrument::loadFile( const QString & _file ) +void vestigeInstrument::loadPluginPresetFile(const QString& file) +{ + QMutexLocker ml(&m_pluginMutex); + m_plugin->openPreset(file); +} + + + + void vestigeInstrument::play( sampleFrame * _buf ) { if (!m_pluginMutex.tryLock(Engine::getSong()->isExporting() ? -1 : 0)) {return;} @@ -468,7 +493,7 @@ PluginView * vestigeInstrument::instantiateView( QWidget * _parent ) VestigeInstrumentView::VestigeInstrumentView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ), + InstrumentViewFixedSize( _instrument, _parent ), lastPosInMenu (0) { if( s_artwork == NULL ) @@ -670,7 +695,7 @@ void VestigeInstrumentView::openPlugin() if( m_vi->m_pluginDLL != "" ) { - QString f = SampleBuffer::tryToMakeAbsolute( m_vi->m_pluginDLL ); + QString f = PathUtil::toAbsolute( m_vi->m_pluginDLL ); ofd.setDirectory( QFileInfo( f ).absolutePath() ); ofd.selectFile( QFileInfo( f ).fileName() ); } @@ -709,7 +734,7 @@ void VestigeInstrumentView::openPreset() { if ( m_vi->m_plugin != NULL ) { - m_vi->m_plugin->openPreset( ); + m_vi->m_plugin->guiOpenPreset(); bool converted; QString str = m_vi->m_plugin->currentProgramName().section("/", 0, 0); if (str != "") @@ -727,7 +752,7 @@ void VestigeInstrumentView::savePreset() if ( m_vi->m_plugin != NULL ) { - m_vi->m_plugin->savePreset( ); + m_vi->m_plugin->guiSavePreset(); /* bool converted; QString str = m_vi->m_plugin->presetString().section("/", 0, 0); if (str != "") @@ -900,7 +925,7 @@ void VestigeInstrumentView::paintEvent( QPaintEvent * ) manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrument, QWidget * _parent, vestigeInstrument * m_vi2 ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { m_vi = m_vi2; m_vi->m_scrollArea = new QScrollArea( this ); @@ -951,7 +976,7 @@ manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrume const QMap & dump = m_vi->m_plugin->parameterDump(); m_vi->paramCount = dump.size(); - vstKnobs = new Knob *[ m_vi->paramCount ]; + vstKnobs = new CustomTextKnob *[ m_vi->paramCount ]; bool hasKnobModel = true; if (m_vi->knobFModel == NULL) { @@ -967,8 +992,8 @@ manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrume sprintf( paramStr, "param%d", i); s_dumpValues = dump[ paramStr ].split( ":" ); - vstKnobs[ i ] = new Knob( knobBright_26, this, s_dumpValues.at( 1 ) ); - vstKnobs[ i ]->setHintText( s_dumpValues.at( 1 ) + ":", "" ); + vstKnobs[ i ] = new CustomTextKnob( knobBright_26, this, s_dumpValues.at( 1 ) ); + vstKnobs[ i ]->setDescription( s_dumpValues.at( 1 ) + ":" ); vstKnobs[ i ]->setLabel( s_dumpValues.at( 1 ).left( 15 ) ); if( !hasKnobModel ) @@ -983,6 +1008,7 @@ manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrume [this, model]() { setParameter( model ); }, Qt::DirectConnection); vstKnobs[i] ->setModel( model ); } + syncParameterText(); int i = 0; for( int lrow = 1; lrow < ( int( m_vi->paramCount / 10 ) + 1 ) + 1; lrow++ ) @@ -1043,6 +1069,7 @@ void manageVestigeInstrumentView::syncPlugin( void ) m_vi->knobFModel[ i ]->setInitValue( f_value ); } } + syncParameterText(); } @@ -1118,6 +1145,38 @@ void manageVestigeInstrumentView::setParameter( Model * action ) if ( m_vi->m_plugin != NULL ) { m_vi->m_plugin->setParam( knobUNID, m_vi->knobFModel[knobUNID]->value() ); + syncParameterText(); + } +} + +void manageVestigeInstrumentView::syncParameterText() +{ + m_vi->m_plugin->loadParameterLabels(); + m_vi->m_plugin->loadParameterDisplays(); + + QString paramLabelStr = m_vi->m_plugin->allParameterLabels(); + QString paramDisplayStr = m_vi->m_plugin->allParameterDisplays(); + + QStringList paramLabelList; + QStringList paramDisplayList; + + for( int i = 0; i < paramLabelStr.size(); ) + { + const int length = paramLabelStr[i].digitValue(); + paramLabelList.append(paramLabelStr.mid(i + 1, length)); + i += length + 1; + } + + for( int i = 0; i < paramDisplayStr.size(); ) + { + const int length = paramDisplayStr[i].digitValue(); + paramDisplayList.append(paramDisplayStr.mid(i + 1, length)); + i += length + 1; + } + + for( int i = 0; i < paramLabelList.size(); ++i ) + { + vstKnobs[i]->setValueText(paramDisplayList[i] + ' ' + paramLabelList[i]); } } @@ -1183,7 +1242,3 @@ Q_DECL_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) } - - - - diff --git a/plugins/vestige/vestige.h b/plugins/vestige/vestige.h index 3b92eea8ffc..9de40aeba51 100644 --- a/plugins/vestige/vestige.h +++ b/plugins/vestige/vestige.h @@ -29,14 +29,13 @@ #include #include -#include #include #include "Instrument.h" #include "InstrumentView.h" #include "Note.h" -#include "Knob.h" - +#include "CustomTextKnob.h" +#include "SubWindow.h" #include "AutomatableModel.h" @@ -62,6 +61,7 @@ class vestigeInstrument : public Instrument virtual QString nodeName( void ) const; virtual void loadFile( const QString & _file ); + virtual void loadPluginPresetFile(const QString& file); virtual Flags flags() const { @@ -98,7 +98,7 @@ protected slots: } ; -class manageVestigeInstrumentView : public InstrumentView +class manageVestigeInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: @@ -110,6 +110,7 @@ protected slots: void syncPlugin( void ); void displayAutomatedOnly( void ); void setParameter( Model * action ); + void syncParameterText(); void closeWindow(); @@ -129,12 +130,12 @@ protected slots: QPushButton * m_syncButton; QPushButton * m_displayAutomatedOnly; QPushButton * m_closeButton; - Knob ** vstKnobs; + CustomTextKnob ** vstKnobs; } ; -class VestigeInstrumentView : public InstrumentView +class VestigeInstrumentView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/vibed/vibed.cpp b/plugins/vibed/vibed.cpp index 94f640ff32f..c663660826e 100644 --- a/plugins/vibed/vibed.cpp +++ b/plugins/vibed/vibed.cpp @@ -349,7 +349,7 @@ PluginView * vibed::instantiateView( QWidget * _parent ) vibedView::vibedView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); QPalette pal; diff --git a/plugins/vibed/vibed.h b/plugins/vibed/vibed.h index 9e175c4cc40..b1c33f4b711 100644 --- a/plugins/vibed/vibed.h +++ b/plugins/vibed/vibed.h @@ -82,7 +82,7 @@ class vibed : public Instrument -class vibedView : public InstrumentView +class vibedView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index 44ed0dcb3be..873ed5f8e81 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -11,23 +11,35 @@ SET(REMOTE_VST_PLUGIN_FILEPATH_64 "RemoteVstPlugin64" CACHE STRING "Relative fil ADD_SUBDIRECTORY(vstbase) -SET(LMMS_BINARY_DIR ${CMAKE_BINARY_DIR}) -SET(LMMS_SOURCE_DIR ${CMAKE_SOURCE_DIR}) - SET(EXTERNALPROJECT_ARGS SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin" - INSTALL_COMMAND "" + #INSTALL_COMMAND "" BUILD_ALWAYS ON + # Skip the install step. + INSTALL_COMMAND "" ) +set(export_variables + "LMMS_SOURCE_DIR" + "LMMS_BINARY_DIR" + "CMAKE_MODULE_PATH" + "CMAKE_RUNTIME_OUTPUT_DIRECTORY" + "CMAKE_BUILD_TYPE" + "LMMS_BUILD_LINUX" + "LMMS_BUILD_WIN32" + "PLUGIN_DIR") + SET(EXTERNALPROJECT_CMAKE_ARGS - "-DLMMS_SOURCE_DIR=${CMAKE_SOURCE_DIR}" - "-DLMMS_BINARY_DIR=${CMAKE_BINARY_DIR}" - "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - "-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}" - "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" + "-DBUILD_WITH_EXTERNALPROJECT=ON" ) +macro(_export_var_to_external var_name) + list(APPEND EXTERNALPROJECT_CMAKE_ARGS "-D${var_name}=${${var_name}}") +endmacro() +foreach(var ${export_variables}) + _export_var_to_external(${var}) +endforeach() + # build 32 bit version of RemoteVstPlugin IF(WANT_VST_32) INCLUDE("${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin32.cmake") diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 48ab137438b..9246f4ee936 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -70,6 +70,8 @@ #include #include #include +#include +#include #include @@ -95,18 +97,6 @@ struct ERect #include "VstSyncData.h" -#ifdef LMMS_BUILD_WIN32 -#define USE_QT_SHMEM -#endif - -#ifndef USE_QT_SHMEM -#include -#include -#include -#include -#include -#endif - using namespace std; static VstHostLanguages hlang = LanguageEnglish; @@ -148,9 +138,9 @@ class RemoteVstPlugin : public RemotePluginClient { public: #ifdef SYNC_WITH_SHM_FIFO - RemoteVstPlugin( key_t _shm_in, key_t _shm_out ); + RemoteVstPlugin(key_t shmIn, key_t shmOut, key_t shmVstSync); #else - RemoteVstPlugin( const char * socketPath ); + RemoteVstPlugin(const char * socketPath, key_t shmVstSync); #endif virtual ~RemoteVstPlugin(); @@ -223,6 +213,10 @@ class RemoteVstPlugin : public RemotePluginClient // determine name of current program const char * programName(); + void getParameterDisplays(); + + void getParameterLabels(); + // send name of current program back to host void sendCurrentProgramName(); @@ -432,11 +426,11 @@ class RemoteVstPlugin : public RemotePluginClient #ifdef SYNC_WITH_SHM_FIFO -RemoteVstPlugin::RemoteVstPlugin( key_t _shm_in, key_t _shm_out ) : - RemotePluginClient( _shm_in, _shm_out ), +RemoteVstPlugin::RemoteVstPlugin(key_t shmIn, key_t shmOut, key_t shmVstSync) : + RemotePluginClient(shmIn, shmOut, shmVstSync), #else -RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) : - RemotePluginClient( socketPath ), +RemoteVstPlugin::RemoteVstPlugin(const char * socketPath, key_t shmVstSync) : + RemotePluginClient(socketPath, shmVstSync), #endif m_libInst( NULL ), m_plugin( NULL ), @@ -462,30 +456,7 @@ RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) : { __plugin = this; -#ifndef USE_QT_SHMEM - key_t key; - if( ( key = ftok( VST_SNC_SHM_KEY_FILE, 'R' ) ) == -1 ) - { - perror( "RemoteVstPlugin.cpp::ftok" ); - } - else - { // connect to shared memory segment - if( ( m_shmID = shmget( key, 0, 0 ) ) == -1 ) - { - perror( "RemoteVstPlugin.cpp::shmget" ); - } - else - { // attach segment - m_vstSyncData = (VstSyncData *)shmat(m_shmID, 0, 0); - if( m_vstSyncData == (VstSyncData *)( -1 ) ) - { - perror( "RemoteVstPlugin.cpp::shmat" ); - } - } - } -#else - m_vstSyncData = RemotePluginClient::getQtVSTshm(); -#endif + m_vstSyncData = RemotePluginClient::getVSTshm(); if( m_vstSyncData == NULL ) { fprintf(stderr, "RemoteVstPlugin.cpp: " @@ -527,21 +498,6 @@ RemoteVstPlugin::~RemoteVstPlugin() destroyEditor(); setResumed( false ); pluginDispatch( effClose ); -#ifndef USE_QT_SHMEM - // detach shared memory segment - if( shmdt( m_vstSyncData ) == -1) - { - if( __plugin->m_vstSyncData->hasSHM ) - { - perror( "~RemoteVstPlugin::shmdt" ); - } - if( m_vstSyncData != NULL ) - { - delete m_vstSyncData; - m_vstSyncData = NULL; - } - } -#endif if( m_libInst != NULL ) { @@ -660,6 +616,14 @@ bool RemoteVstPlugin::processMessage( const message & _m ) //sendMessage( IdVstSetParameter ); break; + case IdVstParameterDisplays: + getParameterDisplays(); + break; + + case IdVstParameterLabels: + getParameterLabels(); + break; + case IdVstIdleUpdate: { @@ -734,6 +698,7 @@ void RemoteVstPlugin::init( const std::string & _plugin_file ) static void close_check( FILE* fp ) { + if (!fp) {return;} if( fclose( fp ) ) { perror( "fclose" ); @@ -1067,6 +1032,49 @@ const char * RemoteVstPlugin::programName() +// join the ParameterDisplays (stringified values without units) and send them to host +void RemoteVstPlugin::getParameterDisplays() +{ + std::string paramDisplays; + static char buf[9]; // buffer for getting string + for (int i=0; i< m_plugin->numParams; ++i) + { + memset( buf, 0, sizeof( buf ) ); // fill with '\0' because got string may not to be ended with '\0' + pluginDispatch( effGetParamDisplay, i, 0, buf ); + buf[8] = 0; + + // each field shaped like: [length:number][content:string] + paramDisplays += '0' + strlen(buf); // add length descriptor (length is up to 8) + paramDisplays += buf; + } + + sendMessage( message( IdVstParameterDisplays ).addString( paramDisplays.c_str() ) ); +} + + + +// join the ParameterLabels (units) and send them to host +void RemoteVstPlugin::getParameterLabels() +{ + std::string paramLabels; + static char buf[9]; // buffer for getting string + for (int i=0; i< m_plugin->numParams; ++i) + { + memset( buf, 0, sizeof( buf ) ); // fill with '\0' because got string may not to be ended with '\0' + pluginDispatch( effGetParamLabel, i, 0, buf ); + buf[8] = 0; + + // each field shaped like: [length:number][content:string] + paramLabels += '0' + strlen(buf); // add length descriptor (length is up to 8) + paramLabels += buf; + } + + sendMessage( message( IdVstParameterLabels ).addString( paramLabels.c_str() ) ); +} + + + + void RemoteVstPlugin::sendCurrentProgramName() { char presName[64]; @@ -1084,7 +1092,7 @@ void RemoteVstPlugin::getParameterDump() for( int i = 0; i < m_plugin->numParams; ++i ) { - char paramName[32]; + char paramName[256]; memset( paramName, 0, sizeof( paramName ) ); pluginDispatch( effGetParamName, i, 0, paramName ); paramName[sizeof(paramName)-1] = 0; @@ -1128,6 +1136,12 @@ void RemoteVstPlugin::saveChunkToFile( const std::string & _file ) if( len > 0 ) { FILE* fp = F_OPEN_UTF8( _file, "wb" ); + if (!fp) + { + fprintf( stderr, + "Error opening file for saving chunk.\n" ); + return; + } if ( fwrite( chunk, 1, len, fp ) != len ) { fprintf( stderr, @@ -1292,7 +1306,13 @@ void RemoteVstPlugin::savePreset( const std::string & _file ) if (!isPreset &&!chunky) uIntToFile = (unsigned int) m_plugin->numPrograms; pBank->numPrograms = endian_swap( uIntToFile ); - FILE * stream = F_OPEN_UTF8( _file, "w" ); + FILE * stream = F_OPEN_UTF8( _file, "wb" ); + if (!stream) + { + fprintf( stderr, + "Error opening file for saving preset.\n" ); + return; + } fwrite ( pBank, 1, 28, stream ); fwrite ( progName, 1, isPreset ? 28 : 128, stream ); if ( chunky ) { @@ -1344,7 +1364,13 @@ void RemoteVstPlugin::loadPresetFile( const std::string & _file ) unsigned int * pLen = new unsigned int[ 1 ]; unsigned int len = 0; sBank * pBank = (sBank*) new char[ sizeof( sBank ) ]; - FILE * stream = F_OPEN_UTF8( _file, "r" ); + FILE * stream = F_OPEN_UTF8( _file, "rb" ); + if (!stream) + { + fprintf( stderr, + "Error opening file for loading preset.\n" ); + return; + } if ( fread ( pBank, 1, 56, stream ) != 56 ) { fprintf( stderr, "Error loading preset file.\n" ); @@ -1446,6 +1472,12 @@ void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len ) char * chunk = new char[_len]; FILE* fp = F_OPEN_UTF8( _file, "rb" ); + if (!fp) + { + fprintf( stderr, + "Error opening file for loading chunk.\n" ); + return; + } if ( fread( chunk, 1, _len, fp ) != _len ) { fprintf( stderr, "Error loading chunk from file.\n" ); @@ -2001,7 +2033,7 @@ bool RemoteVstPlugin::setupMessageWindow() } __MessageHwnd = CreateWindowEx( 0, "LVSL", "dummy", - 0, 0, 0, 0, 0, NULL, NULL, + 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInst, NULL ); // install GUI update timer SetTimer( __MessageHwnd, 1000, 50, NULL ); @@ -2079,9 +2111,9 @@ LRESULT CALLBACK RemoteVstPlugin::wndProc( HWND hwnd, UINT uMsg, int main( int _argc, char * * _argv ) { #ifdef SYNC_WITH_SHM_FIFO - if( _argc < 4 ) + if( _argc < 5 ) #else - if( _argc < 3 ) + if( _argc < 4 ) #endif { fprintf( stderr, "not enough arguments\n" ); @@ -2131,9 +2163,9 @@ int main( int _argc, char * * _argv ) { #ifdef SYNC_WITH_SHM_FIFO - int embedMethodIndex = 3; + int embedMethodIndex = 4; #else - int embedMethodIndex = 2; + int embedMethodIndex = 3; #endif std::string embedMethod = _argv[embedMethodIndex]; @@ -2172,9 +2204,9 @@ int main( int _argc, char * * _argv ) // constructor automatically will process messages until it receives // a IdVstLoadPlugin message and processes it #ifdef SYNC_WITH_SHM_FIFO - __plugin = new RemoteVstPlugin( atoi( _argv[1] ), atoi( _argv[2] ) ); + __plugin = new RemoteVstPlugin(atoi(_argv[1]), atoi(_argv[2]), atoi(_argv[3])); #else - __plugin = new RemoteVstPlugin( _argv[1] ); + __plugin = new RemoteVstPlugin(_argv[1], atoi(_argv[2])); #endif if( __plugin->isInitialized() ) diff --git a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt index 59dd19a0aa6..f4023fd426c 100644 --- a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt +++ b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt @@ -76,3 +76,18 @@ endif() IF(STRIP) ADD_CUSTOM_COMMAND(TARGET ${EXE_NAME} POST_BUILD COMMAND "${STRIP}" "$") ENDIF() + +if(BITNESS EQUAL 32) + INSTALL(TARGETS ${EXE_NAME} RUNTIME DESTINATION "${PLUGIN_DIR}/32") +else() + INSTALL(TARGETS ${EXE_NAME} RUNTIME DESTINATION "${PLUGIN_DIR}") +endif() + +if(BUILD_WITH_EXTERNALPROJECT) + include(InstallTargetDependencies) + INSTALL_TARGET_DEPENDENCIES(TARGETS ${EXE_NAME} + DESTINATION "${PLUGIN_DIR}/32") +else() + # Needed to deploy dependencies of RemoteVstPlugin + SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT "${EXE_NAME}") +endif() diff --git a/plugins/vst_base/RemoteVstPlugin32.cmake b/plugins/vst_base/RemoteVstPlugin32.cmake index 9a8f0452948..466752aa5da 100644 --- a/plugins/vst_base/RemoteVstPlugin32.cmake +++ b/plugins/vst_base/RemoteVstPlugin32.cmake @@ -1,33 +1,31 @@ +# INSTALL_EXTERNAL_PROJECT: install a project created with ExternalProject_Add in the +# parent project's install time. +# +# Description: +# In a regular scenario, cmake will install external projects +# BEFORE actually building the parent project. Since the building +# process may use installed components from the project. +# We want to give the external project the ability to install +# files directly to the parent's install. Therefore, we have to +# manually trigger the install stage with the parent's INSTALL_PREFIX. +MACRO(INSTALL_EXTERNAL_PROJECT name) + ExternalProject_Get_Property(${name} BINARY_DIR) + + install(CODE "include(\"${BINARY_DIR}/cmake_install.cmake\")") +ENDMACRO() + IF(LMMS_BUILD_WIN32 AND NOT LMMS_BUILD_WIN64) ADD_SUBDIRECTORY(RemoteVstPlugin) - IF(MSVC) - SET(VCPKG_ROOT "${CMAKE_FIND_ROOT_PATH}") - INSTALL(FILES "${VCPKG_ROOT}/bin/Qt5Core.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${VCPKG_ROOT}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32") - ELSE(MSVC) - INSTALL(FILES "${MINGW_PREFIX}/bin/Qt5Core.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${MINGW_PREFIX}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32") - ENDIF(MSVC) - INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32.exe" DESTINATION "${PLUGIN_DIR}/32") ELSEIF(LMMS_BUILD_WIN64 AND MSVC) - SET(MSVC_VER ${CMAKE_CXX_COMPILER_VERSION}) + IF(NOT QT_32_PREFIX) + SET(LMMS_MSVC_YEAR_FOR_QT ${LMMS_MSVC_YEAR}) - IF(NOT CMAKE_GENERATOR_32) - IF(MSVC_VER VERSION_GREATER 19.10 OR MSVC_VER VERSION_EQUAL 19.10) - SET(CMAKE_GENERATOR_32 "Visual Studio 15 2017") - SET(MSVC_YEAR 2017) - ELSEIF(MSVC_VER VERSION_GREATER 19.0 OR MSVC_VER VERSION_EQUAL 19.0) - SET(CMAKE_GENERATOR_32 "Visual Studio 14 2015") - SET(MSVC_YEAR 2015) - ELSE() - MESSAGE(SEND_WARNING "Can't build RemoteVstPlugin32, unknown MSVC version ${MSVC_VER} and no CMAKE_GENERATOR_32 set") - RETURN() - ENDIF() - ENDIF() + if(LMMS_MSVC_YEAR_FOR_QT EQUAL 2019 AND Qt5_VERSION VERSION_LESS "5.15") + SET(LMMS_MSVC_YEAR_FOR_QT 2017) # Qt only provides binaries for MSVC 2017, but 2019 is binary compatible + endif() - IF(NOT QT_32_PREFIX) GET_FILENAME_COMPONENT(QT_BIN_DIR ${QT_QMAKE_EXECUTABLE} DIRECTORY) - SET(QT_32_PREFIX "${QT_BIN_DIR}/../../msvc${MSVC_YEAR}") + SET(QT_32_PREFIX "${QT_BIN_DIR}/../../msvc${LMMS_MSVC_YEAR_FOR_QT}") ENDIF() #TODO: qt5 installed using vcpkg: I don't know how to detect if the user built the x86 version of qt5 from here. At least not cleanly. @@ -38,7 +36,8 @@ ELSEIF(LMMS_BUILD_WIN64 AND MSVC) ExternalProject_Add(RemoteVstPlugin32 "${EXTERNALPROJECT_ARGS}" - CMAKE_GENERATOR "${CMAKE_GENERATOR_32}" + CMAKE_GENERATOR "${LMMS_MSVC_GENERATOR}" + CMAKE_GENERATOR_PLATFORM Win32 #CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}" CMAKE_ARGS "${EXTERNALPROJECT_CMAKE_ARGS}" @@ -46,16 +45,7 @@ ELSEIF(LMMS_BUILD_WIN64 AND MSVC) "-DCMAKE_PREFIX_PATH=${QT_32_PREFIX}" ) - INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32.exe" DESTINATION "${PLUGIN_DIR}/32") - - #TODO: find a solution when not using vcpkg for qt - SET(VCPKG_ROOT_32 "${CMAKE_FIND_ROOT_PATH}/../x86-windows") - - INSTALL(FILES "${VCPKG_ROOT_32}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${VCPKG_ROOT_32}/bin/pcre2-16.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${VCPKG_ROOT_32}/bin/double-conversion.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${VCPKG_ROOT_32}/bin/qt5core.dll" DESTINATION "${PLUGIN_DIR}/32") - + INSTALL_EXTERNAL_PROJECT(RemoteVstPlugin32) ELSEIF(LMMS_BUILD_LINUX) # Use winegcc INCLUDE(CheckWineGcc) @@ -82,9 +72,7 @@ ELSEIF(CMAKE_TOOLCHAIN_FILE_32) "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_32}" "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE_32}" ) - INSTALL(FILES "${CMAKE_PREFIX_PATH_32}/bin/Qt5Core.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${CMAKE_PREFIX_PATH_32}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32.exe" DESTINATION "${PLUGIN_DIR}/32") + INSTALL_EXTERNAL_PROJECT(RemoteVstPlugin32) ELSE() MESSAGE(WARNING "Can't build RemoteVstPlugin32, unknown environment. Please supply CMAKE_TOOLCHAIN_FILE_32 and optionally CMAKE_PREFIX_PATH_32") RETURN() diff --git a/plugins/vst_base/RemoteVstPlugin64.cmake b/plugins/vst_base/RemoteVstPlugin64.cmake index 4b02bf8abf4..65b33a16251 100644 --- a/plugins/vst_base/RemoteVstPlugin64.cmake +++ b/plugins/vst_base/RemoteVstPlugin64.cmake @@ -1,6 +1,5 @@ IF(LMMS_BUILD_WIN64) ADD_SUBDIRECTORY(RemoteVstPlugin) - INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin64.exe" DESTINATION "${PLUGIN_DIR}") ELSEIF(LMMS_BUILD_LINUX) INCLUDE(CheckWineGcc) CheckWineGcc(64 "${WINEGCC}" WINEGCC_WORKING) diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index 8d86f576f33..5b05c87ec17 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -59,6 +59,7 @@ #include "LocaleHelper.h" #include "MainWindow.h" #include "Mixer.h" +#include "PathUtil.h" #include "Song.h" #include "FileDialog.h" @@ -121,7 +122,7 @@ class FileInfo VstPlugin::VstPlugin( const QString & _plugin ) : - m_plugin( _plugin ), + m_plugin( PathUtil::toAbsolute(_plugin) ), m_pluginWindowID( 0 ), m_embedMethod( gui ? ConfigManager::inst()->vstEmbedMethod() @@ -129,11 +130,6 @@ VstPlugin::VstPlugin( const QString & _plugin ) : m_version( 0 ), m_currentProgram() { - if( QDir::isRelativePath( m_plugin ) ) - { - m_plugin = ConfigManager::inst()->vstDir() + m_plugin; - } - setSplittedChannels( true ); PE::MachineType machineType; @@ -438,6 +434,14 @@ bool VstPlugin::processMessage( const message & _m ) m_allProgramNames = _m.getQString(); break; + case IdVstParameterLabels: + m_allParameterLabels = _m.getQString(); + break; + + case IdVstParameterDisplays: + m_allParameterDisplays = _m.getQString(); + break; + case IdVstPluginUniqueID: // TODO: display graphically in case of failure printf("unique ID: %s\n", _m.getString().c_str() ); @@ -475,7 +479,7 @@ QWidget *VstPlugin::editor() } -void VstPlugin::openPreset( ) +void VstPlugin::guiOpenPreset() { FileDialog ofd( NULL, tr( "Open Preset" ), "", @@ -485,17 +489,23 @@ void VstPlugin::openPreset( ) !ofd.selectedFiles().isEmpty() ) { lock(); - sendMessage( message( IdLoadPresetFile ). - addString( - QSTR_TO_STDSTR( - QDir::toNativeSeparators( ofd.selectedFiles()[0] ) ) ) - ); - waitForMessage( IdLoadPresetFile, true ); + openPreset(ofd.selectedFiles()[0]); unlock(); } } +void VstPlugin::openPreset(const QString& file) +{ + lock(); + sendMessage(message(IdLoadPresetFile). + addString( + QSTR_TO_STDSTR( + QDir::toNativeSeparators(file))) + ); + waitForMessage(IdLoadPresetFile, true); + unlock(); +} void VstPlugin::setProgram( int index ) @@ -531,7 +541,29 @@ void VstPlugin::loadProgramNames() -void VstPlugin::savePreset( ) +void VstPlugin::loadParameterLabels() +{ + lock(); + sendMessage( message( IdVstParameterLabels ) ); + waitForMessage( IdVstParameterLabels, true ); + unlock(); +} + + + + +void VstPlugin::loadParameterDisplays() +{ + lock(); + sendMessage( message( IdVstParameterDisplays ) ); + waitForMessage( IdVstParameterDisplays, true ); + unlock(); +} + + + + +void VstPlugin::guiSavePreset() { QString presName = currentProgramName().isEmpty() ? tr(": default") : currentProgramName(); presName.replace(tr("\""), tr("'")); // QFileDialog unable to handle double quotes properly @@ -555,20 +587,28 @@ void VstPlugin::savePreset( ) if ((fns.toUpper().indexOf(tr(".FXP")) == -1) && (fns.toUpper().indexOf(tr(".FXB")) == -1)) fns = fns + tr(".fxb"); else fns = fns.left(fns.length() - 4) + (fns.right( 4 )).toLower(); - lock(); - sendMessage( message( IdSavePresetFile ). - addString( - QSTR_TO_STDSTR( - QDir::toNativeSeparators( fns ) ) ) - ); - waitForMessage( IdSavePresetFile, true ); - unlock(); + savePreset(fns); } } +void VstPlugin::savePreset(const QString& file) +{ + lock(); + sendMessage(message(IdSavePresetFile). + addString( + QSTR_TO_STDSTR( + QDir::toNativeSeparators(file))) + ); + waitForMessage(IdSavePresetFile, true); + unlock(); +} + + + + void VstPlugin::setParam( int i, float f ) { lock(); @@ -774,7 +814,3 @@ QString VstPlugin::embedMethod() const { return m_embedMethod; } - - - - diff --git a/plugins/vst_base/VstPlugin.h b/plugins/vst_base/VstPlugin.h index 5b459d40dd8..6cf425bab1d 100644 --- a/plugins/vst_base/VstPlugin.h +++ b/plugins/vst_base/VstPlugin.h @@ -49,7 +49,7 @@ class VSTBASE_EXPORT VstPlugin : public RemotePlugin, public JournallingObject void tryLoad( const QString &remoteVstPluginExecutable ); - virtual bool processMessage( const message & _m ); + bool processMessage( const message & _m ) override; inline bool hasEditor() const { @@ -91,6 +91,16 @@ class VSTBASE_EXPORT VstPlugin : public RemotePlugin, public JournallingObject return m_allProgramNames; } + inline const QString& allParameterLabels() const + { + return m_allParameterLabels; + } + + inline const QString& allParameterDisplays() const + { + return m_allParameterDisplays; + } + int currentProgram(); const QMap & parameterDump(); @@ -99,28 +109,32 @@ class VSTBASE_EXPORT VstPlugin : public RemotePlugin, public JournallingObject QWidget * pluginWidget(); - virtual void loadSettings( const QDomElement & _this ); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); + void loadSettings( const QDomElement & _this ) override; + void saveSettings( QDomDocument & _doc, QDomElement & _this ) override; - inline virtual QString nodeName() const + virtual QString nodeName() const override { return "vstplugin"; } virtual void createUI(QWidget *parent); - bool eventFilter(QObject *obj, QEvent *event); + bool eventFilter(QObject *obj, QEvent *event) override; QString embedMethod() const; public slots: void setTempo( bpm_t _bpm ); void updateSampleRate(); - void openPreset( void ); + void guiOpenPreset(); + void openPreset(const QString& file); void setProgram( int index ); void rotateProgram( int offset ); void loadProgramNames(); - void savePreset( void ); + void loadParameterLabels(); + void loadParameterDisplays(); + void guiSavePreset(); + void savePreset(const QString& file); void setParam( int i, float f ); void idleUpdate(); @@ -148,6 +162,8 @@ public slots: QString m_productString; QString m_currentProgramName; QString m_allProgramNames; + QString m_allParameterLabels; + QString m_allParameterDisplays; QString p_name; diff --git a/plugins/vst_base/communication.h b/plugins/vst_base/communication.h index 756fd75573e..c25b213d18d 100644 --- a/plugins/vst_base/communication.h +++ b/plugins/vst_base/communication.h @@ -67,6 +67,8 @@ enum VstRemoteMessageIDs IdVstSetProgram, IdVstRotateProgram, IdVstIdleUpdate, + IdVstParameterDisplays, + IdVstParameterLabels, // remoteVstPlugin -> vstPlugin IdVstFailedLoadingPlugin, diff --git a/plugins/watsyn/Watsyn.cpp b/plugins/watsyn/Watsyn.cpp index 5c47b7a7aac..a5af401ccf7 100644 --- a/plugins/watsyn/Watsyn.cpp +++ b/plugins/watsyn/Watsyn.cpp @@ -666,7 +666,7 @@ void WatsynInstrument::updateWaveB2() WatsynView::WatsynView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); QPalette pal; diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index e52b7bb75e6..079e532e41a 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -293,7 +293,7 @@ public slots: }; -class WatsynView : public InstrumentView +class WatsynView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/plugins/waveshaper/waveshaper.cpp b/plugins/waveshaper/waveshaper.cpp index 3f9d3e19fba..a3bf2ddfb12 100644 --- a/plugins/waveshaper/waveshaper.cpp +++ b/plugins/waveshaper/waveshaper.cpp @@ -140,10 +140,10 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf, s[0] *= *outputPtr; s[1] *= *outputPtr; - out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1]; // mix wet/dry signals _buf[f][0] = d * _buf[f][0] + w * s[0]; _buf[f][1] = d * _buf[f][1] + w * s[1]; + out_sum += _buf[f][0] * _buf[f][0] + _buf[f][1] * _buf[f][1]; outputPtr += outputInc; inputPtr += inputInc; diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index f1d37fa3eb6..f9cc4efd37c 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -3,7 +3,7 @@ INCLUDE(BuildPlugin) set(CMAKE_POSITION_INDEPENDENT_CODE ON) # definitions for ZynAddSubFX -IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD) +IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE OR LMMS_BUILD_OPENBSD OR LMMS_BUILD_FREEBSD) FIND_PACKAGE(X11) INCLUDE_DIRECTORIES(${X11_INCLUDE_DIR}) ADD_DEFINITIONS(-DOS_LINUX) @@ -162,6 +162,8 @@ SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp "${WINRC}") INSTALL(TARGETS RemoteZynAddSubFx RUNTIME DESTINATION "${PLUGIN_DIR}") +# Needed to deploy dependencies of RemoteZynAddSubFx +SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT "RemoteZynAddSubFx") IF(LMMS_BUILD_WIN32) SET_TARGET_PROPERTIES(RemoteZynAddSubFx PROPERTIES LINK_FLAGS "${LINK_FLAGS} -mwindows") diff --git a/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp b/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp index 7cb6e635a8b..2772afd8098 100644 --- a/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp @@ -45,11 +45,11 @@ class RemoteZynAddSubFx : public RemotePluginClient, public LocalZynAddSubFx { public: #ifdef SYNC_WITH_SHM_FIFO - RemoteZynAddSubFx( int _shm_in, int _shm_out ) : - RemotePluginClient( _shm_in, _shm_out ), + RemoteZynAddSubFx(key_t shmIn, key_t shmOut, key_t shmVstSync) : + RemotePluginClient(shmIn, shmOut, shmVstSync), #else - RemoteZynAddSubFx( const char * socketPath ) : - RemotePluginClient( socketPath ), + RemoteZynAddSubFx(const char * socketPath, key_t shmVstSync) : + RemotePluginClient(socketPath, shmVstSync), #endif LocalZynAddSubFx(), m_guiSleepTime( 100 ), @@ -260,9 +260,9 @@ void RemoteZynAddSubFx::guiLoop() int main( int _argc, char * * _argv ) { #ifdef SYNC_WITH_SHM_FIFO - if( _argc < 3 ) + if( _argc < 4 ) #else - if( _argc < 2 ) + if( _argc < 3 ) #endif { fprintf( stderr, "not enough arguments\n" ); @@ -280,9 +280,9 @@ int main( int _argc, char * * _argv ) #ifdef SYNC_WITH_SHM_FIFO RemoteZynAddSubFx * remoteZASF = - new RemoteZynAddSubFx( atoi( _argv[1] ), atoi( _argv[2] ) ); + new RemoteZynAddSubFx(atoi(_argv[1]), atoi(_argv[2]), atoi(_argv[3])); #else - RemoteZynAddSubFx * remoteZASF = new RemoteZynAddSubFx( _argv[1] ); + RemoteZynAddSubFx * remoteZASF = new RemoteZynAddSubFx(_argv[1], atoi(_argv[2])); #endif remoteZASF->guiLoop(); diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index 277c22596a6..429948e7508 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -497,7 +497,7 @@ PluginView * ZynAddSubFxInstrument::instantiateView( QWidget * _parent ) ZynAddSubFxView::ZynAddSubFxView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) + InstrumentViewFixedSize( _instrument, _parent ) { setAutoFillBackground( true ); QPalette pal; diff --git a/plugins/zynaddsubfx/ZynAddSubFx.h b/plugins/zynaddsubfx/ZynAddSubFx.h index e8974d149ba..6f5bc754d1c 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.h +++ b/plugins/zynaddsubfx/ZynAddSubFx.h @@ -132,7 +132,7 @@ private slots: -class ZynAddSubFxView : public InstrumentView +class ZynAddSubFxView : public InstrumentViewFixedSize { Q_OBJECT public: diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index 473e7702f09..808298e79ff 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -1,8 +1,3 @@ -set(CMAKE_C_FLAGS "") -set(CMAKE_CXX_FLAGS "") -set(CMAKE_C_FLAGS_DEBUG "") -set(CMAKE_CXX_FLAGS_DEBUG "") - IF(LMMS_BUILD_LINUX AND WANT_VST) set(BUILD_SHARED_LIBS OFF) add_subdirectory(qt5-x11embed) @@ -10,3 +5,22 @@ ENDIF() ADD_SUBDIRECTORY(rpmalloc) ADD_SUBDIRECTORY(weakjack) + +# The lockless ring buffer library is compiled as part of the core +SET(RINGBUFFER_DIR "${CMAKE_SOURCE_DIR}/src/3rdparty/ringbuffer/") +SET(RINGBUFFER_DIR ${RINGBUFFER_DIR} PARENT_SCOPE) +# Create a dummy ringbuffer_export.h, since ringbuffer is not compiled as a library +FILE(WRITE ${CMAKE_BINARY_DIR}/src/ringbuffer_export.h + "#include \"${CMAKE_BINARY_DIR}/src/lmms_export.h\"\n + #define RINGBUFFER_EXPORT LMMS_EXPORT") +# Enable MLOCK support for ringbuffer if available +INCLUDE(CheckIncludeFiles) +CHECK_INCLUDE_FILES(sys/mman.h HAVE_SYS_MMAN) +IF(HAVE_SYS_MMAN) + SET(USE_MLOCK ON) +ELSE() + SET(USE_MLOCK OFF) +ENDIF() +# Generate ringbuffer configuration headers +CONFIGURE_FILE(${RINGBUFFER_DIR}/src/ringbuffer-config.h.in ${CMAKE_BINARY_DIR}/src/ringbuffer-config.h) +CONFIGURE_FILE(${RINGBUFFER_DIR}/src/ringbuffer-version.h.in ${CMAKE_BINARY_DIR}/src/ringbuffer-version.h) diff --git a/src/3rdparty/ringbuffer b/src/3rdparty/ringbuffer new file mode 160000 index 00000000000..82ed7cfb9ad --- /dev/null +++ b/src/3rdparty/ringbuffer @@ -0,0 +1 @@ +Subproject commit 82ed7cfb9ad40467421d8b14ca1af0350e92613c diff --git a/src/3rdparty/rpmalloc/CMakeLists.txt b/src/3rdparty/rpmalloc/CMakeLists.txt index 23d1551c22b..3b3afa6d329 100644 --- a/src/3rdparty/rpmalloc/CMakeLists.txt +++ b/src/3rdparty/rpmalloc/CMakeLists.txt @@ -1,5 +1,3 @@ -set(CMAKE_C_FLAGS "-std=c11") - add_library(rpmalloc STATIC rpmalloc/rpmalloc/rpmalloc.c rpmalloc/rpmalloc/rpmalloc.h @@ -9,6 +7,14 @@ target_include_directories(rpmalloc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/rpmalloc/rpmalloc ) +set_property(TARGET rpmalloc PROPERTY C_STANDARD 11) + +IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(rpmalloc + PRIVATE -Wno-unused-variable + ) +endif() + if (NOT LMMS_BUILD_WIN32) target_compile_definitions(rpmalloc PRIVATE -D_GNU_SOURCE diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ac6bf1332f..3ebec349e60 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,7 @@ INCLUDE_DIRECTORIES( "${CMAKE_BINARY_DIR}/include" "${CMAKE_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}/include" + "${RINGBUFFER_DIR}/include" ) IF(WIN32 AND MSVC) @@ -89,6 +90,19 @@ IF(NOT ("${LAME_INCLUDE_DIRS}" STREQUAL "")) INCLUDE_DIRECTORIES("${LAME_INCLUDE_DIRS}") ENDIF() +IF(NOT ("${LV2_INCLUDE_DIRS}" STREQUAL "")) + INCLUDE_DIRECTORIES(${LV2_INCLUDE_DIRS}) +ENDIF() + +IF(NOT ("${LILV_INCLUDE_DIRS}" STREQUAL "")) + INCLUDE_DIRECTORIES(${LILV_INCLUDE_DIRS}) +ENDIF() + +IF(NOT ("${SUIL_INCLUDE_DIRS}" STREQUAL "")) + INCLUDE_DIRECTORIES(${SUIL_INCLUDE_DIRS}) +ENDIF() +LIST(APPEND LMMS_SRCS "${RINGBUFFER_DIR}/src/lib/ringbuffer.cpp") + # Use libraries in non-standard directories (e.g., another version of Qt) IF(LMMS_BUILD_LINUX) LINK_LIBRARIES(-Wl,--enable-new-dtags) @@ -164,6 +178,9 @@ SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} ${JACK_LIBRARIES} ${OGGVORBIS_LIBRARIES} ${LAME_LIBRARIES} + ${LV2_LIBRARIES} + ${SUIL_LIBRARIES} + ${LILV_LIBRARIES} ${SAMPLERATE_LIBRARIES} ${SNDFILE_LIBRARIES} ${EXTRA_LIBRARIES} @@ -186,210 +203,30 @@ FOREACH(LIB ${LMMS_REQUIRED_LIBS}) ENDIF() ENDFOREACH() - -# Install -IF(NOT MSVC) - IF(LMMS_BUILD_WIN32) - SET_TARGET_PROPERTIES(lmms PROPERTIES - LINK_FLAGS "${LINK_FLAGS} -mwindows" - ENABLE_EXPORTS ON - ) - - IF(LMMS_BUILD_MSYS) - # ENABLE_EXPORTS property has no effect in some MSYS2 configurations. - # Add the linker flag manually to create liblmms.dll.a import library - SET_PROPERTY(TARGET lmms - APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--out-implib,liblmms.dll.a" - ) - ENDIF() - - IF(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") - ADD_CUSTOM_COMMAND(TARGET lmms POST_BUILD COMMAND "${STRIP}" "$") - ENDIF() - - INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") - INSTALL(FILES - "${MINGW_PREFIX}/bin/Qt5Core.dll" - "${MINGW_PREFIX}/bin/Qt5Gui.dll" - "${MINGW_PREFIX}/bin/Qt5Widgets.dll" - "${MINGW_PREFIX}/bin/Qt5Xml.dll" - DESTINATION .) - INSTALL(FILES - "${MINGW_PREFIX}/lib/qt5/plugins/platforms/qwindows.dll" - DESTINATION ./platforms) - INSTALL(FILES - "${MINGW_PREFIX}/bin/libsamplerate-0.dll" - "${MINGW_PREFIX}/bin/libsndfile-1.dll" - "${MINGW_PREFIX}/bin/libvorbis-0.dll" - "${MINGW_PREFIX}/bin/libvorbisenc-2.dll" - "${MINGW_PREFIX}/bin/libvorbisfile-3.dll" - "${MINGW_PREFIX}/bin/libjpeg-9.dll" - "${MINGW_PREFIX}/bin/libogg-0.dll" - "${MINGW_PREFIX}/bin/libmp3lame-0.dll" - "${MINGW_PREFIX}/bin/libfftw3f-3.dll" - "${MINGW_PREFIX}/bin/libFLAC-8.dll" - "${MINGW_PREFIX}/bin/libpng16-16.dll" - "${MINGW_PREFIX}/bin/SDL.dll" - "${MINGW_PREFIX}/bin/libglib-2.0-0.dll" - "${MINGW_PREFIX}/bin/libgthread-2.0-0.dll" - "${MINGW_PREFIX}/bin/zlib1.dll" - "${MINGW_PREFIX}/${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32/bin/libwinpthread-1.dll" - DESTINATION .) - IF(LMMS_BUILD_MSYS) - INSTALL(FILES - "${MINGW_PREFIX}/bin/libwinpthread-1.dll" - "${MINGW_PREFIX}/bin/libgcc_s_seh-1.dll" - "${MINGW_PREFIX}/bin/libstdc++-6.dll" - DESTINATION .) - ELSE() - INSTALL(FILES - "${MINGW_PREFIX}/${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32/bin/libwinpthread-1.dll" - DESTINATION .) - ENDIF() - IF(FLTK_FOUND) - INSTALL(FILES - "${MINGW_PREFIX}/bin/libfltk.dll" - DESTINATION .) - ENDIF() - IF(FLUIDSYNTH_FOUND) - INSTALL(FILES - "${MINGW_PREFIX}/bin/libfluidsynth.dll" - DESTINATION .) - ENDIF() - IF(GIG_FOUND) - # Handle libgig-*.dll - FILE(GLOB GIG_LIBRARY "${MINGW_PREFIX}/bin/libgig-*.dll") - INSTALL(FILES - ${GIG_LIBRARY} - DESTINATION .) - ENDIF() - IF(PORTAUDIO_FOUND) - INSTALL(FILES - "${MINGW_PREFIX}/bin/libportaudio-2.dll" - DESTINATION .) - ENDIF() - IF(SOUNDIO_FOUND) - INSTALL(FILES - "${MINGW_PREFIX}/lib/libsoundio.dll" - DESTINATION .) - ENDIF() - - ELSE(LMMS_BUILD_WIN32) - IF(NOT LMMS_BUILD_APPLE) - SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E") - ENDIF(NOT LMMS_BUILD_APPLE) - - INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") - INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1/" PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) - - ENDIF(LMMS_BUILD_WIN32) -ELSE(NOT MSVC) - SET_TARGET_PROPERTIES(lmms PROPERTIES - ENABLE_EXPORTS ON - ) - INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") - - SET_TARGET_PROPERTIES(lmms PROPERTIES - LINK_FLAGS "${LINK_FLAGS} -mwindows" - ENABLE_EXPORTS ON +IF(LMMS_BUILD_WIN32) + SET_TARGET_PROPERTIES(lmms PROPERTIES + ENABLE_EXPORTS ON + ) + IF(LMMS_BUILD_MSYS) + # ENABLE_EXPORTS property has no effect in some MSYS2 configurations. + # Add the linker flag manually to create liblmms.dll.a import library + SET_PROPERTY(TARGET lmms + APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--out-implib,liblmms.dll.a" ) + ENDIF() +ELSE() + IF(NOT LMMS_BUILD_APPLE) + SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E") + ENDIF(NOT LMMS_BUILD_APPLE) + + if(CMAKE_INSTALL_MANDIR) + SET(INSTALL_MANDIR ${CMAKE_INSTALL_MANDIR}) + ELSE(CMAKE_INSTALL_MANDIR) + SET(INSTALL_MANDIR ${CMAKE_INSTALL_PREFIX}/share/man) + ENDIF(CMAKE_INSTALL_MANDIR) + INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz" + DESTINATION "${INSTALL_MANDIR}/man1/" + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) +ENDIF() - #CMAKE_FIND_ROOT_PATH - SET(VCPKG_ROOT ${CMAKE_FIND_ROOT_PATH}) - - INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") - - INSTALL(FILES - "${VCPKG_ROOT}/bin/Qt5Core.dll" - "${VCPKG_ROOT}/bin/Qt5Gui.dll" - "${VCPKG_ROOT}/bin/Qt5Widgets.dll" - "${VCPKG_ROOT}/bin/Qt5Xml.dll" - - "${VCPKG_ROOT}/bin/zlib1.dll" - "${VCPKG_ROOT}/bin/jpeg62.dll" - "${VCPKG_ROOT}/bin/libpng16.dll" - "${VCPKG_ROOT}/bin/gthread-2.dll" - "${VCPKG_ROOT}/bin/glib-2.dll" - "${VCPKG_ROOT}/bin/harfbuzz.dll" - "${VCPKG_ROOT}/bin/pcre2-16.dll" - "${VCPKG_ROOT}/bin/double-conversion.dll" - "${VCPKG_ROOT}/bin/freetype.dll" - "${VCPKG_ROOT}/bin/libbz2.dll" - "${VCPKG_ROOT}/bin/pcre.dll" - "${VCPKG_ROOT}/bin/libiconv.dll" - "${VCPKG_ROOT}/bin/libcharset.dll" - "${VCPKG_ROOT}/bin/libintl.dll" - DESTINATION .) - - INSTALL(FILES - "${VCPKG_ROOT}/plugins/platforms/qwindows.dll" - DESTINATION ./platforms) - - INSTALL(FILES - "${VCPKG_ROOT}/bin/libsndfile-1.dll" - "${VCPKG_ROOT}/bin/ogg.dll" - "${VCPKG_ROOT}/bin/vorbis.dll" - "${VCPKG_ROOT}/bin/vorbisenc.dll" - "${VCPKG_ROOT}/bin/FLAC.dll" - "${VCPKG_ROOT}/bin/vorbisfile.dll" - - "${VCPKG_ROOT}/bin/libsamplerate-0.dll" - "${VCPKG_ROOT}/bin/SDL2.dll" - "${VCPKG_ROOT}/bin/fftw3f.dll" - DESTINATION .) - - #not yet in vcpkg - #IF(LAME_FOUND) - # INSTALL(FILES - # "${VCPKG_ROOT}/bin/libmp3lame-0.dll" - # DESTINATION .) - #ENDIF(LAME_FOUND) - - IF(FLTK_FOUND) - INSTALL(FILES - "${VCPKG_ROOT}/bin/libfltk_SHARED.dll" - - "${VCPKG_ROOT}/bin/zlib1.dll" - "${VCPKG_ROOT}/bin/jpeg62.dll" - DESTINATION .) - ENDIF() - - IF(FLUIDSYNTH_FOUND) - INSTALL(FILES - "${VCPKG_ROOT}/bin/libfluidsynth-1.dll" - "${VCPKG_ROOT}/bin/glib-2.dll" - "${VCPKG_ROOT}/bin/pcre.dll" - "${VCPKG_ROOT}/bin/libiconv.dll" - "${VCPKG_ROOT}/bin/libcharset.dll" - "${VCPKG_ROOT}/bin/libintl.dll" - DESTINATION .) - ENDIF() - - #not yet included in vcpkg - #IF(GIG_FOUND) - # # Handle libgig-*.dll - # FILE(GLOB GIG_LIBRARY "${VCPKG_ROOT}/bin/libgig-*.dll") - # INSTALL(FILES - # ${GIG_LIBRARY} - # DESTINATION .) - #ENDIF() - - IF(PORTAUDIO_FOUND) - IF(LMMS_BUILD_WIN64) - INSTALL(FILES - "${VCPKG_ROOT}/bin/portaudio-x64.dll" - DESTINATION .) - ELSE(LMMS_BUILD_WIN64) - INSTALL(FILES - "${VCPKG_ROOT}/bin/portaudio-x86.dll" - DESTINATION .) - ENDIF(LMMS_BUILD_WIN64) - ENDIF() - - #not yet in vcpkg - #IF(SOUNDIO_FOUND) - # INSTALL(FILES - # "${VCPKG_ROOT}/bin/libsoundio.dll" - # DESTINATION .) - #ENDIF() -ENDIF(NOT MSVC) +INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 6055598f704..8328e5cb9ea 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -499,8 +499,23 @@ void AutomatableModel::unlinkModel( AutomatableModel* model ) void AutomatableModel::linkModels( AutomatableModel* model1, AutomatableModel* model2 ) { + if (!model1->m_linkedModels.contains( model2 ) && model1 != model2) + { + // copy data + model1->m_value = model2->m_value; + if (model1->valueBuffer() && model2->valueBuffer()) + { + std::copy_n(model2->valueBuffer()->data(), + model1->valueBuffer()->length(), + model1->valueBuffer()->data()); + } + // send dataChanged() before linking (because linking will + // connect the two dataChanged() signals) + emit model1->dataChanged(); + // finally: link the models model1->linkModel( model2 ); model2->linkModel( model1 ); + } } diff --git a/src/core/AutomationPattern.cpp b/src/core/AutomationPattern.cpp index e36838d807a..2fd1cea125f 100644 --- a/src/core/AutomationPattern.cpp +++ b/src/core/AutomationPattern.cpp @@ -178,9 +178,16 @@ const AutomationPattern::objectVector& AutomationPattern::objects() const MidiTime AutomationPattern::timeMapLength() const { - if( m_timeMap.isEmpty() ) return 0; + MidiTime one_bar = MidiTime(1, 0); + if (m_timeMap.isEmpty()) { return one_bar; } + timeMap::const_iterator it = m_timeMap.end(); - return MidiTime( MidiTime( (it-1).key() ).nextFullTact(), 0 ); + tick_t last_tick = static_cast((it-1).key()); + // if last_tick is 0 (single item at tick 0) + // return length as a whole bar to prevent disappearing TCO + if (last_tick == 0) { return one_bar; } + + return MidiTime(last_tick); } @@ -188,7 +195,8 @@ MidiTime AutomationPattern::timeMapLength() const void AutomationPattern::updateLength() { - changeLength( timeMapLength() ); + // Do not resize down in case user manually extended up + changeLength(qMax(length(), timeMapLength())); } @@ -223,12 +231,7 @@ MidiTime AutomationPattern::putValue( const MidiTime & time, } generateTangents( it, 3 ); - // we need to maximize our length in case we're part of a hidden - // automation track as the user can't resize this pattern - if( getTrack() && getTrack()->type() == Track::HiddenAutomationTrack ) - { - updateLength(); - } + updateLength(); emit dataChanged(); @@ -251,10 +254,7 @@ void AutomationPattern::removeValue( const MidiTime & time ) } generateTangents(it, 3); - if( getTrack() && getTrack()->type() == Track::HiddenAutomationTrack ) - { - updateLength(); - } + updateLength(); emit dataChanged(); } diff --git a/src/core/BBTrackContainer.cpp b/src/core/BBTrackContainer.cpp index e349c7b021e..ac4b6cb1a2f 100644 --- a/src/core/BBTrackContainer.cpp +++ b/src/core/BBTrackContainer.cpp @@ -62,7 +62,7 @@ bool BBTrackContainer::play( MidiTime _start, fpp_t _frames, return false; } - _start = _start % ( lengthOfBB( _tco_num ) * MidiTime::ticksPerTact() ); + _start = _start % ( lengthOfBB( _tco_num ) * MidiTime::ticksPerBar() ); TrackList tl = tracks(); for( TrackList::iterator it = tl.begin(); it != tl.end(); ++it ) @@ -90,9 +90,9 @@ void BBTrackContainer::updateAfterTrackAdd() -tact_t BBTrackContainer::lengthOfBB( int _bb ) const +bar_t BBTrackContainer::lengthOfBB( int _bb ) const { - MidiTime max_length = MidiTime::ticksPerTact(); + MidiTime max_length = MidiTime::ticksPerBar(); const TrackList & tl = tracks(); for (Track* t : tl) @@ -104,7 +104,7 @@ tact_t BBTrackContainer::lengthOfBB( int _bb ) const } } - return max_length.nextFullTact(); + return max_length.nextFullBar(); } @@ -124,7 +124,7 @@ void BBTrackContainer::removeBB( int _bb ) for( TrackList::iterator it = tl.begin(); it != tl.end(); ++it ) { delete ( *it )->getTCO( _bb ); - ( *it )->removeTact( _bb * DefaultTicksPerTact ); + ( *it )->removeBar( _bb * DefaultTicksPerBar ); } if( _bb <= currentBB() ) { @@ -151,7 +151,7 @@ void BBTrackContainer::swapBB( int _bb1, int _bb2 ) void BBTrackContainer::updateBBTrack( TrackContentObject * _tco ) { BBTrack * t = BBTrack::findBBTrack( _tco->startPosition() / - DefaultTicksPerTact ); + DefaultTicksPerBar ); if( t != NULL ) { t->dataChanged(); @@ -247,16 +247,13 @@ AutomatedValueMap BBTrackContainer::automatedValuesAt(MidiTime time, int tcoNum) Q_ASSERT(tcoNum >= 0); Q_ASSERT(time.getTicks() >= 0); - auto length_tacts = lengthOfBB(tcoNum); - auto length_ticks = length_tacts * MidiTime::ticksPerTact(); - if (time > length_ticks) { + auto length_bars = lengthOfBB(tcoNum); + auto length_ticks = length_bars * MidiTime::ticksPerBar(); + if (time > length_ticks) + { time = length_ticks; } - return TrackContainer::automatedValuesAt(time + (MidiTime::ticksPerTact() * tcoNum), tcoNum); + return TrackContainer::automatedValuesAt(time + (MidiTime::ticksPerBar() * tcoNum), tcoNum); } - - - - diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ba41e089c7a..2820cc7c745 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,5 +1,6 @@ set(LMMS_SRCS ${LMMS_SRCS} + core/AutomatableModel.cpp core/AutomationPattern.cpp core/BandLimitedWave.cpp @@ -26,10 +27,12 @@ set(LMMS_SRCS core/InstrumentPlayHandle.cpp core/InstrumentSoundShaping.cpp core/JournallingObject.cpp + core/JsonDataFile.cpp core/Ladspa2LMMS.cpp core/LadspaControl.cpp core/LadspaManager.cpp core/LfoController.cpp + core/LinkedModelGroups.cpp core/LocklessAllocator.cpp core/MemoryHelper.cpp core/MemoryManager.cpp @@ -44,6 +47,7 @@ set(LMMS_SRCS core/Note.cpp core/NotePlayHandle.cpp core/Oscillator.cpp + core/PathUtil.cpp core/PeakController.cpp core/PerfLog.cpp core/Piano.cpp @@ -61,6 +65,7 @@ set(LMMS_SRCS core/SampleBuffer.cpp core/SamplePlayHandle.cpp core/SampleRecordHandle.cpp + core/ScriptPlugin.cpp core/SerializingObject.cpp core/Song.cpp core/TempoSyncKnobModel.cpp @@ -88,6 +93,15 @@ set(LMMS_SRCS core/audio/AudioSampleRecorder.cpp core/audio/AudioSdl.cpp + core/lv2/Lv2Basics.cpp + core/lv2/Lv2ControlBase.cpp + core/lv2/Lv2Features.cpp + core/lv2/Lv2Ports.cpp + core/lv2/Lv2Proc.cpp + core/lv2/Lv2Manager.cpp + core/lv2/Lv2SubPluginFeatures.cpp + core/lv2/Lv2UridMap.cpp + core/midi/MidiAlsaRaw.cpp core/midi/MidiAlsaSeq.cpp core/midi/MidiClient.cpp diff --git a/src/core/Clipboard.cpp b/src/core/Clipboard.cpp index 0c4b972865b..9b1191cdc0d 100644 --- a/src/core/Clipboard.cpp +++ b/src/core/Clipboard.cpp @@ -22,6 +22,9 @@ * */ +#include +#include + #include "Clipboard.h" #include "JournallingObject.h" @@ -35,6 +38,10 @@ void Clipboard::copy( JournallingObject * _obj ) QDomElement parent = doc.createElement( "Clipboard" ); _obj->saveState( doc, parent ); content[_obj->nodeName()] = parent.firstChild().toElement(); + + // Clear the QApplication clipboard, so we don't have any conflicts when LMMS has to + // decide between the QApplication clipboard and the internal clipboard data + QApplication::clipboard()->clear( QClipboard::Clipboard ); } diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index d8c783dd235..7429de75470 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -22,6 +22,7 @@ * */ + #include #include #include @@ -36,9 +37,10 @@ #include "lmmsversion.h" -static inline QString ensureTrailingSlash( const QString & s ) + +static inline QString ensureTrailingSlash(const QString & s ) { - if( ! s.isEmpty() && !s.endsWith('/') && !s.endsWith('\\') ) + if(! s.isEmpty() && !s.endsWith('/') && !s.endsWith('\\')) { return s + '/'; } @@ -49,60 +51,26 @@ static inline QString ensureTrailingSlash( const QString & s ) ConfigManager * ConfigManager::s_instanceOfMe = NULL; -ConfigManager::ConfigManager() : - m_lmmsRcFile( QDir::home().absolutePath() +"/.lmmsrc.xml" ), - m_workingDir( QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation ) + "/lmms/"), - m_dataDir( "data:/" ), - m_artworkDir( defaultArtworkDir() ), - m_vstDir( m_workingDir + "vst/" ), - m_gigDir( m_workingDir + GIG_PATH ), - m_sf2Dir( m_workingDir + SF2_PATH ), - m_version( defaultVersion() ) +ConfigManager::ConfigManager() : m_version(defaultVersion()) { - // Detect < 1.2.0 working directory as a courtesy - if ( QFileInfo( QDir::home().absolutePath() + "/lmms/projects/" ).exists() ) - m_workingDir = QDir::home().absolutePath() + "/lmms/"; - - if (! qgetenv("LMMS_DATA_DIR").isEmpty()) - QDir::addSearchPath("data", QString::fromLocal8Bit(qgetenv("LMMS_DATA_DIR"))); - - // If we're in development (lmms is not installed) let's get the source and - // binary directories by reading the CMake Cache - QDir appPath = qApp->applicationDirPath(); - // If in tests, get parent directory - if (appPath.dirName() == "tests") { - appPath.cdUp(); + if (QFileInfo::exists(qApp->applicationDirPath() + PORTABLE_MODE_FILE)) + { + initPortableWorkingDir(); } - QFile cmakeCache(appPath.absoluteFilePath("CMakeCache.txt")); - if (cmakeCache.exists()) { - cmakeCache.open(QFile::ReadOnly); - QTextStream stream(&cmakeCache); - - // Find the lines containing something like lmms_SOURCE_DIR:static= - // and lmms_BINARY_DIR:static= - int done = 0; - while(! stream.atEnd()) - { - QString line = stream.readLine(); - - if (line.startsWith("lmms_SOURCE_DIR:")) { - QString srcDir = line.section('=', -1).trimmed(); - QDir::addSearchPath("data", srcDir + "/data/"); - done++; - } - if (line.startsWith("lmms_BINARY_DIR:")) { - m_lmmsRcFile = line.section('=', -1).trimmed() + QDir::separator() + - ".lmmsrc.xml"; - done++; - } - if (done == 2) - { - break; - } - } - - cmakeCache.close(); + else + { + initInstalledWorkingDir(); } + m_dataDir = "data:/"; + m_vstDir = m_workingDir + "vst/"; + m_sf2Dir = m_workingDir + SF2_PATH; + m_gigDir = m_workingDir + GIG_PATH; + m_themeDir = defaultThemeDir(); + if (!qgetenv("LMMS_DATA_DIR").isEmpty()) + { + QDir::addSearchPath("data", QString::fromLocal8Bit(qgetenv("LMMS_DATA_DIR"))); + } + initDevelopmentWorkingDir(); #ifdef LMMS_BUILD_WIN32 QDir::addSearchPath("data", qApp->applicationDirPath() + "/data/"); @@ -110,7 +78,6 @@ ConfigManager::ConfigManager() : QDir::addSearchPath("data", qApp->applicationDirPath().section('/', 0, -2) + "/share/lmms/"); #endif - } @@ -125,19 +92,19 @@ ConfigManager::~ConfigManager() void ConfigManager::upgrade_1_1_90() { // Remove trailing " (bad latency!)" string which was once saved with PulseAudio - if( value( "mixer", "audiodev" ).startsWith( "PulseAudio (" ) ) + if(value("mixer", "audiodev").startsWith("PulseAudio (")) { setValue("mixer", "audiodev", "PulseAudio"); } // MidiAlsaRaw used to store the device info as "Device" instead of "device" - if ( value( "MidiAlsaRaw", "device" ).isNull() ) + if (value("MidiAlsaRaw", "device").isNull()) { // copy "device" = "Device" and then delete the old "Device" (further down) - QString oldDevice = value( "MidiAlsaRaw", "Device" ); + QString oldDevice = value("MidiAlsaRaw", "Device"); setValue("MidiAlsaRaw", "device", oldDevice); } - if ( !value( "MidiAlsaRaw", "device" ).isNull() ) + if (!value("MidiAlsaRaw", "device").isNull()) { // delete the old "Device" in the case that we just copied it to "device" // or if the user somehow set both the "Device" and "device" fields @@ -149,9 +116,9 @@ void ConfigManager::upgrade_1_1_90() void ConfigManager::upgrade_1_1_91() { // rename displaydbv to displaydbfs - if ( !value( "app", "displaydbv" ).isNull() ) { - setValue( "app", "displaydbfs", value( "app", "displaydbv" ) ); - deleteValue( "app", "displaydbv" ); + if (!value("app", "displaydbv").isNull()) { + setValue("app", "displaydbfs", value("app", "displaydbv")); + deleteValue("app", "displaydbv"); } } @@ -159,27 +126,27 @@ void ConfigManager::upgrade_1_1_91() void ConfigManager::upgrade() { // Skip the upgrade if versions match - if ( m_version == LMMS_VERSION ) + if (m_version == LMMS_VERSION) { return; } ProjectVersion createdWith = m_version; - if ( createdWith.setCompareType(ProjectVersion::Build) < "1.1.90" ) + if (createdWith.setCompareType(ProjectVersion::Build) < "1.1.90") { upgrade_1_1_90(); } - if ( createdWith.setCompareType(ProjectVersion::Build) < "1.1.91" ) + if (createdWith.setCompareType(ProjectVersion::Build) < "1.1.91") { upgrade_1_1_91(); } // Don't use old themes as they break the UI (i.e. 0.4 != 1.0, etc) - if ( createdWith.setCompareType(ProjectVersion::Minor) != LMMS_VERSION ) + if (createdWith.setCompareType(ProjectVersion::Minor) != LMMS_VERSION) { - m_artworkDir = defaultArtworkDir(); + m_themeDir = defaultThemeDir(); } // Bump the version, now that we are upgraded @@ -191,7 +158,7 @@ QString ConfigManager::defaultVersion() const return LMMS_VERSION; } -QStringList ConfigManager::availabeVstEmbedMethods() +QStringList ConfigManager::availableVstEmbedMethods() { QStringList methods; methods.append("none"); @@ -213,7 +180,7 @@ QStringList ConfigManager::availabeVstEmbedMethods() QString ConfigManager::vstEmbedMethod() const { - QStringList methods = availabeVstEmbedMethods(); + QStringList methods = availableVstEmbedMethods(); QString defaultMethod = *(methods.end() - 1); QString currentMethod = value( "ui", "vstembedmethod", defaultMethod ); return methods.contains(currentMethod) ? currentMethod : defaultMethod; @@ -221,107 +188,115 @@ QString ConfigManager::vstEmbedMethod() const bool ConfigManager::hasWorkingDir() const { - return QDir( m_workingDir ).exists(); + return QDir(m_workingDir).exists(); } -void ConfigManager::setWorkingDir( const QString & wd ) +void ConfigManager::setWorkingDir(const QString & workingDir) { - m_workingDir = ensureTrailingSlash( QDir::cleanPath( wd ) ); + m_workingDir = ensureTrailingSlash(QDir::cleanPath(workingDir)); } -void ConfigManager::setVSTDir( const QString & _vd ) +void ConfigManager::setVSTDir(const QString & vstDir) { - m_vstDir = ensureTrailingSlash( _vd ); + m_vstDir = ensureTrailingSlash(vstDir); } -void ConfigManager::setArtworkDir( const QString & _ad ) +void ConfigManager::setLADSPADir(const QString & ladspaDir) { - m_artworkDir = ensureTrailingSlash( _ad ); + m_ladspaDir = ladspaDir; } -void ConfigManager::setLADSPADir( const QString & _fd ) +void ConfigManager::setSTKDir(const QString & stkDir) { - m_ladDir = _fd; +#ifdef LMMS_HAVE_STK + m_stkDir = ensureTrailingSlash(stkDir); +#endif } -void ConfigManager::setSTKDir( const QString & _fd ) +void ConfigManager::setSF2Dir(const QString & sf2Dir) { -#ifdef LMMS_HAVE_STK - m_stkDir = ensureTrailingSlash( _fd ); -#endif + m_sf2Dir = sf2Dir; } -void ConfigManager::setDefaultSoundfont( const QString & _sf ) +void ConfigManager::setSF2File(const QString & sf2File) { #ifdef LMMS_HAVE_FLUIDSYNTH - m_defaultSoundfont = _sf; + m_sf2File = sf2File; #endif } -void ConfigManager::setBackgroundArtwork( const QString & _ba ) +void ConfigManager::setGIGDir(const QString & gigDir) { - m_backgroundArtwork = _ba; + m_gigDir = gigDir; } -void ConfigManager::setGIGDir(const QString &gd) + + + +void ConfigManager::setThemeDir(const QString & themeDir) { - m_gigDir = gd; + m_themeDir = ensureTrailingSlash(themeDir); } -void ConfigManager::setSF2Dir(const QString &sfd) + + + +void ConfigManager::setBackgroundPicFile(const QString & backgroundPicFile) { - m_sf2Dir = sfd; + m_backgroundPicFile = backgroundPicFile; } + + void ConfigManager::createWorkingDir() { - QDir().mkpath( m_workingDir ); - - QDir().mkpath( userProjectsDir() ); - QDir().mkpath( userTemplateDir() ); - QDir().mkpath( userSamplesDir() ); - QDir().mkpath( userPresetsDir() ); - QDir().mkpath( userGigDir() ); - QDir().mkpath( userSf2Dir() ); - QDir().mkpath( userVstDir() ); - QDir().mkpath( userLadspaDir() ); + QDir().mkpath(m_workingDir); + + QDir().mkpath(userProjectsDir()); + QDir().mkpath(userTemplateDir()); + QDir().mkpath(userSamplesDir()); + QDir().mkpath(userPresetsDir()); + QDir().mkpath(userGigDir()); + QDir().mkpath(userSf2Dir()); + QDir().mkpath(userVstDir()); + QDir().mkpath(userLadspaDir()); } -void ConfigManager::addRecentlyOpenedProject( const QString & file ) +void ConfigManager::addRecentlyOpenedProject(const QString & file) { - QFileInfo recentFile( file ); - if( recentFile.suffix().toLower() == "mmp" || + QFileInfo recentFile(file); + if(recentFile.suffix().toLower() == "mmp" || recentFile.suffix().toLower() == "mmpz" || - recentFile.suffix().toLower() == "mpt" ) + recentFile.suffix().toLower() == "mpt") { - m_recentlyOpenedProjects.removeAll( file ); - if( m_recentlyOpenedProjects.size() > 50 ) + m_recentlyOpenedProjects.removeAll(file); + if(m_recentlyOpenedProjects.size() > 50) { m_recentlyOpenedProjects.removeLast(); } - m_recentlyOpenedProjects.push_front( file ); + m_recentlyOpenedProjects.push_front(file); ConfigManager::inst()->saveConfigFile(); } } @@ -329,18 +304,18 @@ void ConfigManager::addRecentlyOpenedProject( const QString & file ) -const QString & ConfigManager::value( const QString & cls, - const QString & attribute ) const +const QString & ConfigManager::value(const QString & cls, + const QString & attribute) const { - if( m_settings.contains( cls ) ) + if(m_settings.contains(cls)) { - for( stringPairVector::const_iterator it = + for(stringPairVector::const_iterator it = m_settings[cls].begin(); - it != m_settings[cls].end(); ++it ) + it != m_settings[cls].end(); ++it) { - if( ( *it ).first == attribute ) + if((*it).first == attribute) { - return ( *it ).second ; + return (*it).second ; } } } @@ -350,49 +325,49 @@ const QString & ConfigManager::value( const QString & cls, -const QString & ConfigManager::value( const QString & cls, +const QString & ConfigManager::value(const QString & cls, const QString & attribute, - const QString & defaultVal ) const + const QString & defaultVal) const { - const QString & val = value( cls, attribute ); + const QString & val = value(cls, attribute); return val.isEmpty() ? defaultVal : val; } -void ConfigManager::setValue( const QString & cls, +void ConfigManager::setValue(const QString & cls, const QString & attribute, - const QString & value ) + const QString & value) { - if( m_settings.contains( cls ) ) + if(m_settings.contains(cls)) { - for( QPair& pair : m_settings[cls]) + for(QPair& pair : m_settings[cls]) { - if( pair.first == attribute ) + if(pair.first == attribute) { - if ( pair.second != value ) + if (pair.second != value) { pair.second = value; - emit valueChanged( cls, attribute, value ); + emit valueChanged(cls, attribute, value); } return; } } } // not in map yet, so we have to add it... - m_settings[cls].push_back( qMakePair( attribute, value ) ); + m_settings[cls].push_back(qMakePair(attribute, value)); } -void ConfigManager::deleteValue( const QString & cls, const QString & attribute) +void ConfigManager::deleteValue(const QString & cls, const QString & attribute) { - if( m_settings.contains( cls ) ) + if(m_settings.contains(cls)) { - for( stringPairVector::iterator it = m_settings[cls].begin(); - it != m_settings[cls].end(); ++it ) + for(stringPairVector::iterator it = m_settings[cls].begin(); + it != m_settings[cls].end(); ++it) { - if( ( *it ).first == attribute ) + if((*it).first == attribute) { m_settings[cls].erase(it); return; @@ -402,23 +377,23 @@ void ConfigManager::deleteValue( const QString & cls, const QString & attribute) } -void ConfigManager::loadConfigFile( const QString & configFile ) +void ConfigManager::loadConfigFile(const QString & configFile) { // read the XML file and create DOM tree // Allow configuration file override through --config commandline option - if ( !configFile.isEmpty() ) + if (!configFile.isEmpty()) { m_lmmsRcFile = configFile; } - QFile cfg_file( m_lmmsRcFile ); + QFile cfg_file(m_lmmsRcFile); QDomDocument dom_tree; - if( cfg_file.open( QIODevice::ReadOnly ) ) + if(cfg_file.open(QIODevice::ReadOnly)) { QString errorString; int errorLine, errorCol; - if( dom_tree.setContent( &cfg_file, false, &errorString, &errorLine, &errorCol ) ) + if(dom_tree.setContent(&cfg_file, false, &errorString, &errorLine, &errorCol)) { // get the head information from the DOM QDomElement root = dom_tree.documentElement(); @@ -426,41 +401,41 @@ void ConfigManager::loadConfigFile( const QString & configFile ) QDomNode node = root.firstChild(); // Cache the config version for upgrade() - if ( !root.attribute( "version" ).isNull() ) { - m_version = root.attribute( "version" ); + if (!root.attribute("version").isNull()) { + m_version = root.attribute("version"); } // create the settings-map out of the DOM - while( !node.isNull() ) + while(!node.isNull()) { - if( node.isElement() && - node.toElement().hasAttributes () ) + if(node.isElement() && + node.toElement().hasAttributes ()) { stringPairVector attr; QDomNamedNodeMap node_attr = node.toElement().attributes(); - for( int i = 0; i < node_attr.count(); - ++i ) + for(int i = 0; i < node_attr.count(); + ++i) { - QDomNode n = node_attr.item( i ); - if( n.isAttr() ) + QDomNode n = node_attr.item(i); + if(n.isAttr()) { - attr.push_back( qMakePair( n.toAttr().name(), - n.toAttr().value() ) ); + attr.push_back(qMakePair(n.toAttr().name(), + n.toAttr().value())); } } m_settings[node.nodeName()] = attr; } - else if( node.nodeName() == "recentfiles" ) + else if(node.nodeName() == "recentfiles") { m_recentlyOpenedProjects.clear(); QDomNode n = node.firstChild(); - while( !n.isNull() ) + while(!n.isNull()) { - if( n.isElement() && n.toElement().hasAttributes() ) + if(n.isElement() && n.toElement().hasAttributes()) { m_recentlyOpenedProjects << - n.toElement().attribute( "path" ); + n.toElement().attribute("path"); } n = n.nextSibling(); } @@ -468,45 +443,45 @@ void ConfigManager::loadConfigFile( const QString & configFile ) node = node.nextSibling(); } - if( value( "paths", "artwork" ) != "" ) + if(value("paths", "theme") != "") { - m_artworkDir = value( "paths", "artwork" ); + m_themeDir = value("paths", "theme"); #ifdef LMMS_BUILD_WIN32 // Detect a QDir/QFile hang on Windows // see issue #3417 on github - bool badPath = ( m_artworkDir == "/" || m_artworkDir == "\\" ); + bool badPath = (m_themeDir == "/" || m_themeDir == "\\"); #else bool badPath = false; #endif - if( badPath || !QDir( m_artworkDir ).exists() || - !QFile( m_artworkDir + "/style.css" ).exists() ) + if(badPath || !QDir(m_themeDir).exists() || + !QFile(m_themeDir + "/style.css").exists()) { - m_artworkDir = defaultArtworkDir(); + m_themeDir = defaultThemeDir(); } - m_artworkDir = ensureTrailingSlash(m_artworkDir); + m_themeDir = ensureTrailingSlash(m_themeDir); } - setWorkingDir( value( "paths", "workingdir" ) ); + setWorkingDir(value("paths", "workingdir")); - setGIGDir( value( "paths", "gigdir" ) == "" ? gigDir() : value( "paths", "gigdir" ) ); - setSF2Dir( value( "paths", "sf2dir" ) == "" ? sf2Dir() : value( "paths", "sf2dir" ) ); - setVSTDir( value( "paths", "vstdir" ) ); - setLADSPADir( value( "paths", "laddir" ) ); + setGIGDir(value("paths", "gigdir") == "" ? gigDir() : value("paths", "gigdir")); + setSF2Dir(value("paths", "sf2dir") == "" ? sf2Dir() : value("paths", "sf2dir")); + setVSTDir(value("paths", "vstdir")); + setLADSPADir(value("paths", "ladspadir")); #ifdef LMMS_HAVE_STK - setSTKDir( value( "paths", "stkdir" ) ); + setSTKDir(value("paths", "stkdir")); #endif #ifdef LMMS_HAVE_FLUIDSYNTH - setDefaultSoundfont( value( "paths", "defaultsf2" ) ); + setSF2File(value("paths", "defaultsf2")); #endif - setBackgroundArtwork( value( "paths", "backgroundartwork" ) ); + setBackgroundPicFile(value("paths", "backgroundtheme")); } - else if( gui ) + else if(gui) { - QMessageBox::warning( NULL, MainWindow::tr( "Configuration file" ), - MainWindow::tr( "Error while parsing configuration file at line %1:%2: %3" ). - arg( errorLine ). - arg( errorCol ). - arg( errorString ) ); + QMessageBox::warning(NULL, MainWindow::tr("Configuration file"), + MainWindow::tr("Error while parsing configuration file at line %1:%2: %3"). + arg(errorLine). + arg(errorCol). + arg(errorString)); } cfg_file.close(); } @@ -517,21 +492,21 @@ void ConfigManager::loadConfigFile( const QString & configFile ) !QDir( m_vstDir ).exists() ) { #ifdef LMMS_BUILD_WIN32 - QString programFiles = QString::fromLocal8Bit( getenv( "ProgramFiles" ) ); + QString programFiles = QString::fromLocal8Bit(getenv("ProgramFiles")); m_vstDir = programFiles + "/VstPlugins/"; #else m_vstDir = m_workingDir + "plugins/vst/"; #endif } - if( m_ladDir.isEmpty() ) + if(m_ladspaDir.isEmpty() ) { - m_ladDir = userLadspaDir(); + m_ladspaDir = userLadspaDir(); } #ifdef LMMS_HAVE_STK - if( m_stkDir.isEmpty() || m_stkDir == QDir::separator() || m_stkDir == "/" || - !QDir( m_stkDir ).exists() ) + if(m_stkDir.isEmpty() || m_stkDir == QDir::separator() || m_stkDir == "/" || + !QDir(m_stkDir).exists()) { #if defined(LMMS_BUILD_WIN32) m_stkDir = m_dataDir + "stk/rawwaves/"; @@ -557,11 +532,11 @@ void ConfigManager::loadConfigFile( const QString & configFile ) QStringList searchPaths; if(! qgetenv("LMMS_THEME_PATH").isNull()) searchPaths << qgetenv("LMMS_THEME_PATH"); - searchPaths << artworkDir() << defaultArtworkDir(); - QDir::setSearchPaths( "resources", searchPaths); + searchPaths << themeDir() << defaultThemeDir(); + QDir::setSearchPaths("resources", searchPaths); // Create any missing subdirectories in the working dir, but only if the working dir exists - if( hasWorkingDir() ) + if(hasWorkingDir()) { createWorkingDir(); } @@ -572,72 +547,130 @@ void ConfigManager::loadConfigFile( const QString & configFile ) void ConfigManager::saveConfigFile() { - setValue( "paths", "artwork", m_artworkDir ); - setValue( "paths", "workingdir", m_workingDir ); - setValue( "paths", "vstdir", m_vstDir ); - setValue( "paths", "gigdir", m_gigDir ); - setValue( "paths", "sf2dir", m_sf2Dir ); - setValue( "paths", "laddir", m_ladDir ); + setValue("paths", "theme", m_themeDir); + setValue("paths", "workingdir", m_workingDir); + setValue("paths", "vstdir", m_vstDir); + setValue("paths", "gigdir", m_gigDir); + setValue("paths", "sf2dir", m_sf2Dir); + setValue("paths", "ladspadir", m_ladspaDir); #ifdef LMMS_HAVE_STK - setValue( "paths", "stkdir", m_stkDir ); + setValue("paths", "stkdir", m_stkDir); #endif #ifdef LMMS_HAVE_FLUIDSYNTH - setValue( "paths", "defaultsf2", m_defaultSoundfont ); + setValue("paths", "defaultsf2", m_sf2File); #endif - setValue( "paths", "backgroundartwork", m_backgroundArtwork ); + setValue("paths", "backgroundtheme", m_backgroundPicFile); - QDomDocument doc( "lmms-config-file" ); + QDomDocument doc("lmms-config-file"); - QDomElement lmms_config = doc.createElement( "lmms" ); - lmms_config.setAttribute( "version", m_version ); - doc.appendChild( lmms_config ); + QDomElement lmms_config = doc.createElement("lmms"); + lmms_config.setAttribute("version", m_version); + doc.appendChild(lmms_config); - for( settingsMap::iterator it = m_settings.begin(); - it != m_settings.end(); ++it ) + for(settingsMap::iterator it = m_settings.begin(); + it != m_settings.end(); ++it) { - QDomElement n = doc.createElement( it.key() ); - for( stringPairVector::iterator it2 = ( *it ).begin(); - it2 != ( *it ).end(); ++it2 ) + if (it.key() == "tmp") { continue; } + QDomElement n = doc.createElement(it.key()); + for(stringPairVector::iterator it2 = (*it).begin(); + it2 != (*it).end(); ++it2) { - n.setAttribute( ( *it2 ).first, ( *it2 ).second ); + n.setAttribute((*it2).first, (*it2).second); } - lmms_config.appendChild( n ); + lmms_config.appendChild(n); } - QDomElement recent_files = doc.createElement( "recentfiles" ); + QDomElement recent_files = doc.createElement("recentfiles"); - for( QStringList::iterator it = m_recentlyOpenedProjects.begin(); - it != m_recentlyOpenedProjects.end(); ++it ) + for(QStringList::iterator it = m_recentlyOpenedProjects.begin(); + it != m_recentlyOpenedProjects.end(); ++it) { - QDomElement n = doc.createElement( "file" ); - n.setAttribute( "path", *it ); - recent_files.appendChild( n ); + QDomElement n = doc.createElement("file"); + n.setAttribute("path", *it); + recent_files.appendChild(n); } - lmms_config.appendChild( recent_files ); + lmms_config.appendChild(recent_files); - QString xml = "\n" + doc.toString( 2 ); + QString xml = "\n" + doc.toString(2); - QFile outfile( m_lmmsRcFile ); - if( !outfile.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) + QFile outfile(m_lmmsRcFile); + if(!outfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { QString title, message; - title = MainWindow::tr( "Could not open file" ); - message = MainWindow::tr( "Could not open file %1 " + title = MainWindow::tr("Could not open file"); + message = MainWindow::tr("Could not open file %1 " "for writing.\nPlease make " "sure you have write " "permission to the file and " "the directory containing the " "file and try again!" - ).arg( m_lmmsRcFile ); - if( gui ) + ).arg(m_lmmsRcFile); + if(gui) { - QMessageBox::critical( NULL, title, message, + QMessageBox::critical(NULL, title, message, QMessageBox::Ok, - QMessageBox::NoButton ); + QMessageBox::NoButton); } return; } - outfile.write( xml.toUtf8() ); + outfile.write(xml.toUtf8()); outfile.close(); } + +void ConfigManager::initPortableWorkingDir() +{ + QString applicationPath = qApp->applicationDirPath(); + m_workingDir = applicationPath + "/lmms-workspace/"; + m_lmmsRcFile = applicationPath + "/.lmmsrc.xml"; +} + +void ConfigManager::initInstalledWorkingDir() +{ + m_workingDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/lmms/"; + m_lmmsRcFile = QDir::home().absolutePath() +"/.lmmsrc.xml"; + // Detect < 1.2.0 working directory as a courtesy + if ( QFileInfo( QDir::home().absolutePath() + "/lmms/projects/" ).exists() ) + m_workingDir = QDir::home().absolutePath() + "/lmms/"; +} + +void ConfigManager::initDevelopmentWorkingDir() +{ + // If we're in development (lmms is not installed) let's get the source and + // binary directories by reading the CMake Cache + QDir appPath = qApp->applicationDirPath(); + // If in tests, get parent directory + if (appPath.dirName() == "tests") { + appPath.cdUp(); + } + QFile cmakeCache(appPath.absoluteFilePath("CMakeCache.txt")); + if (cmakeCache.exists()) { + cmakeCache.open(QFile::ReadOnly); + QTextStream stream(&cmakeCache); + + // Find the lines containing something like lmms_SOURCE_DIR:static= + // and lmms_BINARY_DIR:static= + int done = 0; + while(! stream.atEnd()) + { + QString line = stream.readLine(); + + if (line.startsWith("lmms_SOURCE_DIR:")) { + QString srcDir = line.section('=', -1).trimmed(); + QDir::addSearchPath("data", srcDir + "/data/"); + done++; + } + if (line.startsWith("lmms_BINARY_DIR:")) { + m_lmmsRcFile = line.section('=', -1).trimmed() + QDir::separator() + + ".lmmsrc.xml"; + done++; + } + if (done == 2) + { + break; + } + } + + cmakeCache.close(); + } +} diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 129c9738b3e..44cb920d844 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -166,6 +166,9 @@ bool DataFile::validate( QString extension ) ( extension == "xiz" && ! pluginFactory->pluginSupportingExtension(extension).isNull()) || extension == "sf2" || extension == "sf3" || extension == "pat" || extension == "mid" || extension == "dll" +#ifdef LMMS_HAVE_LV2 + || extension == "lv2" +#endif ) ) { return true; diff --git a/src/core/DrumSynth.cpp b/src/core/DrumSynth.cpp index c41de1fd4d0..859fe403f0c 100644 --- a/src/core/DrumSynth.cpp +++ b/src/core/DrumSynth.cpp @@ -325,6 +325,8 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sa timestretch = .01f * mem_time * GetPrivateProfileFloat(sec,"Stretch",100.0,dsfile); if(timestretch<0.2f) timestretch=0.2f; if(timestretch>10.f) timestretch=10.f; + // the unit of envelope lengths is a sample in 44100Hz sample rate, so correct it + timestretch *= Fs / 44100.f; DGain = 1.0f; //leave this here! DGain = (float)powf(10.0, 0.05 * GetPrivateProfileFloat(sec,"Level",0,dsfile)); diff --git a/src/core/EffectChain.cpp b/src/core/EffectChain.cpp index 21b85917b18..c8f5cb87b00 100644 --- a/src/core/EffectChain.cpp +++ b/src/core/EffectChain.cpp @@ -38,6 +38,7 @@ EffectChain::EffectChain( Model * _parent ) : SerializingObject(), m_enabledModel( false, NULL, tr( "Effects enabled" ) ) { + connect(&m_enabledModel, &BoolModel::dataChanged, this, &EffectChain::startRunning); } diff --git a/src/core/Engine.cpp b/src/core/Engine.cpp index d2b4a9cc2aa..81cd0acdb17 100644 --- a/src/core/Engine.cpp +++ b/src/core/Engine.cpp @@ -28,6 +28,7 @@ #include "ConfigManager.h" #include "FxMixer.h" #include "Ladspa2LMMS.h" +#include "Lv2Manager.h" #include "Mixer.h" #include "Plugin.h" #include "PresetPreviewPlayHandle.h" @@ -41,6 +42,9 @@ FxMixer * LmmsCore::s_fxMixer = NULL; BBTrackContainer * LmmsCore::s_bbTrackContainer = NULL; Song * LmmsCore::s_song = NULL; ProjectJournal * LmmsCore::s_projectJournal = NULL; +#ifdef LMMS_HAVE_LV2 +Lv2Manager * LmmsCore::s_lv2Manager = nullptr; +#endif Ladspa2LMMS * LmmsCore::s_ladspaManager = NULL; void* LmmsCore::s_dndPluginKey = nullptr; DummyTrackContainer * LmmsCore::s_dummyTC = NULL; @@ -63,6 +67,10 @@ void LmmsCore::init( bool renderOnly ) s_fxMixer = new FxMixer; s_bbTrackContainer = new BBTrackContainer; +#ifdef LMMS_HAVE_LV2 + s_lv2Manager = new Lv2Manager; + s_lv2Manager->initPlugins(); +#endif s_ladspaManager = new Ladspa2LMMS; s_projectJournal->setJournalling( true ); @@ -95,6 +103,9 @@ void LmmsCore::destroy() deleteHelper( &s_fxMixer ); deleteHelper( &s_mixer ); +#ifdef LMMS_HAVE_LV2 + deleteHelper( &s_lv2Manager ); +#endif deleteHelper( &s_ladspaManager ); //delete ConfigManager::inst(); @@ -105,10 +116,10 @@ void LmmsCore::destroy() delete ConfigManager::inst(); } -float LmmsCore::framesPerTick(sample_rate_t sample_rate) +float LmmsCore::framesPerTick(sample_rate_t sampleRate) { - return sample_rate * 60.0f * 4 / - DefaultTicksPerTact / s_song->getTempo(); + return sampleRate * 60.0f * 4 / + DefaultTicksPerBar / s_song->getTempo(); } @@ -117,7 +128,7 @@ float LmmsCore::framesPerTick(sample_rate_t sample_rate) void LmmsCore::updateFramesPerTick() { s_framesPerTick = s_mixer->processingSampleRate() * 60.0f * 4 / - DefaultTicksPerTact / s_song->getTempo(); + DefaultTicksPerBar / s_song->getTempo(); } diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 032090bf1d5..7ddcbea623a 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -34,6 +34,7 @@ #include "InstrumentTrack.h" #include "SampleTrack.h" #include "BBTrackContainer.h" +#include "TrackContainer.h" // For TrackContainer::TrackList typedef FxRoute::FxRoute( FxChannel * from, FxChannel * to, float amount ) : m_from( from ), @@ -72,6 +73,7 @@ FxChannel::FxChannel( int idx, Model * _parent ) : m_lock(), m_channelIndex( idx ), m_queued( false ), + m_hasColor( false ), m_dependenciesMet(0) { BufferManager::clear( m_buffer, Engine::mixer()->framesPerPeriod() ); @@ -336,6 +338,11 @@ void FxMixer::deleteChannel( int index ) deleteChannelSend( ch->m_receives.first() ); } + // if m_lastSoloed was our index, reset it + if (m_lastSoloed == index) { m_lastSoloed = -1; } + // if m_lastSoloed is > delete index, it will move left + else if (m_lastSoloed > index) { --m_lastSoloed; } + // actually delete the channel m_fxChannels.remove(index); delete ch; @@ -373,14 +380,18 @@ void FxMixer::moveChannelLeft( int index ) // channels to swap int a = index - 1, b = index; + // check if m_lastSoloed is one of our swaps + if (m_lastSoloed == a) { m_lastSoloed = b; } + else if (m_lastSoloed == b) { m_lastSoloed = a; } + // go through every instrument and adjust for the channel index change - QVector songTrackList = Engine::getSong()->tracks(); - QVector bbTrackList = Engine::getBBTrackContainer()->tracks(); + TrackContainer::TrackList songTrackList = Engine::getSong()->tracks(); + TrackContainer::TrackList bbTrackList = Engine::getBBTrackContainer()->tracks(); - QVector trackLists[] = {songTrackList, bbTrackList}; + TrackContainer::TrackList trackLists[] = {songTrackList, bbTrackList}; for(int tl=0; tl<2; ++tl) { - QVector trackList = trackLists[tl]; + TrackContainer::TrackList trackList = trackLists[tl]; for(int i=0; itype() == Track::InstrumentTrack ) @@ -731,6 +742,7 @@ void FxMixer::saveSettings( QDomDocument & _doc, QDomElement & _this ) ch->m_soloModel.saveSettings( _doc, fxch, "soloed" ); fxch.setAttribute( "num", i ); fxch.setAttribute( "name", ch->m_name ); + if( ch->m_hasColor ) fxch.setAttribute( "color", ch->m_color.name() ); // add the channel sends for( int si = 0; si < ch->m_sends.size(); ++si ) @@ -776,6 +788,11 @@ void FxMixer::loadSettings( const QDomElement & _this ) m_fxChannels[num]->m_muteModel.loadSettings( fxch, "muted" ); m_fxChannels[num]->m_soloModel.loadSettings( fxch, "soloed" ); m_fxChannels[num]->m_name = fxch.attribute( "name" ); + if( fxch.hasAttribute( "color" ) ) + { + m_fxChannels[num]->m_hasColor = true; + m_fxChannels[num]->m_color.setNamedColor( fxch.attribute( "color" ) ); + } m_fxChannels[num]->m_fxChain.restoreState( fxch.firstChildElement( m_fxChannels[num]->m_fxChain.nodeName() ) ); diff --git a/src/core/ImportFilter.cpp b/src/core/ImportFilter.cpp index e29e9f1d48b..efa8b88ae1a 100644 --- a/src/core/ImportFilter.cpp +++ b/src/core/ImportFilter.cpp @@ -24,11 +24,13 @@ #include +#include #include #include "ImportFilter.h" #include "Engine.h" #include "TrackContainer.h" +#include "GuiApplication.h" #include "PluginFactory.h" #include "ProjectJournal.h" @@ -52,8 +54,9 @@ ImportFilter::~ImportFilter() -void ImportFilter::import( const QString & _file_to_import, - TrackContainer* tc ) +void ImportFilter::import(const QString & _file_to_import, + TrackContainer* tc, + QJsonValue config) { bool successful = false; @@ -68,7 +71,7 @@ void ImportFilter::import( const QString & _file_to_import, { unique_ptr p(Plugin::instantiate( desc->name, NULL, s.data() )); if( dynamic_cast( p.get() ) != NULL && - dynamic_cast( p.get() )->tryImport( tc ) ) + dynamic_cast( p.get() )->tryImport(tc, config) ) { successful = true; break; @@ -79,16 +82,24 @@ void ImportFilter::import( const QString & _file_to_import, if( successful == false ) { - QMessageBox::information( NULL, - TrackContainer::tr( "Couldn't import file" ), - TrackContainer::tr( "Couldn't find a filter for " + QString errorMessage = TrackContainer::tr("Couldn't find a filter for " "importing file %1.\n" "You should convert this file " "into a format supported by " "LMMS using another software." - ).arg( _file_to_import ), - QMessageBox::Ok, - QMessageBox::NoButton ); + ).arg(_file_to_import); + if (gui) + { + QMessageBox::information( NULL, + TrackContainer::tr( "Couldn't import file" ), + errorMessage, + QMessageBox::Ok, + QMessageBox::NoButton ); + } + else + { + qWarning().noquote() << errorMessage; + } } } @@ -99,17 +110,24 @@ bool ImportFilter::openFile() { if( m_file.open( QFile::ReadOnly ) == false ) { - QMessageBox::critical( NULL, - TrackContainer::tr( "Couldn't open file" ), - TrackContainer::tr( "Couldn't open file %1 " + QString errorMessage = TrackContainer::tr("Couldn't open file %1 " "for reading.\nPlease make " "sure you have read-" "permission to the file and " "the directory containing the " - "file and try again!" ).arg( - m_file.fileName() ), - QMessageBox::Ok, - QMessageBox::NoButton ); + "file and try again!").arg(m_file.fileName()); + if (gui) + { + QMessageBox::critical( NULL, + TrackContainer::tr( "Couldn't open file" ), + errorMessage, + QMessageBox::Ok, + QMessageBox::NoButton ); + } + else + { + qWarning().noquote() << errorMessage; + } return false; } return true; diff --git a/src/core/Instrument.cpp b/src/core/Instrument.cpp index ba608da14a2..3e8dc80742e 100644 --- a/src/core/Instrument.cpp +++ b/src/core/Instrument.cpp @@ -23,8 +23,12 @@ */ #include "Instrument.h" -#include "InstrumentTrack.h" + +#include + #include "DummyInstrument.h" +#include "InstrumentTrack.h" +#include "lmms_constants.h" Instrument::Instrument(InstrumentTrack * _instrument_track, @@ -78,8 +82,96 @@ bool Instrument::isFromTrack( const Track * _track ) const return( m_instrumentTrack == _track ); } +// helper function for Instrument::applyFadeIn +static int countZeroCrossings(sampleFrame *buf, fpp_t start, fpp_t frames) +{ + // zero point crossing counts of all channels + int zeroCrossings[DEFAULT_CHANNELS] = {0}; + // maximum zero point crossing of all channels + int maxZeroCrossings = 0; + + // determine the zero point crossing counts + for (fpp_t f = start; f < frames; ++f) + { + for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch) + { + // we don't want to count [-1, 0, 1] as two crossings + if ((buf[f - 1][ch] <= 0.0 && buf[f][ch] > 0.0) || + (buf[f - 1][ch] >= 0.0 && buf[f][ch] < 0.0)) + { + ++zeroCrossings[ch]; + if (zeroCrossings[ch] > maxZeroCrossings) + { + maxZeroCrossings = zeroCrossings[ch]; + } + } + } + } + + return maxZeroCrossings; +} + +// helper function for Instrument::applyFadeIn +fpp_t getFadeInLength(float maxLength, fpp_t frames, int zeroCrossings) +{ + // calculate the length of the fade in + // Length is inversely proportional to the max of zeroCrossings, + // because for low frequencies, we need a longer fade in to + // prevent clicking. + return (fpp_t) (maxLength / ((float) zeroCrossings / ((float) frames / 128.0f) + 1.0f)); +} + +void Instrument::applyFadeIn(sampleFrame * buf, NotePlayHandle * n) +{ + const static float MAX_FADE_IN_LENGTH = 85.0; + f_cnt_t total = n->totalFramesPlayed(); + if (total == 0) + { + const fpp_t frames = n->framesLeftForCurrentPeriod(); + const f_cnt_t offset = n->offset(); + // We need to skip the first sample because it almost always + // produces a zero crossing; it's not helpful while + // determining the fade in length. Hence 1 + int maxZeroCrossings = countZeroCrossings(buf, offset + 1, offset + frames); + + fpp_t length = getFadeInLength(MAX_FADE_IN_LENGTH, frames, maxZeroCrossings); + n->m_fadeInLength = length; + + // apply fade in + length = length < frames ? length : frames; + for (fpp_t f = 0; f < length; ++f) + { + for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch) + { + buf[offset + f][ch] *= 0.5 - 0.5 * cosf(F_PI * (float) f / (float) n->m_fadeInLength); + } + } + } + else if (total < n->m_fadeInLength) + { + const fpp_t frames = n->framesLeftForCurrentPeriod(); + + int new_zc = countZeroCrossings(buf, 1, frames); + fpp_t new_length = getFadeInLength(MAX_FADE_IN_LENGTH, frames, new_zc); + + for (fpp_t f = 0; f < frames; ++f) + { + for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch) + { + float currentLength = n->m_fadeInLength * (1.0f - (float) f / frames) + new_length * ((float) f / frames); + buf[f][ch] *= 0.5 - 0.5 * cosf(F_PI * (float) (total + f) / currentLength); + if (total + f >= currentLength) + { + n->m_fadeInLength = currentLength; + return; + } + } + } + n->m_fadeInLength = new_length; + } +} void Instrument::applyRelease( sampleFrame * buf, const NotePlayHandle * _n ) { @@ -109,6 +201,3 @@ QString Instrument::fullDisplayName() const { return instrumentTrack()->displayName(); } - - - diff --git a/src/core/JsonDataFile.cpp b/src/core/JsonDataFile.cpp new file mode 100644 index 00000000000..ff61d11fb05 --- /dev/null +++ b/src/core/JsonDataFile.cpp @@ -0,0 +1,127 @@ +/* + * JsonDataFile.h - a convenient wrapper of QJsonDocument, + * used for managing JSON data files + * + * Copyright (c) 2019 Hyunjin Song + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#include "JsonDataFile.h" + +#include + +#include + + +JsonDataFile::JsonDataFile() : QJsonDocument() +{ +} + +JsonDataFile::JsonDataFile(const QString& fileName) : QJsonDocument() +{ + readFile(fileName); +} + +JsonDataFile::JsonDataFile(const JsonDataFile& other) : + QJsonDocument(static_cast(other)) +{ +} +JsonDataFile::JsonDataFile(JsonDataFile&& other) : + QJsonDocument(static_cast(other)) +{ +} +JsonDataFile::JsonDataFile(const QJsonDocument& other) : + QJsonDocument(other) +{ +} +JsonDataFile::JsonDataFile(QJsonDocument&& other) : + QJsonDocument(std::move(other)) +{ +} +JsonDataFile::JsonDataFile(const QJsonArray& array) : + QJsonDocument(array) +{ +} +JsonDataFile::JsonDataFile(const QJsonObject& object) : + QJsonDocument(object) +{ +} + + +JsonDataFile& JsonDataFile::operator=(const JsonDataFile& other) +{ + static_cast(*this) = static_cast(other); + return *this; +} + +JsonDataFile& JsonDataFile::operator=(JsonDataFile&& other) +{ + static_cast(*this) = static_cast(other); + return *this; +} + +JsonDataFile& JsonDataFile::operator=(const QJsonDocument& other) +{ + static_cast(*this) = other; + return *this; +} + +JsonDataFile& JsonDataFile::operator=(QJsonDocument&& other) +{ + static_cast(*this) = std::move(other); + return *this; +} + + +JsonDataFile JsonDataFile::fromFile(const QString& fileName) +{ + if (fileName.isEmpty()) {return JsonDataFile();} + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) {return JsonDataFile();} + return JsonDataFile(QJsonDocument::fromJson(file.readAll())); + file.close(); +} + +void JsonDataFile::readFile(const QString& fileName) +{ + if (fileName.isEmpty()) {return;} + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) {return;} + static_cast(*this) = QJsonDocument::fromJson(file.readAll()); +} + +void JsonDataFile::writeFile(const QString& fileName) +{ + if (fileName.isEmpty()) {return;} + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly)) {return;} + file.write(toJson()); +} + + +QJsonValue JsonDataFile::value() +{ + if (isArray()) return QJsonValue(array()); + else if (isObject()) return QJsonValue(object()); + else return QJsonValue(); +} + + diff --git a/src/core/LadspaControl.cpp b/src/core/LadspaControl.cpp index 731241b8541..68f2ee643b7 100644 --- a/src/core/LadspaControl.cpp +++ b/src/core/LadspaControl.cpp @@ -80,7 +80,7 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port, ( m_port->max - m_port->min ) / ( m_port->name.toUpper() == "GAIN" && m_port->max == 10.0f ? 4000.0f : - ( m_port->suggests_logscale ? 8000.0f : 800.0f ) ) ); + ( m_port->suggests_logscale ? 8000000.0f : 800000.0f ) ) ); m_knobModel.setInitValue( m_port->def ); connect( &m_knobModel, SIGNAL( dataChanged() ), this, SLOT( knobChanged() ) ); diff --git a/src/core/LinkedModelGroups.cpp b/src/core/LinkedModelGroups.cpp new file mode 100644 index 00000000000..c9bbc475a8f --- /dev/null +++ b/src/core/LinkedModelGroups.cpp @@ -0,0 +1,185 @@ +/* + * LinkedModelGroups.cpp - base classes for groups of linked models + * + * Copyright (c) 2019-2019 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "LinkedModelGroups.h" + +#include +#include + +#include "AutomatableModel.h" +#include "stdshims.h" + + + + +/* + LinkedModelGroup +*/ + + +void LinkedModelGroup::linkControls(LinkedModelGroup *other) +{ + foreach_model([&other](const std::string& id, ModelInfo& inf) + { + auto itr2 = other->m_models.find(id); + Q_ASSERT(itr2 != other->m_models.end()); + AutomatableModel::linkModels(inf.m_model, itr2->second.m_model); + }); +} + + + + +void LinkedModelGroup::saveValues(QDomDocument &doc, QDomElement &that) +{ + foreach_model([&doc, &that](const std::string& , ModelInfo& inf) + { + inf.m_model->saveSettings(doc, that, /*m_models[idx].m_name*/ inf.m_name); /* TODO: m_name useful */ + }); +} + + + + +void LinkedModelGroup::loadValues(const QDomElement &that) +{ + foreach_model([&that](const std::string& , ModelInfo& inf) + { + // try to load, if it fails, this will load a sane initial value + inf.m_model->loadSettings(that, /*m_models()[idx].m_name*/ inf.m_name); /* TODO: m_name useful */ + }); +} + + + + +void LinkedModelGroup::addModel(AutomatableModel *model, const QString &name) +{ + model->setObjectName(name); + m_models.emplace(std::string(name.toUtf8().data()), ModelInfo(name, model)); + connect(model, &AutomatableModel::destroyed, + this, [this, model](jo_id_t){ + if(containsModel(model->objectName())) + { + emit modelRemoved(model); + eraseModel(model->objectName()); + } + }, + Qt::DirectConnection); + + // View needs to create another child view, e.g. a new knob: + emit modelAdded(model); + emit dataChanged(); +} + + + + +void LinkedModelGroup::removeControl(AutomatableModel* mdl) +{ + if(containsModel(mdl->objectName())) + { + emit modelRemoved(mdl); + eraseModel(mdl->objectName()); + } +} + + + + +bool LinkedModelGroup::eraseModel(const QString& name) +{ + return m_models.erase(name.toStdString()) > 0; +} + + + + +void LinkedModelGroup::clearModels() +{ + m_models.clear(); +} + + + + +bool LinkedModelGroup::containsModel(const QString &name) const +{ + return m_models.find(name.toStdString()) != m_models.end(); +} + + + + +/* + LinkedModelGroups +*/ + + + +LinkedModelGroups::~LinkedModelGroups() {} + + + + +void LinkedModelGroups::linkAllModels() +{ + LinkedModelGroup* first = getGroup(0); + LinkedModelGroup* cur; + + for (std::size_t i = 1; (cur = getGroup(i)); ++i) + { + first->linkControls(cur); + } +} + + + + +void LinkedModelGroups::saveSettings(QDomDocument& doc, QDomElement& that) +{ + LinkedModelGroup* grp0 = getGroup(0); + if (grp0) + { + QDomElement models = doc.createElement("models"); + that.appendChild(models); + grp0->saveValues(doc, models); + } + else { /* don't even add a "models" node */ } +} + + + + +void LinkedModelGroups::loadSettings(const QDomElement& that) +{ + QDomElement models = that.firstChildElement("models"); + LinkedModelGroup* grp0; + if (!models.isNull() && (grp0 = getGroup(0))) + { + // only load the first group, the others are linked to the first + grp0->loadValues(models); + } +} + diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 7e41f2097d9..29bc725b6b6 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -357,16 +357,16 @@ const surroundSampleFrame * Mixer::renderNextBuffer() currentPlayMode == Song::Mode_PlayBB; if( playModeSupportsMetronome && m_metronomeActive && !song->isExporting() && - p != last_metro_pos && + !song->isPaused() && p != last_metro_pos && // Stop crash with metronome if empty project Engine::getSong()->countTracks() ) { - tick_t ticksPerTact = MidiTime::ticksPerTact(); - if ( p.getTicks() % (ticksPerTact / 1 ) == 0 ) + tick_t ticksPerBar = MidiTime::ticksPerBar(); + if ( p.getTicks() % ( ticksPerBar / 1 ) == 0 ) { addPlayHandle( new SamplePlayHandle( "misc/metronome02.ogg" ) ); } - else if ( p.getTicks() % (ticksPerTact / + else if ( p.getTicks() % ( ticksPerBar / song->getTimeSigModel().getNumerator() ) == 0 ) { addPlayHandle( new SamplePlayHandle( "misc/metronome01.ogg" ) ); @@ -831,7 +831,9 @@ void Mixer::runChangesInModel() if( m_changesSignal ) { m_waitChangesMutex.lock(); + // allow changes in the model from other threads ... m_changesRequestCondition.wakeOne(); + // ... and wait until they are done m_changesMixerCondition.wait( &m_waitChangesMutex ); m_waitChangesMutex.unlock(); } @@ -1205,8 +1207,18 @@ MidiClient * Mixer::tryMidiClients() printf( "midi apple didn't work: client_name=%s\n", client_name.toUtf8().constData()); #endif - printf( "Couldn't create MIDI-client, neither with ALSA nor with " - "OSS. Will use dummy-MIDI-client.\n" ); + if(client_name != MidiDummy::name()) + { + if (client_name.isEmpty()) + { + printf("Unknown MIDI-client. "); + } + else + { + printf("Couldn't create %s MIDI-client. ", client_name.toUtf8().constData()); + } + printf("Will use dummy-MIDI-client.\n"); + } m_midiClientName = MidiDummy::name(); @@ -1245,7 +1257,7 @@ void Mixer::fifoWriter::run() disable_denormals(); #if 0 -#ifdef LMMS_BUILD_LINUX +#if defined(LMMS_BUILD_LINUX) || defined(LMMS_BUILD_FREEBSD) #ifdef LMMS_HAVE_SCHED_H cpu_set_t mask; CPU_ZERO( &mask ); @@ -1286,5 +1298,3 @@ void Mixer::fifoWriter::write( surroundSampleFrame * buffer ) m_mixer->m_doChangesMutex.unlock(); } - - diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 0039f935a5d..5ea0038feee 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -180,6 +180,15 @@ int NotePlayHandle::midiKey() const +bool NotePlayHandle::shouldDelayRelease() const +{ + return instrumentTrack()->isSustainPedalPressed() + && !(instrumentTrack()->instrument()->flags() & Instrument::IsMidiBased); +} + + + + void NotePlayHandle::play( sampleFrame * _working_buffer ) { if( m_muted ) @@ -196,7 +205,12 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) lock(); - if( m_totalFramesPlayed == 0 && !m_hasMidiNote + /* It is possible for NotePlayHandle::noteOff to be called before NotePlayHandle::play, + * which results in a note-on message being sent without a subsequent note-off message. + * Therefore, we check here whether the note has already been released before sending + * the note-on message. */ + if( !m_released + && m_totalFramesPlayed == 0 && !m_hasMidiNote && ( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() ) ) { m_hasMidiNote = true; @@ -222,12 +236,12 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) // check if we start release during this period if( m_released == false && - instrumentTrack()->isSustainPedalPressed() == false && + !shouldDelayRelease() && m_totalFramesPlayed + framesThisPeriod > m_frames ) { noteOff( m_totalFramesPlayed == 0 ? ( m_frames + offset() ) // if we have noteon and noteoff during the same period, take offset in account for release frame - : ( m_frames - m_totalFramesPlayed ) ); // otherwise, the offset is already negated and can be ignored + : std::max(0, m_frames - m_totalFramesPlayed) ); // otherwise, the offset is already negated and can be ignored } // under some circumstances we're called even if there's nothing to play @@ -239,7 +253,7 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) m_instrumentTrack->playNote( this, _working_buffer ); } - if( m_released && (!instrumentTrack()->isSustainPedalPressed() || + if( m_released && (!shouldDelayRelease() || m_releaseStarted) ) { m_releaseStarted = true; @@ -304,7 +318,7 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) f_cnt_t NotePlayHandle::framesLeft() const { - if( instrumentTrack()->isSustainPedalPressed() ) + if( shouldDelayRelease() ) { return 4*Engine::mixer()->framesPerPeriod(); } @@ -374,7 +388,7 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) } // inform attached components about MIDI finished (used for recording in Piano Roll) - if (!instrumentTrack()->isSustainPedalPressed()) + if (!shouldDelayRelease()) { if( m_origin == OriginMidiInput ) { @@ -532,6 +546,15 @@ void NotePlayHandle::processMidiTime( const MidiTime& time ) void NotePlayHandle::resize( const bpm_t _new_tempo ) { + if (origin() == OriginMidiInput || + (origin() == OriginNoteStacking && m_parent->origin() == OriginMidiInput)) + { + // Don't resize notes from MIDI input - they should continue to play + // until the key is released, and their large duration can cause + // overflows in this method. + return; + } + double completed = m_totalFramesPlayed / (double) m_frames; double new_frames = m_origFrames * m_origTempo / (double) _new_tempo; m_frames = (f_cnt_t)new_frames; diff --git a/src/core/PathUtil.cpp b/src/core/PathUtil.cpp new file mode 100644 index 00000000000..61fe341b543 --- /dev/null +++ b/src/core/PathUtil.cpp @@ -0,0 +1,148 @@ +#include "PathUtil.h" + +#include +#include +#include + +#include "ConfigManager.h" + +namespace PathUtil +{ + Base relativeBases[] = { Base::ProjectDir, Base::FactorySample, Base::UserSample, Base::UserVST, Base::Preset, + Base::UserLADSPA, Base::DefaultLADSPA, Base::UserSoundfont, Base::DefaultSoundfont, Base::UserGIG, Base::DefaultGIG }; + + QString baseLocation(const Base base) + { + QString loc = ""; + switch (base) + { + case Base::ProjectDir : loc = ConfigManager::inst()->userProjectsDir(); break; + case Base::FactorySample : + { + QDir fsd = QDir(ConfigManager::inst()->factorySamplesDir()); + loc = fsd.absolutePath(); break; + } + case Base::UserSample : loc = ConfigManager::inst()->userSamplesDir(); break; + case Base::UserVST : loc = ConfigManager::inst()->userVstDir(); break; + case Base::Preset : loc = ConfigManager::inst()->userPresetsDir(); break; + case Base::UserLADSPA : loc = ConfigManager::inst()->ladspaDir(); break; + case Base::DefaultLADSPA : loc = ConfigManager::inst()->userLadspaDir(); break; + case Base::UserSoundfont : loc = ConfigManager::inst()->sf2Dir(); break; + case Base::DefaultSoundfont : loc = ConfigManager::inst()->userSf2Dir(); break; + case Base::UserGIG : loc = ConfigManager::inst()->gigDir(); break; + case Base::DefaultGIG : loc = ConfigManager::inst()->userGigDir(); break; + default : return QString(""); + } + return QDir::cleanPath(loc) + "/"; + } + + QDir baseQDir (const Base base) { return QDir(baseLocation(base)); } + + QString basePrefix(const Base base) + { + switch (base) + { + case Base::ProjectDir : return QStringLiteral("userprojects:"); + case Base::FactorySample : return QStringLiteral("factorysample:"); + case Base::UserSample : return QStringLiteral("usersample:"); + case Base::UserVST : return QStringLiteral("uservst:"); + case Base::Preset : return QStringLiteral("preset:"); + case Base::UserLADSPA : return QStringLiteral("userladspa:"); + case Base::DefaultLADSPA : return QStringLiteral("defaultladspa:"); + case Base::UserSoundfont : return QStringLiteral("usersoundfont:"); + case Base::DefaultSoundfont : return QStringLiteral("defaultsoundfont:"); + case Base::UserGIG : return QStringLiteral("usergig:"); + case Base::DefaultGIG : return QStringLiteral("defaultgig:"); + default : return QStringLiteral(""); + } + } + + Base baseLookup(const QString & path) + { + for (auto base: relativeBases) + { + QString prefix = basePrefix(base); + if ( path.startsWith(prefix) ) { return base; } + } + return Base::Absolute; + } + + + + + QString stripPrefix(const QString & path) + { + return path.mid( basePrefix(baseLookup(path)).length() ); + } + + QString cleanName(const QString & path) + { + return stripPrefix(QFileInfo(path).baseName()); + } + + + + + QString oldRelativeUpgrade(const QString & input) + { + if (input.isEmpty()) { return input; } + + //Start by assuming that the file is a user sample + Base assumedBase = Base::UserSample; + + //Check if it's a factory sample + QString factoryPath = baseLocation(Base::FactorySample) + input; + QFileInfo factoryInfo(factoryPath); + if (factoryInfo.exists()) { assumedBase = Base::FactorySample; } + + //Check if it's a VST + QString vstPath = baseLocation(Base::UserVST) + input; + QFileInfo vstInfo(vstPath); + if (vstInfo.exists()) { assumedBase = Base::UserVST; } + + //Assume we've found the correct base location, return the full path + return basePrefix(assumedBase) + input; + } + + + + + QString toAbsolute(const QString & input) + { + //First, do no harm to absolute paths + QFileInfo inputFileInfo = QFileInfo(input); + if (inputFileInfo.isAbsolute()) { return input; } + //Next, handle old relative paths with no prefix + QString upgraded = input.contains(":") ? input : oldRelativeUpgrade(input); + + Base base = baseLookup(upgraded); + return baseLocation(base) + upgraded.remove(0, basePrefix(base).length()); + } + + QString relativeOrAbsolute(const QString & input, const Base base) + { + if (input.isEmpty() || base == Base::Absolute) { return input; } + QString absolutePath = toAbsolute(input); + QString relativePath = baseQDir(base).relativeFilePath(absolutePath); + return relativePath.startsWith("..") ? absolutePath : relativePath; + } + + QString toShortestRelative(const QString & input) + { + QFileInfo inputFileInfo = QFileInfo(input); + QString absolutePath = inputFileInfo.isAbsolute() ? input : toAbsolute(input); + + Base shortestBase = Base::Absolute; + QString shortestPath = relativeOrAbsolute(absolutePath, shortestBase); + for (auto base: relativeBases) + { + QString otherPath = relativeOrAbsolute(absolutePath, base); + if (otherPath.length() < shortestPath.length()) + { + shortestBase = base; + shortestPath = otherPath; + } + } + return basePrefix(shortestBase) + relativeOrAbsolute(absolutePath, shortestBase); + } +} diff --git a/src/core/Plugin.cpp b/src/core/Plugin.cpp index 411f6fe5899..c5a0dc4758b 100644 --- a/src/core/Plugin.cpp +++ b/src/core/Plugin.cpp @@ -59,8 +59,8 @@ Plugin::Plugin(const Descriptor * descriptor, Model * parent, const Descriptor::SubPluginFeatures::Key* key) : Model(parent), JournallingObject(), - m_descriptor(descriptor), - m_key(key ? *key : Descriptor::SubPluginFeatures::Key(m_descriptor)) + m_key(key ? *key : Descriptor::SubPluginFeatures::Key(m_descriptor)), + m_descriptor(descriptor) { if( m_descriptor == NULL ) { @@ -176,6 +176,13 @@ void Plugin::loadFile( const QString & ) +void Plugin::loadPluginPresetFile(const QString &) +{ +} + + + + AutomatableModel * Plugin::childModel( const QString & ) { static FloatModel fm; diff --git a/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index ca0e5219499..d7a0260ef55 100644 --- a/src/core/PresetPreviewPlayHandle.cpp +++ b/src/core/PresetPreviewPlayHandle.cpp @@ -54,7 +54,7 @@ class PreviewTrackContainer : public TrackContainer { } - virtual QString nodeName() const + QString nodeName() const override { return "previewtrackcontainer"; } @@ -156,19 +156,9 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, dataFileCreated = true; } - // vestige previews are bug prone; fallback on 3xosc with volume of 0 - // without an instrument in preview track, it will segfault - if(dataFile->content().elementsByTagName( "vestige" ).length() == 0 ) - { - s_previewTC->previewInstrumentTrack()-> - loadTrackSpecificSettings( - dataFile->content().firstChild().toElement() ); - } - else - { - s_previewTC->previewInstrumentTrack()->loadInstrument("tripleoscillator"); - s_previewTC->previewInstrumentTrack()->setVolume( 0 ); - } + s_previewTC->previewInstrumentTrack()->loadTrackSpecificSettings( + dataFile->content().firstChild().toElement()); + if( dataFileCreated ) { delete dataFile; diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index 71a5aaff8b1..0616a925278 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -168,7 +168,7 @@ void ProjectRenderer::run() { MemoryManager::ThreadGuard mmThreadGuard; Q_UNUSED(mmThreadGuard); #if 0 -#ifdef LMMS_BUILD_LINUX +#if defined(LMMS_BUILD_LINUX) || defined(LMMS_BUILD_FREEBSD) #ifdef LMMS_HAVE_SCHED_H cpu_set_t mask; CPU_ZERO( &mask ); @@ -181,7 +181,6 @@ void ProjectRenderer::run() PerfLogTimer perfLog("Project Render"); Engine::getSong()->startExport(); - Engine::getSong()->updateLength(); // Skip first empty buffer. Engine::mixer()->nextBuffer(); diff --git a/src/core/RemotePlugin.cpp b/src/core/RemotePlugin.cpp index 23654d782ac..81ea93232b6 100644 --- a/src/core/RemotePlugin.cpp +++ b/src/core/RemotePlugin.cpp @@ -32,6 +32,7 @@ #include "RemotePlugin.h" #include "Mixer.h" #include "Engine.h" +#include "Song.h" #include #include @@ -78,7 +79,7 @@ void ProcessWatcher::run() RemotePlugin::RemotePlugin() : QObject(), #ifdef SYNC_WITH_SHM_FIFO - RemotePluginBase( new shmFifo(), new shmFifo() ), + RemotePluginBase(new ShmFifo(), new ShmFifo()), #else RemotePluginBase(), #endif @@ -86,11 +87,7 @@ RemotePlugin::RemotePlugin() : m_watcher( this ), m_commMutex( QMutex::Recursive ), m_splitChannels( false ), -#ifdef USE_QT_SHMEM m_shmObj(), -#else - m_shmID( 0 ), -#endif m_shmSize( 0 ), m_shm( NULL ), m_inputCount( DEFAULT_CHANNELS ), @@ -102,14 +99,14 @@ RemotePlugin::RemotePlugin() : m_socketFile = QDir::tempPath() + QDir::separator() + QUuid::createUuid().toString(); - const char * path = m_socketFile.toUtf8().constData(); - size_t length = strlen( path ); + auto path = m_socketFile.toUtf8(); + size_t length = path.length(); if ( length >= sizeof sa.sun_path ) { length = sizeof sa.sun_path - 1; qWarning( "Socket path too long." ); } - memcpy( sa.sun_path, path, length ); + memcpy(sa.sun_path, path.constData(), length ); sa.sun_path[length] = '\0'; m_server = socket( PF_LOCAL, SOCK_STREAM, 0 ); @@ -117,7 +114,7 @@ RemotePlugin::RemotePlugin() : { qWarning( "Unable to start the server." ); } - remove( path ); + remove(path.constData()); int ret = bind( m_server, (struct sockaddr *) &sa, sizeof sa ); if ( ret == -1 || listen( m_server, 1 ) == -1 ) { @@ -158,11 +155,6 @@ RemotePlugin::~RemotePlugin() } unlock(); } - -#ifndef USE_QT_SHMEM - shmdt( m_shm ); - shmctl( m_shmID, IPC_RMID, NULL ); -#endif } #ifndef SYNC_WITH_SHM_FIFO @@ -184,7 +176,7 @@ bool RemotePlugin::init(const QString &pluginExecutable, if( m_failed ) { #ifdef SYNC_WITH_SHM_FIFO - reset( new shmFifo(), new shmFifo() ); + reset( new ShmFifo(), new ShmFifo() ); #endif m_failed = false; } @@ -227,6 +219,8 @@ bool RemotePlugin::init(const QString &pluginExecutable, #else args << m_socketFile; #endif + // FIXME what should I pass as the ID? + args << QString::number(Engine::getSong()->vstSyncController().sharedMemoryKey()); args << extraArgs; #ifndef DEBUG_REMOTE_PLUGIN m_process.setProcessChannelMode( QProcess::ForwardedChannels ); @@ -245,8 +239,17 @@ bool RemotePlugin::init(const QString &pluginExecutable, pollin.fd = m_server; pollin.events = POLLIN; - switch ( poll( &pollin, 1, 30000 ) ) + int retryCount = 0; + int result; + do { + if (retryCount > 0) + { + qWarning("Retrying to connect to the remote plugin..."); + } + result = poll(&pollin, 1, 30000); + switch (result) + { case -1: qWarning( "Unexpected poll error." ); break; @@ -261,7 +264,9 @@ bool RemotePlugin::init(const QString &pluginExecutable, { qWarning( "Unexpected socket error." ); } - } + } + ++retryCount; + } while (result == -1 && retryCount <= 3); #endif resizeSharedProcessingMemory(); @@ -436,34 +441,13 @@ void RemotePlugin::resizeSharedProcessingMemory() sizeof( float ); if( m_shm != NULL ) { -#ifdef USE_QT_SHMEM m_shmObj.detach(); -#else - shmdt( m_shm ); - shmctl( m_shmID, IPC_RMID, NULL ); -#endif - } - - static int shm_key = 0; -#ifdef USE_QT_SHMEM - do - { - m_shmObj.setKey( QString( "%1" ).arg( ++shm_key ) ); - m_shmObj.create( s ); - } while( m_shmObj.error() != QSharedMemory::NoError ); - - m_shm = (float *) m_shmObj.data(); -#else - while( ( m_shmID = shmget( ++shm_key, s, IPC_CREAT | IPC_EXCL | - 0600 ) ) == -1 ) - { } - m_shm = (float *) shmat( m_shmID, 0, 0 ); -#endif - m_shmSize = s; + static int shmKey = 0; + m_shm = (float*)createShmWithFreeKey(m_shmObj, s, shmKey); sendMessage( message( IdChangeSharedMemoryKey ). - addInt( shm_key ).addInt( m_shmSize ) ); + addInt( shmKey ).addInt( m_shmSize ) ); } diff --git a/src/core/RenderManager.cpp b/src/core/RenderManager.cpp index 019e14acf42..69255442cd4 100644 --- a/src/core/RenderManager.cpp +++ b/src/core/RenderManager.cpp @@ -80,9 +80,9 @@ void RenderManager::renderNextTrack() m_tracksToRender.pop_back(); // mute everything but the track we are about to render - for( auto it = m_unmuted.begin(); it != m_unmuted.end(); ++it ) + for (auto track : m_unmuted) { - (*it)->setMuted( (*it) != renderTrack ); + track->setMuted(track != renderTrack); } // for multi-render, prefix each output file with a different number @@ -182,7 +182,7 @@ QString RenderManager::pathForTrack(const Track *track, int num) { QString extension = ProjectRenderer::getFileExtensionFromFormat( m_format ); QString name = track->name(); - name = name.remove(QRegExp("[^a-zA-Z]")); + name = name.remove(QRegExp(FILENAME_FILTER)); name = QString( "%1_%2%3" ).arg( num ).arg( name ).arg( extension ); return QDir(m_outputPath).filePath(name); } diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 7795925297b..cd943638d4f 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -24,7 +24,6 @@ #include "SampleBuffer.h" - #include #include #include @@ -55,11 +54,11 @@ #include "Engine.h" #include "GuiApplication.h" #include "Mixer.h" +#include "PathUtil.h" #include "FileDialog.h" - SampleBuffer::SampleBuffer() : m_audioFile( "" ), m_origData( NULL ), @@ -179,7 +178,7 @@ void SampleBuffer::update( bool _keep_settings ) } else if( !m_audioFile.isEmpty() ) { - QString file = tryToMakeAbsolute( m_audioFile ); + QString file = PathUtil::toAbsolute( m_audioFile ); int_sample_t * buf = NULL; sample_t * fbuf = NULL; ch_cnt_t channels = DEFAULT_CHANNELS; @@ -370,11 +369,14 @@ void SampleBuffer::directFloatWrite ( sample_t * & _fbuf, f_cnt_t _frames, int _ void SampleBuffer::normalizeSampleRate( const sample_rate_t _src_sr, bool _keep_settings ) { + const sample_rate_t old_rate = m_sampleRate; // do samplerate-conversion to our default-samplerate if( _src_sr != mixerSampleRate() ) { SampleBuffer * resampled = resample( _src_sr, mixerSampleRate() ); + + m_sampleRate = mixerSampleRate(); MM_FREE( m_data ); m_frames = resampled->frames(); m_data = MM_ALLOC( sampleFrame, m_frames ); @@ -389,6 +391,16 @@ void SampleBuffer::normalizeSampleRate( const sample_rate_t _src_sr, m_loopStartFrame = m_startFrame = 0; m_loopEndFrame = m_endFrame = m_frames; } + else if( old_rate != mixerSampleRate() ) + { + auto old_rate_to_new_rate_ratio = static_cast(mixerSampleRate()) / old_rate; + + m_startFrame = qBound(0, f_cnt_t(m_startFrame*old_rate_to_new_rate_ratio), m_frames); + m_endFrame = qBound(m_startFrame, f_cnt_t(m_endFrame*old_rate_to_new_rate_ratio), m_frames); + m_loopStartFrame = qBound(0, f_cnt_t(m_loopStartFrame*old_rate_to_new_rate_ratio), m_frames); + m_loopEndFrame = qBound(m_loopStartFrame, f_cnt_t(m_loopEndFrame*old_rate_to_new_rate_ratio), m_frames); + m_sampleRate = mixerSampleRate(); + } } @@ -768,7 +780,7 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state, } } - if( tmp != NULL ) + if( tmp != NULL ) { MM_FREE( tmp ); } @@ -1018,7 +1030,7 @@ QString SampleBuffer::openAudioFile() const { return QString(); } - return tryToMakeRelative( ofd.selectedFiles()[0] ); + return PathUtil::toShortestRelative( ofd.selectedFiles()[0] ); } return QString(); @@ -1209,7 +1221,7 @@ SampleBuffer * SampleBuffer::resample( const sample_rate_t _src_sr, void SampleBuffer::setAudioFile( const QString & _audio_file ) { - m_audioFile = tryToMakeRelative( _audio_file ); + m_audioFile = PathUtil::toShortestRelative( _audio_file ); update(); } @@ -1406,60 +1418,6 @@ void SampleBuffer::setReversed( bool _on ) -QString SampleBuffer::tryToMakeRelative( const QString & file ) -{ - if( QFileInfo( file ).isRelative() == false ) - { - // Normalize the path - QString f( QDir::cleanPath( file ) ); - - // First, look in factory samples - // Isolate "samples/" from "data:/samples/" - QString samplesSuffix = ConfigManager::inst()->factorySamplesDir().mid( ConfigManager::inst()->dataDir().length() ); - - // Iterate over all valid "data:/" searchPaths - for ( const QString & path : QDir::searchPaths( "data" ) ) - { - QString samplesPath = QDir::cleanPath( path + samplesSuffix ) + "/"; - if ( f.startsWith( samplesPath ) ) - { - return QString( f ).mid( samplesPath.length() ); - } - } - - // Next, look in user samples - QString usd = ConfigManager::inst()->userSamplesDir(); - usd.replace( QDir::separator(), '/' ); - if( f.startsWith( usd ) ) - { - return QString( f ).mid( usd.length() ); - } - } - return file; -} - - - - -QString SampleBuffer::tryToMakeAbsolute(const QString& file) -{ - QFileInfo f(file); - - if(f.isRelative()) - { - f = QFileInfo(ConfigManager::inst()->userSamplesDir() + file); - - if(! f.exists()) - { - f = QFileInfo(ConfigManager::inst()->factorySamplesDir() + file); - } - } - - if (f.exists()) { - return f.absoluteFilePath(); - } - return file; -} @@ -1475,7 +1433,7 @@ SampleBuffer::handleState::handleState( bool _varying_pitch, int interpolation_m { int error; m_interpolationMode = interpolation_mode; - + if( ( m_resamplingData = src_new( interpolation_mode, DEFAULT_CHANNELS, &error ) ) == NULL ) { qDebug( "Error: src_new() failed in sample_buffer.cpp!\n" ); diff --git a/include/custom_events.h b/src/core/ScriptPlugin.cpp similarity index 71% rename from include/custom_events.h rename to src/core/ScriptPlugin.cpp index 955521490de..d932463cd45 100644 --- a/include/custom_events.h +++ b/src/core/ScriptPlugin.cpp @@ -1,7 +1,7 @@ /* - * custom_events.h - custom event types list + * ScriptPlugin.cpp - base class for scripting plugins * - * Copyright (c) 2007 Javier Serrano Polo + * Copyright (c) 2019 Hyunjin Song * * This file is part of LMMS - https://lmms.io * @@ -22,25 +22,14 @@ * */ +#include -#ifndef CUSTOM_EVENTS_H -#define CUSTOM_EVENTS_H +#include "ScriptPlugin.h" -#include - - -namespace customEvents +ScriptPlugin::ScriptPlugin(const Plugin::Descriptor * desc, + Model * parent, + const Descriptor::SubPluginFeatures::Key * key) : + Plugin(desc, parent, key) { - - enum Type - { - GUI_UPDATE = QEvent::User - } ; - } - - - - -#endif diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 336aa3df273..5f63e6ee859 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -55,7 +55,7 @@ #include "PeakController.h" -tick_t MidiTime::s_ticksPerTact = DefaultTicksPerTact; +tick_t MidiTime::s_ticksPerBar = DefaultTicksPerBar; @@ -66,9 +66,10 @@ Song::Song() : this ) ) ), m_tempoModel( DefaultTempo, MinTempo, MaxTempo, this, tr( "Tempo" ) ), m_timeSigModel( this ), - m_oldTicksPerTact( DefaultTicksPerTact ), + m_oldTicksPerBar( DefaultTicksPerBar ), m_masterVolumeModel( 100, 0, 200, this, tr( "Master volume" ) ), m_masterPitchModel( 0, -12, 12, this, tr( "Master pitch" ) ), + m_nLoadingTrack( 0 ), m_fileName(), m_oldFileName(), m_modified( false ), @@ -79,6 +80,7 @@ Song::Song() : m_renderBetweenMarkers( false ), m_playing( false ), m_paused( false ), + m_savingProject( false ), m_loadingProject( false ), m_isCancelled( false ), m_playMode( Mode_None ), @@ -86,7 +88,7 @@ Song::Song() : m_patternToPlay( NULL ), m_loopPattern( false ), m_elapsedTicks( 0 ), - m_elapsedTacts( 0 ), + m_elapsedBars( 0 ), m_loopRenderCount(1), m_loopRenderRemaining(1) { @@ -162,10 +164,10 @@ void Song::setTempo() void Song::setTimeSignature() { - MidiTime::setTicksPerTact( ticksPerTact() ); - emit timeSignatureChanged( m_oldTicksPerTact, ticksPerTact() ); + MidiTime::setTicksPerBar( ticksPerBar() ); + emit timeSignatureChanged( m_oldTicksPerBar, ticksPerBar() ); emit dataChanged(); - m_oldTicksPerTact = ticksPerTact(); + m_oldTicksPerBar = ticksPerBar(); m_vstSyncController.setTimeSignature( getTimeSigModel().getNumerator(), getTimeSigModel().getDenominator() ); @@ -286,20 +288,20 @@ void Song::processNextBuffer() int ticks = m_playPos[m_playMode].getTicks() + ( int )( currentFrame / framesPerTick ); - // did we play a whole tact? - if( ticks >= MidiTime::ticksPerTact() ) + // did we play a whole bar? + if( ticks >= MidiTime::ticksPerBar() ) { // per default we just continue playing even if // there's no more stuff to play // (song-play-mode) - int maxTact = m_playPos[m_playMode].getTact() + int maxBar = m_playPos[m_playMode].getBar() + 2; - // then decide whether to go over to next tact - // or to loop back to first tact + // then decide whether to go over to next bar + // or to loop back to first bar if( m_playMode == Mode_PlayBB ) { - maxTact = Engine::getBBTrackContainer() + maxBar = Engine::getBBTrackContainer() ->lengthOfCurrentBB(); } else if( m_playMode == Mode_PlayPattern && @@ -307,17 +309,17 @@ void Song::processNextBuffer() tl != NULL && tl->loopPointsEnabled() == false ) { - maxTact = m_patternToPlay->length() - .getTact(); + maxBar = m_patternToPlay->length() + .getBar(); } // end of played object reached? - if( m_playPos[m_playMode].getTact() + 1 - >= maxTact ) + if( m_playPos[m_playMode].getBar() + 1 + >= maxBar ) { // then start from beginning and keep // offset - ticks %= ( maxTact * MidiTime::ticksPerTact() ); + ticks %= ( maxBar * MidiTime::ticksPerBar() ); // wrap milli second counter setToTimeByTicks(ticks); @@ -407,8 +409,8 @@ void Song::processNextBuffer() m_playPos[m_playMode].setCurrentFrame( framesToPlay + currentFrame ); m_elapsedMilliSeconds[m_playMode] += MidiTime::ticksToMilliseconds(framesToPlay / framesPerTick, getTempo()); - m_elapsedTacts = m_playPos[Mode_PlaySong].getTact(); - m_elapsedTicks = ( m_playPos[Mode_PlaySong].getTicks() % ticksPerTact() ) / 48; + m_elapsedBars = m_playPos[Mode_PlaySong].getBar(); + m_elapsedTicks = ( m_playPos[Mode_PlaySong].getTicks() % ticksPerBar() ) / 48; } } @@ -610,16 +612,14 @@ void Song::updateLength() { m_length = 0; m_tracksMutex.lockForRead(); - for( TrackList::const_iterator it = tracks().begin(); - it != tracks().end(); ++it ) + for (auto track : tracks()) { - if( Engine::getSong()->isExporting() && - ( *it )->isMuted() ) + if (m_exporting && track->isMuted()) { continue; } - const tact_t cur = ( *it )->length(); + const bar_t cur = track->length(); if( cur > m_length ) { m_length = cur; @@ -742,6 +742,10 @@ void Song::stop() void Song::startExport() { stop(); + + m_exporting = true; + updateLength(); + if (m_renderBetweenMarkers) { m_exportSongBegin = m_exportLoopBegin = m_playPos[Mode_PlaySong].m_timeLine->loopBegin(); @@ -763,12 +767,16 @@ void Song::startExport() m_exportSongEnd += MidiTime(1,0); m_exportSongBegin = MidiTime(0,0); - m_exportLoopBegin = m_playPos[Mode_PlaySong].m_timeLine->loopBegin() < m_exportSongEnd && - m_playPos[Mode_PlaySong].m_timeLine->loopEnd() <= m_exportSongEnd ? - m_playPos[Mode_PlaySong].m_timeLine->loopBegin() : MidiTime(0,0); - m_exportLoopEnd = m_playPos[Mode_PlaySong].m_timeLine->loopBegin() < m_exportSongEnd && - m_playPos[Mode_PlaySong].m_timeLine->loopEnd() <= m_exportSongEnd ? - m_playPos[Mode_PlaySong].m_timeLine->loopEnd() : MidiTime(0,0); + // FIXME: remove this check once we load timeline in headless mode + if (m_playPos[Mode_PlaySong].m_timeLine) + { + m_exportLoopBegin = m_playPos[Mode_PlaySong].m_timeLine->loopBegin() < m_exportSongEnd && + m_playPos[Mode_PlaySong].m_timeLine->loopEnd() <= m_exportSongEnd ? + m_playPos[Mode_PlaySong].m_timeLine->loopBegin() : MidiTime(0,0); + m_exportLoopEnd = m_playPos[Mode_PlaySong].m_timeLine->loopBegin() < m_exportSongEnd && + m_playPos[Mode_PlaySong].m_timeLine->loopEnd() <= m_exportSongEnd ? + m_playPos[Mode_PlaySong].m_timeLine->loopEnd() : MidiTime(0,0); + } m_playPos[Mode_PlaySong].setTicks( 0 ); } @@ -779,8 +787,6 @@ void Song::startExport() playSong(); - m_exporting = true; - m_vstSyncController.setPlaybackState( true ); } @@ -791,7 +797,6 @@ void Song::stopExport() { stop(); m_exporting = false; - m_exportLoop = false; m_vstSyncController.setPlaybackState( m_playing ); } @@ -805,7 +810,7 @@ void Song::insertBar() for( TrackList::const_iterator it = tracks().begin(); it != tracks().end(); ++it ) { - ( *it )->insertTact( m_playPos[Mode_PlaySong] ); + ( *it )->insertBar( m_playPos[Mode_PlaySong] ); } m_tracksMutex.unlock(); } @@ -819,7 +824,7 @@ void Song::removeBar() for( TrackList::const_iterator it = tracks().begin(); it != tracks().end(); ++it ) { - ( *it )->removeTact( m_playPos[Mode_PlaySong] ); + ( *it )->removeBar( m_playPos[Mode_PlaySong] ); } m_tracksMutex.unlock(); } @@ -1420,24 +1425,37 @@ void Song::clearErrors() void Song::collectError( const QString error ) { - m_errors.append( error ); + if (!m_errors.contains(error)) { m_errors[error] = 1; } + else { m_errors[ error ]++; } } bool Song::hasErrors() { - return ( m_errors.length() > 0 ); + return !(m_errors.isEmpty()); } QString Song::errorSummary() { - QString errors = m_errors.join("\n") + '\n'; + QString errors; + + auto i = m_errors.constBegin(); + while (i != m_errors.constEnd()) + { + errors.append( i.key() ); + if( i.value() > 1 ) + { + errors.append( tr(" (repeated %1 times)").arg( i.value() ) ); + } + errors.append("\n"); + ++i; + } errors.prepend( "\n\n" ); - errors.prepend( tr( "The following errors occured while loading: " ) ); + errors.prepend( tr( "The following errors occurred while loading: " ) ); return errors; } diff --git a/src/core/StepRecorder.cpp b/src/core/StepRecorder.cpp index 7a63e88e26e..e107c58181b 100644 --- a/src/core/StepRecorder.cpp +++ b/src/core/StepRecorder.cpp @@ -32,7 +32,8 @@ const int REMOVE_RELEASED_NOTE_TIME_THRESHOLD_MS = 70; StepRecorder::StepRecorder(PianoRoll& pianoRoll, StepRecorderWidget& stepRecorderWidget): m_pianoRoll(pianoRoll), - m_stepRecorderWidget(stepRecorderWidget) + m_stepRecorderWidget(stepRecorderWidget), + m_pattern(nullptr) { m_stepRecorderWidget.hide(); } diff --git a/src/core/Track.cpp b/src/core/Track.cpp index 64c17c9e8ec..f79a34a15c9 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -44,6 +44,8 @@ #include #include #include +#include +#include #include "AutomationPattern.h" @@ -73,6 +75,10 @@ */ const int RESIZE_GRIP_WIDTH = 4; +/*! Alternate between a darker and a lighter background color every 4 bars + */ +const int BARS_PER_GROUP = 4; + /*! A pointer for that text bubble used when moving segments, etc. * @@ -155,7 +161,7 @@ void TrackContentObject::movePosition( const MidiTime & pos ) /*! \brief Change the length of this TrackContentObject * - * If the track content object's length has chaanged, update it. We + * If the track content object's length has changed, update it. We * also add a journal entry for undo and update the display. * * \param _length The new length of the track content object. @@ -267,6 +273,9 @@ TrackContentObjectView::TrackContentObjectView( TrackContentObject * tco, m_action( NoAction ), m_initialMousePos( QPoint( 0, 0 ) ), m_initialMouseGlobalPos( QPoint( 0, 0 ) ), + m_initialTCOPos( MidiTime(0) ), + m_initialTCOEnd( MidiTime(0) ), + m_initialOffsets( QVector() ), m_hint( NULL ), m_mutedColor( 0, 0, 0 ), m_mutedBackgroundColor( 0, 0, 0 ), @@ -275,6 +284,8 @@ TrackContentObjectView::TrackContentObjectView( TrackContentObject * tco, m_textShadowColor( 0, 0, 0 ), m_BBPatternBackground( 0, 0, 0 ), m_gradient( true ), + m_mouseHotspotHand( 0, 0 ), + m_cursorSetYet( false ), m_needsUpdate( true ) { if( s_textFloat == NULL ) @@ -286,7 +297,7 @@ TrackContentObjectView::TrackContentObjectView( TrackContentObject * tco, setAttribute( Qt::WA_OpaquePaintEvent, true ); setAttribute( Qt::WA_DeleteOnClose, true ); setFocusPolicy( Qt::StrongFocus ); - setCursor( QCursor( embed::getIconPixmap( "hand" ), 3, 3 ) ); + setCursor( QCursor( embed::getIconPixmap( "hand" ), m_mouseHotspotHand.width(), m_mouseHotspotHand.height() ) ); move( 0, 0 ); show(); @@ -335,6 +346,12 @@ TrackContentObjectView::~TrackContentObjectView() */ void TrackContentObjectView::update() { + if( !m_cursorSetYet ) + { + setCursor( QCursor( embed::getIconPixmap( "hand" ), m_mouseHotspotHand.width(), m_mouseHotspotHand.height() ) ); + m_cursorSetYet = true; + } + if( fixedTCOs() ) { updateLength(); @@ -415,6 +432,11 @@ void TrackContentObjectView::setBBPatternBackground( const QColor & c ) void TrackContentObjectView::setGradient( const bool & b ) { m_gradient = b; } +void TrackContentObjectView::setMouseHotspotHand(const QSize & s) +{ + m_mouseHotspotHand = s; +} + // access needsUpdate member variable bool TrackContentObjectView::needsUpdate() { return m_needsUpdate; } @@ -486,8 +508,8 @@ void TrackContentObjectView::updateLength() else { setFixedWidth( - static_cast( m_tco->length() * pixelsPerTact() / - MidiTime::ticksPerTact() ) + 1 /*+ + static_cast( m_tco->length() * pixelsPerBar() / + MidiTime::ticksPerBar() ) + 1 /*+ TCO_BORDER_WIDTH * 2-1*/ ); } m_trackView->trackContainerView()->update(); @@ -524,7 +546,8 @@ void TrackContentObjectView::updatePosition() void TrackContentObjectView::dragEnterEvent( QDragEnterEvent * dee ) { TrackContentWidget * tcw = getTrackView()->getTrackContentWidget(); - MidiTime tcoPos = MidiTime( m_tco->startPosition().getTact(), 0 ); + MidiTime tcoPos = MidiTime( m_tco->startPosition() ); + if( tcw->canPasteSelection( tcoPos, dee ) == false ) { dee->ignore(); @@ -563,7 +586,8 @@ void TrackContentObjectView::dropEvent( QDropEvent * de ) if( m_trackView->trackContainerView()->allowRubberband() == true ) { TrackContentWidget * tcw = getTrackView()->getTrackContentWidget(); - MidiTime tcoPos = MidiTime( m_tco->startPosition().getTact(), 0 ); + MidiTime tcoPos = MidiTime( m_tco->startPosition() ); + if( tcw->pasteSelection( tcoPos, de ) == true ) { de->accept(); @@ -600,7 +624,7 @@ void TrackContentObjectView::leaveEvent( QEvent * e ) { if( cursor().shape() != Qt::BitmapCursor ) { - setCursor( QCursor( embed::getIconPixmap( "hand" ), 3, 3 ) ); + setCursor( QCursor( embed::getIconPixmap( "hand" ), m_mouseHotspotHand.width(), m_mouseHotspotHand.height() ) ); } if( e != NULL ) { @@ -653,7 +677,7 @@ DataFile TrackContentObjectView::createTCODataFiles( // initialTrackIndex is the index of the track that was touched metadata.setAttribute( "initialTrackIndex", initialTrackIndex ); metadata.setAttribute( "trackContainerId", tc->id() ); - // grabbedTCOPos is the pos of the tact containing the TCO we grabbed + // grabbedTCOPos is the pos of the bar containing the TCO we grabbed metadata.setAttribute( "grabbedTCOPos", m_tco->startPosition() ); dataFile.content().appendChild( metadata ); @@ -711,7 +735,14 @@ void TrackContentObjectView::paintTextLabel(QString const & text, QPainter & pai */ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) { - setInitialMousePos( me->pos() ); + // Right now, active is only used on right/mid clicks actions, so we use a ternary operator + // to avoid the overhead of calling getClickedTCOs when it's not used + auto active = me->button() == Qt::LeftButton + ? QVector() + : getClickedTCOs(); + + setInitialPos( me->pos() ); + setInitialOffsets(); if( !fixedTCOs() && me->button() == Qt::LeftButton ) { if( me->modifiers() & Qt::ControlModifier ) @@ -725,7 +756,9 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) m_action = ToggleSelected; } } - else if( !me->modifiers() ) + else if( !me->modifiers() + || (me->modifiers() & Qt::AltModifier) + || (me->modifiers() & Qt::ShiftModifier) ) { if( isSelected() ) { @@ -739,7 +772,8 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) // move or resize m_tco->setJournalling( false ); - setInitialMousePos( me->pos() ); + setInitialPos( me->pos() ); + setInitialOffsets(); SampleTCO * sTco = dynamic_cast( m_tco ); if( me->x() < RESIZE_GRIP_WIDTH && sTco @@ -748,12 +782,12 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) m_action = ResizeLeft; setCursor( Qt::SizeHorCursor ); } - else if( me->x() < width() - RESIZE_GRIP_WIDTH ) + else if( m_tco->getAutoResize() || me->x() < width() - RESIZE_GRIP_WIDTH ) { m_action = Move; setCursor( Qt::SizeAllCursor ); } - else if( !m_tco->getAutoResize() ) + else { m_action = Resize; setCursor( Qt::SizeHorCursor ); @@ -763,23 +797,23 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) { s_textFloat->setTitle( tr( "Current position" ) ); s_textFloat->setText( QString( "%1:%2" ). - arg( m_tco->startPosition().getTact() + 1 ). + arg( m_tco->startPosition().getBar() + 1 ). arg( m_tco->startPosition().getTicks() % - MidiTime::ticksPerTact() ) ); + MidiTime::ticksPerBar() ) ); } else if( m_action == Resize || m_action == ResizeLeft ) { s_textFloat->setTitle( tr( "Current length" ) ); s_textFloat->setText( tr( "%1:%2 (%3:%4 to %5:%6)" ). - arg( m_tco->length().getTact() ). + arg( m_tco->length().getBar() ). arg( m_tco->length().getTicks() % - MidiTime::ticksPerTact() ). - arg( m_tco->startPosition().getTact() + 1 ). + MidiTime::ticksPerBar() ). + arg( m_tco->startPosition().getBar() + 1 ). arg( m_tco->startPosition().getTicks() % - MidiTime::ticksPerTact() ). - arg( m_tco->endPosition().getTact() + 1 ). + MidiTime::ticksPerBar() ). + arg( m_tco->endPosition().getBar() + 1 ). arg( m_tco->endPosition().getTicks() % - MidiTime::ticksPerTact() ) ); + MidiTime::ticksPerBar() ) ); } // s_textFloat->reparent( this ); // setup text-float as if TCO was already moved/resized @@ -799,22 +833,22 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) { if( me->modifiers() & Qt::ControlModifier ) { - m_tco->toggleMute(); + toggleMute( active ); } else if( me->modifiers() & Qt::ShiftModifier && !fixedTCOs() ) { - remove(); + remove( active ); } } else if( me->button() == Qt::MidButton ) { if( me->modifiers() & Qt::ControlModifier ) { - m_tco->toggleMute(); + toggleMute( active ); } else if( !fixedTCOs() ) { - remove(); + remove( active ); } } } @@ -886,79 +920,89 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) m_hint = NULL; } - const float ppt = m_trackView->trackContainerView()->pixelsPerTact(); + const float ppb = m_trackView->trackContainerView()->pixelsPerBar(); if( m_action == Move ) { - const int x = mapToParent( me->pos() ).x() - m_initialMousePos.x(); - MidiTime t = qMax( 0, (int) - m_trackView->trackContainerView()->currentPosition()+ - static_cast( x * MidiTime::ticksPerTact() / - ppt ) ); - if( ! ( me->modifiers() & Qt::ControlModifier ) - && me->button() == Qt::NoButton ) - { - t = t.toNearestTact(); - } - m_tco->movePosition( t ); + MidiTime newPos = draggedTCOPos( me ); + + // Don't go left of bar zero + newPos = max( 0, newPos.getTicks() ); + m_tco->movePosition( newPos ); m_trackView->getTrackContentWidget()->changePosition(); s_textFloat->setText( QString( "%1:%2" ). - arg( m_tco->startPosition().getTact() + 1 ). - arg( m_tco->startPosition().getTicks() % - MidiTime::ticksPerTact() ) ); + arg( newPos.getBar() + 1 ). + arg( newPos.getTicks() % + MidiTime::ticksPerBar() ) ); s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2 ) ); } else if( m_action == MoveSelection ) { - const int dx = me->x() - m_initialMousePos.x(); - const bool snap = !(me->modifiers() & Qt::ControlModifier) && - me->button() == Qt::NoButton; + // 1: Find the position we want to move the grabbed TCO to + MidiTime newPos = draggedTCOPos( me ); + + // 2: Handle moving the other selected TCOs the same distance QVector so = m_trackView->trackContainerView()->selectedObjects(); - QVector tcos; - int smallestPos = 0; - MidiTime dtick = MidiTime( static_cast( dx * - MidiTime::ticksPerTact() / ppt ) ); - if( snap ) - { - dtick = dtick.toNearestTact(); - } - // find out smallest position of all selected objects for not - // moving an object before zero + QVector tcos; // List of selected clips + int leftmost = 0; // Leftmost clip's offset from grabbed clip + // Populate tcos, find leftmost for( QVector::iterator it = so.begin(); it != so.end(); ++it ) { TrackContentObjectView * tcov = dynamic_cast( *it ); - if( tcov == NULL ) - { - continue; - } - TrackContentObject * tco = tcov->m_tco; - tcos.push_back( tco ); - smallestPos = qMin( smallestPos, - (int)tco->startPosition() + dtick ); - } - dtick -= smallestPos; - if( snap ) - { - dtick = dtick.toAbsoluteTact(); // round toward 0 + if( tcov == NULL ) { continue; } + tcos.push_back( tcov->m_tco ); + int index = std::distance( so.begin(), it ); + leftmost = min (leftmost, m_initialOffsets[index].getTicks() ); } + // Make sure the leftmost clip doesn't get moved to a negative position + if ( newPos.getTicks() + leftmost < 0 ) { newPos = -leftmost; } + for( QVector::iterator it = tcos.begin(); it != tcos.end(); ++it ) { - ( *it )->movePosition( ( *it )->startPosition() + dtick ); + int index = std::distance( tcos.begin(), it ); + ( *it )->movePosition( newPos + m_initialOffsets[index] ); } } else if( m_action == Resize || m_action == ResizeLeft ) { + // If the user is holding alt, or pressed ctrl after beginning the drag, don't quantize + const bool unquantized = (me->modifiers() & Qt::ControlModifier) || (me->modifiers() & Qt::AltModifier); + const float snapSize = gui->songEditor()->m_editor->getSnapSize(); + // Length in ticks of one snap increment + const MidiTime snapLength = MidiTime( (int)(snapSize * MidiTime::ticksPerBar()) ); + if( m_action == Resize ) { - MidiTime t = qMax( MidiTime::ticksPerTact() / 16, static_cast( me->x() * MidiTime::ticksPerTact() / ppt ) ); - if( ! ( me->modifiers() & Qt::ControlModifier ) && me->button() == Qt::NoButton ) - { - t = qMax( MidiTime::ticksPerTact(), t.toNearestTact() ); + // The clip's new length + MidiTime l = static_cast( me->x() * MidiTime::ticksPerBar() / ppb ); + + if ( unquantized ) + { // We want to preserve this adjusted offset, + // even if the user switches to snapping later + setInitialPos( m_initialMousePos ); + // Don't resize to less than 1 tick + m_tco->changeLength( qMax( 1, l ) ); + } + else if ( me->modifiers() & Qt::ShiftModifier ) + { // If shift is held, quantize clip's end position + MidiTime end = MidiTime( m_initialTCOPos + l ).quantize( snapSize ); + // The end position has to be after the clip's start + MidiTime min = m_initialTCOPos.quantize( snapSize ); + if ( min <= m_initialTCOPos ) min += snapLength; + m_tco->changeLength( qMax(min - m_initialTCOPos, end - m_initialTCOPos) ); + } + else + { // Otherwise, resize in fixed increments + MidiTime initialLength = m_initialTCOEnd - m_initialTCOPos; + MidiTime offset = MidiTime( l - initialLength ).quantize( snapSize ); + // Don't resize to less than 1 tick + MidiTime min = MidiTime( initialLength % snapLength ); + if (min < 1) min += snapLength; + m_tco->changeLength( qMax( min, initialLength + offset) ); } - m_tco->changeLength( t ); } else { @@ -968,16 +1012,35 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) const int x = mapToParent( me->pos() ).x() - m_initialMousePos.x(); MidiTime t = qMax( 0, (int) - m_trackView->trackContainerView()->currentPosition()+ - static_cast( x * MidiTime::ticksPerTact() / - ppt ) ); - if( ! ( me->modifiers() & Qt::ControlModifier ) - && me->button() == Qt::NoButton ) - { - t = t.toNearestTact(); + m_trackView->trackContainerView()->currentPosition() + + static_cast( x * MidiTime::ticksPerBar() / ppb ) ); + + if( unquantized ) + { // We want to preserve this adjusted offset, + // even if the user switches to snapping later + setInitialPos( m_initialMousePos ); + //Don't resize to less than 1 tick + t = qMin( m_initialTCOEnd - 1, t); + } + else if( me->modifiers() & Qt::ShiftModifier ) + { // If shift is held, quantize clip's start position + // Don't let the start position move past the end position + MidiTime max = m_initialTCOEnd.quantize( snapSize ); + if ( max >= m_initialTCOEnd ) max -= snapLength; + t = qMin( max, t.quantize( snapSize ) ); + } + else + { // Otherwise, resize in fixed increments + // Don't resize to less than 1 tick + MidiTime initialLength = m_initialTCOEnd - m_initialTCOPos; + MidiTime minLength = MidiTime( initialLength % snapLength ); + if (minLength < 1) minLength += snapLength; + MidiTime offset = MidiTime(t - m_initialTCOPos).quantize( snapSize ); + t = qMin( m_initialTCOEnd - minLength, m_initialTCOPos + offset ); } + MidiTime oldPos = m_tco->startPosition(); - if( m_tco->length() + ( oldPos - t ) >= MidiTime::ticksPerTact() ) + if( m_tco->length() + ( oldPos - t ) >= 1 ) { m_tco->movePosition( t ); m_trackView->getTrackContentWidget()->changePosition(); @@ -987,15 +1050,15 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) } } s_textFloat->setText( tr( "%1:%2 (%3:%4 to %5:%6)" ). - arg( m_tco->length().getTact() ). + arg( m_tco->length().getBar() ). arg( m_tco->length().getTicks() % - MidiTime::ticksPerTact() ). - arg( m_tco->startPosition().getTact() + 1 ). + MidiTime::ticksPerBar() ). + arg( m_tco->startPosition().getBar() + 1 ). arg( m_tco->startPosition().getTicks() % - MidiTime::ticksPerTact() ). - arg( m_tco->endPosition().getTact() + 1 ). + MidiTime::ticksPerBar() ). + arg( m_tco->endPosition().getBar() + 1 ). arg( m_tco->endPosition().getTicks() % - MidiTime::ticksPerTact() ) ); + MidiTime::ticksPerBar() ) ); s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2) ); } else @@ -1060,45 +1123,234 @@ void TrackContentObjectView::mouseReleaseEvent( QMouseEvent * me ) */ void TrackContentObjectView::contextMenuEvent( QContextMenuEvent * cme ) { + // Depending on whether we right-clicked a selection or an individual TCO we will have + // different labels for the actions. + bool individualTCO = getClickedTCOs().size() <= 1; + if( cme->modifiers() ) { return; } QMenu contextMenu( this ); + if( fixedTCOs() == false ) { - contextMenu.addAction( embed::getIconPixmap( "cancel" ), - tr( "Delete (middle mousebutton)" ), - this, SLOT( remove() ) ); + contextMenu.addAction( + embed::getIconPixmap( "cancel" ), + tr( individualTCO + ? "Delete (middle mousebutton)" + : "Delete selection (middle mousebutton)" ), + [this](){ contextMenuAction( Remove ); } ); + contextMenu.addSeparator(); - contextMenu.addAction( embed::getIconPixmap( "edit_cut" ), - tr( "Cut" ), this, SLOT( cut() ) ); + + contextMenu.addAction( + embed::getIconPixmap( "edit_cut" ), + tr( individualTCO + ? "Cut" + : "Cut selection" ), + [this](){ contextMenuAction( Cut ); } ); } - contextMenu.addAction( embed::getIconPixmap( "edit_copy" ), - tr( "Copy" ), m_tco, SLOT( copy() ) ); - contextMenu.addAction( embed::getIconPixmap( "edit_paste" ), - tr( "Paste" ), m_tco, SLOT( paste() ) ); + + contextMenu.addAction( + embed::getIconPixmap( "edit_copy" ), + tr( individualTCO + ? "Copy" + : "Copy selection" ), + [this](){ contextMenuAction( Copy ); } ); + + contextMenu.addAction( + embed::getIconPixmap( "edit_paste" ), + tr( "Paste" ), + [this](){ contextMenuAction( Paste ); } ); + contextMenu.addSeparator(); - contextMenu.addAction( embed::getIconPixmap( "muted" ), - tr( "Mute/unmute (<%1> + middle click)" ).arg(UI_CTRL_KEY), - m_tco, SLOT( toggleMute() ) ); + + contextMenu.addAction( + embed::getIconPixmap( "muted" ), + tr( individualTCO + ? "Mute/unmute (<%1> + middle click)" + : "Mute/unmute selection (<%1> + middle click)" ).arg(UI_CTRL_KEY), + [this](){ contextMenuAction( Mute ); } ); + constructContextMenu( &contextMenu ); contextMenu.exec( QCursor::pos() ); } +// This method processes the actions from the context menu of the TCO View. +void TrackContentObjectView::contextMenuAction( ContextMenuAction action ) +{ + QVector active = getClickedTCOs(); + // active will be later used for the remove, copy, cut or toggleMute methods + switch( action ) + { + case Remove: + remove( active ); + break; + case Cut: + cut( active ); + break; + case Copy: + copy( active ); + break; + case Paste: + paste(); + break; + case Mute: + toggleMute( active ); + break; + } +} +QVector TrackContentObjectView::getClickedTCOs() +{ + // Get a list of selected selectableObjects + QVector sos = gui->songEditor()->m_editor->selectedObjects(); + + // Convert to a list of selected TCOVs + QVector selection; + selection.reserve( sos.size() ); + for( auto so: sos ) + { + TrackContentObjectView *tcov = dynamic_cast ( so ); + if( tcov != nullptr ) + { + selection.append( tcov ); + } + } + + // If we clicked part of the selection, affect all selected clips. Otherwise affect the clip we clicked + return selection.contains(this) + ? selection + : QVector( 1, this ); +} + +void TrackContentObjectView::remove( QVector tcovs ) +{ + for( auto tcov: tcovs ) + { + // No need to check if it's nullptr because we check when building the QVector + tcov->remove(); + } +} + +void TrackContentObjectView::copy( QVector tcovs ) +{ + // Checks if there are other selected TCOs and if so copy them as well + if( tcovs.size() > 1 ) + { + // Write the TCOs to a DataFile for copying + DataFile dataFile = createTCODataFiles( tcovs ); + + // Add the TCO type as a key to the final string + QString finalString = QString( "tco_%1:%2" ).arg( m_tco->getTrack()->type() ).arg( dataFile.toString() ); + + // Copy it to the clipboard + QMimeData *tco_content = new QMimeData; + tco_content->setData( StringPairDrag::mimeType(), finalString.toUtf8() ); + QApplication::clipboard()->setMimeData( tco_content, QClipboard::Clipboard ); + } + else + { + tcovs.at(0)->getTrackContentObject()->copy(); + } +} +void TrackContentObjectView::cut( QVector tcovs ) +{ + // Checks if there are other selected TCOs and if so cut them as well + if( tcovs.size() > 1 ) + { + // Write the TCOs to a DataFile for copying + DataFile dataFile = createTCODataFiles( tcovs ); + + // Now that the dataFile is created we can delete the tracks, since we are cutting + // TODO: Is it safe to call tcov->remove(); on the current TCOV instance? + remove( tcovs ); + + // Add the TCO type as a key to the final string + QString finalString = QString( "tco_%1:%2" ).arg( m_tco->getTrack()->type() ).arg( dataFile.toString() ); + + // Copy it to the clipboard + QMimeData *tco_content = new QMimeData; + tco_content->setData( StringPairDrag::mimeType(), finalString.toUtf8() ); + QApplication::clipboard()->setMimeData( tco_content, QClipboard::Clipboard ); + } + else + { + tcovs.at(0)->cut(); + } +} + +void TrackContentObjectView::paste() +{ + // NOTE: Because we give preference to the QApplication clipboard over the LMMS Clipboard class, we need to + // clear the QApplication Clipboard during the LMMS Clipboard copy operations (Clipboard::copy does that) -/*! \brief How many pixels a tact (bar) takes for this trackContentObjectView. + // If we have TCO data on the clipboard paste it. If not, do our regular TCO paste. + if( QApplication::clipboard()->mimeData( QClipboard::Clipboard )->hasFormat( StringPairDrag::mimeType() ) ) + { + // Paste the selection on the MidiTime of the selected Track + const QMimeData *md = QApplication::clipboard()->mimeData( QClipboard::Clipboard ); + MidiTime tcoPos = MidiTime( m_tco->startPosition() ); + + TrackContentWidget *tcw = getTrackView()->getTrackContentWidget(); + + if( tcw->pasteSelection( tcoPos, md ) == true ) + { + // If we succeed on the paste we delete the TCO we pasted on + remove(); + } + } + else + { + getTrackContentObject()->paste(); + } +} + +void TrackContentObjectView::toggleMute( QVector tcovs ) +{ + for( auto tcov: tcovs ) + { + // No need to check for nullptr because we check while building the tcovs QVector + tcov->getTrackContentObject()->toggleMute(); + } +} + + + + +/*! \brief How many pixels a bar takes for this trackContentObjectView. * - * \return the number of pixels per tact (bar). + * \return the number of pixels per bar. */ -float TrackContentObjectView::pixelsPerTact() +float TrackContentObjectView::pixelsPerBar() { - return m_trackView->trackContainerView()->pixelsPerTact(); + return m_trackView->trackContainerView()->pixelsPerBar(); +} + + +/*! \brief Save the offsets between all selected tracks and a clicked track */ +void TrackContentObjectView::setInitialOffsets() +{ + QVector so = m_trackView->trackContainerView()->selectedObjects(); + QVector offsets; + for( QVector::iterator it = so.begin(); + it != so.end(); ++it ) + { + TrackContentObjectView * tcov = + dynamic_cast( *it ); + if( tcov == NULL ) + { + continue; + } + offsets.push_back( tcov->m_tco->startPosition() - m_initialTCOPos ); + } + + m_initialOffsets = offsets; } @@ -1118,6 +1370,49 @@ bool TrackContentObjectView::mouseMovedDistance( QMouseEvent * me, int distance +/*! \brief Calculate the new position of a dragged TCO from a mouse event + * + * + * \param me The QMouseEvent + */ +MidiTime TrackContentObjectView::draggedTCOPos( QMouseEvent * me ) +{ + //Pixels per bar + const float ppb = m_trackView->trackContainerView()->pixelsPerBar(); + // The pixel distance that the mouse has moved + const int mouseOff = mapToGlobal(me->pos()).x() - m_initialMouseGlobalPos.x(); + MidiTime newPos = m_initialTCOPos + mouseOff * MidiTime::ticksPerBar() / ppb; + MidiTime offset = newPos - m_initialTCOPos; + // If the user is holding alt, or pressed ctrl after beginning the drag, don't quantize + if ( me->button() != Qt::NoButton + || (me->modifiers() & Qt::ControlModifier) + || (me->modifiers() & Qt::AltModifier) ) + { + // We want to preserve this adjusted offset, + // even if the user switches to snapping + setInitialPos( m_initialMousePos ); + } + else if ( me->modifiers() & Qt::ShiftModifier ) + { // If shift is held, quantize position (Default in 1.2.0 and earlier) + // or end position, whichever is closest to the actual position + MidiTime startQ = newPos.quantize( gui->songEditor()->m_editor->getSnapSize() ); + // Find start position that gives snapped clip end position + MidiTime endQ = ( newPos + m_tco->length() ); + endQ = endQ.quantize( gui->songEditor()->m_editor->getSnapSize() ); + endQ = endQ - m_tco->length(); + // Select the position closest to actual position + if ( abs(newPos - startQ) < abs(newPos - endQ) ) newPos = startQ; + else newPos = endQ; + } + else + { // Otherwise, quantize moved distance (preserves user offsets) + newPos = m_initialTCOPos + offset.quantize( gui->songEditor()->m_editor->getSnapSize() ); + } + return newPos; +} + + + // =========================================================================== // trackContentWidget @@ -1165,13 +1460,12 @@ TrackContentWidget::~TrackContentWidget() void TrackContentWidget::updateBackground() { - const int tactsPerBar = 4; const TrackContainerView * tcv = m_trackView->trackContainerView(); - // Assume even-pixels-per-tact. Makes sense, should be like this anyways - int ppt = static_cast( tcv->pixelsPerTact() ); + // Assume even-pixels-per-bar. Makes sense, should be like this anyways + int ppb = static_cast( tcv->pixelsPerBar() ); - int w = ppt * tactsPerBar; + int w = ppb * BARS_PER_GROUP; int h = height(); m_background = QPixmap( w * 2, height() ); QPainter pmp( &m_background ); @@ -1182,13 +1476,13 @@ void TrackContentWidget::updateBackground() // draw lines // vertical lines pmp.setPen( QPen( gridColor(), 1 ) ); - for( float x = 0; x < w * 2; x += ppt ) + for( float x = 0; x < w * 2; x += ppb ) { pmp.drawLine( QLineF( x, 0.0, x, h ) ); } pmp.setPen( QPen( embossColor(), 1 ) ); - for( float x = 1.0; x < w * 2; x += ppt ) + for( float x = 1.0; x < w * 2; x += ppb ) { pmp.drawLine( QLineF( x, 0.0, x, h ) ); } @@ -1283,7 +1577,7 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) it != m_tcoViews.end(); ++it ) { if( ( *it )->getTrackContentObject()-> - startPosition().getTact() == curBB ) + startPosition().getBar() == curBB ) { ( *it )->move( 0, ( *it )->y() ); ( *it )->raise(); @@ -1299,7 +1593,7 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) it != m_tcoViews.end(); ++it ) { if( ( *it )->getTrackContentObject()-> - startPosition().getTact() != curBB ) + startPosition().getBar() != curBB ) { ( *it )->hide(); } @@ -1316,7 +1610,7 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) const int begin = pos; const int end = endPosition( pos ); - const float ppt = m_trackView->trackContainerView()->pixelsPerTact(); + const float ppb = m_trackView->trackContainerView()->pixelsPerBar(); setUpdatesEnabled( false ); for( tcoViewVector::iterator it = m_tcoViews.begin(); @@ -1333,8 +1627,8 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) ( te >= begin && te <= end ) || ( ts <= begin && te >= end ) ) { - tcov->move( static_cast( ( ts - begin ) * ppt / - MidiTime::ticksPerTact() ), + tcov->move( static_cast( ( ts - begin ) * ppb / + MidiTime::ticksPerBar() ), tcov->y() ); if( !tcov->isVisible() ) { @@ -1355,7 +1649,7 @@ void TrackContentWidget::changePosition( const MidiTime & newPos ) -/*! \brief Return the position of the trackContentWidget in Tacts. +/*! \brief Return the position of the trackContentWidget in bars. * * \param mouseX the mouse's current X position in pixels. */ @@ -1364,8 +1658,8 @@ MidiTime TrackContentWidget::getPosition( int mouseX ) TrackContainerView * tv = m_trackView->trackContainerView(); return MidiTime( tv->currentPosition() + mouseX * - MidiTime::ticksPerTact() / - static_cast( tv->pixelsPerTact() ) ); + MidiTime::ticksPerBar() / + static_cast( tv->pixelsPerBar() ) ); } @@ -1378,7 +1672,7 @@ MidiTime TrackContentWidget::getPosition( int mouseX ) void TrackContentWidget::dragEnterEvent( QDragEnterEvent * dee ) { MidiTime tcoPos = getPosition( dee->pos().x() ); - if( canPasteSelection( tcoPos, dee ) == false ) + if( canPasteSelection( tcoPos, dee ) == false ) { dee->ignore(); } @@ -1401,9 +1695,19 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QDropEvent* d { const QMimeData * mimeData = de->mimeData(); + // If the source of the DropEvent is the current instance of LMMS we don't allow pasting in the same bar + // if it's another instance of LMMS we allow it + return de->source() + ? canPasteSelection( tcoPos, mimeData ) + : canPasteSelection( tcoPos, mimeData, true ); +} + +// Overloaded method to make it possible to call this method without a Drag&Drop event +bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData* md , bool allowSameBar ) +{ Track * t = getTrack(); - QString type = StringPairDrag::decodeMimeKey( mimeData ); - QString value = StringPairDrag::decodeMimeValue( mimeData ); + QString type = StringPairDrag::decodeMimeKey( md ); + QString value = StringPairDrag::decodeMimeValue( md ); // We can only paste into tracks of the same type if( type != ( "tco_" + QString::number( t->type() ) ) || @@ -1419,7 +1723,7 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QDropEvent* d QDomElement metadata = dataFile.content().firstChildElement( "copyMetadata" ); QDomAttr tcoPosAttr = metadata.attributeNode( "grabbedTCOPos" ); MidiTime grabbedTCOPos = tcoPosAttr.value().toInt(); - MidiTime grabbedTCOTact = MidiTime( grabbedTCOPos.getTact(), 0 ); + MidiTime grabbedTCOBar = MidiTime( grabbedTCOPos.getBar(), 0 ); // Extract the track index that was originally clicked QDomAttr tiAttr = metadata.attributeNode( "initialTrackIndex" ); @@ -1429,10 +1733,10 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QDropEvent* d const TrackContainer::TrackList tracks = t->trackContainer()->tracks(); const int currentTrackIndex = tracks.indexOf( t ); - // Don't paste if we're on the same tact + // Don't paste if we're on the same bar and allowSameBar is false auto sourceTrackContainerId = metadata.attributeNode( "trackContainerId" ).value().toUInt(); - if( de->source() && sourceTrackContainerId == t->trackContainer()->id() && - tcoPos == grabbedTCOTact && currentTrackIndex == initialTrackIndex ) + if( !allowSameBar && sourceTrackContainerId == t->trackContainer()->id() && + tcoPos == grabbedTCOBar && currentTrackIndex == initialTrackIndex ) { return false; } @@ -1473,13 +1777,28 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QDropEvent* d */ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) { + const QMimeData * mimeData = de->mimeData(); + if( canPasteSelection( tcoPos, de ) == false ) { return false; } - QString type = StringPairDrag::decodeKey( de ); - QString value = StringPairDrag::decodeValue( de ); + // We set skipSafetyCheck to true because we already called canPasteSelection + return pasteSelection( tcoPos, mimeData, true ); +} + +// Overloaded method so we can call it without a Drag&Drop event +bool TrackContentWidget::pasteSelection( MidiTime tcoPos, const QMimeData * md, bool skipSafetyCheck ) +{ + // When canPasteSelection was already called before, skipSafetyCheck will skip this + if( !skipSafetyCheck && canPasteSelection( tcoPos, md ) == false ) + { + return false; + } + + QString type = StringPairDrag::decodeMimeKey( md ); + QString value = StringPairDrag::decodeMimeValue( md ); getTrack()->addJournalCheckPoint(); @@ -1496,9 +1815,8 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) int initialTrackIndex = tiAttr.value().toInt(); QDomAttr tcoPosAttr = metadata.attributeNode( "grabbedTCOPos" ); MidiTime grabbedTCOPos = tcoPosAttr.value().toInt(); - MidiTime grabbedTCOTact = MidiTime( grabbedTCOPos.getTact(), 0 ); - // Snap the mouse position to the beginning of the dropped tact, in ticks + // Snap the mouse position to the beginning of the dropped bar, in ticks const TrackContainer::TrackList tracks = getTrack()->trackContainer()->tracks(); const int currentTrackIndex = tracks.indexOf( getTrack() ); @@ -1517,6 +1835,14 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) // TODO -- Need to draw the hovericon either way, or ghost the TCOs // onto their final position. + float snapSize = gui->songEditor()->m_editor->getSnapSize(); + // All patterns should be offset the same amount as the grabbed pattern + MidiTime offset = MidiTime(tcoPos - grabbedTCOPos); + // Users expect clips to "fall" backwards, so bias the offset + offset = offset - MidiTime::ticksPerBar() * snapSize / 2; + // The offset is quantized (rather than the positions) to preserve fine adjustments + offset = offset.quantize(snapSize); + for( int i = 0; isongEditor()->m_editor->getSnapSize(); + if (offset == 0) { pos += shift; } TrackContentObject * tco = t->createTCO( pos ); tco->restoreState( tcoElement ); @@ -1562,7 +1886,7 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) */ void TrackContentWidget::dropEvent( QDropEvent * de ) { - MidiTime tcoPos = MidiTime( getPosition( de->pos().x() ).getTact(), 0 ); + MidiTime tcoPos = MidiTime( getPosition( de->pos().x() ) ); if( pasteSelection( tcoPos, de ) == true ) { de->accept(); @@ -1595,8 +1919,8 @@ void TrackContentWidget::mousePressEvent( QMouseEvent * me ) so.at( i )->setSelected( false); } getTrack()->addJournalCheckPoint(); - const MidiTime pos = getPosition( me->x() ).getTact() * - MidiTime::ticksPerTact(); + const MidiTime pos = getPosition( me->x() ).getBar() * + MidiTime::ticksPerBar(); TrackContentObject * tco = getTrack()->createTCO( pos ); tco->saveJournallingState( false ); @@ -1614,15 +1938,15 @@ void TrackContentWidget::mousePressEvent( QMouseEvent * me ) */ void TrackContentWidget::paintEvent( QPaintEvent * pe ) { - // Assume even-pixels-per-tact. Makes sense, should be like this anyways + // Assume even-pixels-per-bar. Makes sense, should be like this anyways const TrackContainerView * tcv = m_trackView->trackContainerView(); - int ppt = static_cast( tcv->pixelsPerTact() ); + int ppb = static_cast( tcv->pixelsPerBar() ); QPainter p( this ); // Don't draw background on BB-Editor if( m_trackView->trackContainerView() != gui->getBBEditor()->trackContainerView() ) { p.drawTiledPixmap( rect(), m_background, QPoint( - tcv->currentPosition().getTact() * ppt, 0 ) ); + tcv->currentPosition().getBar() * ppb, 0 ) ); } } @@ -1655,17 +1979,54 @@ Track * TrackContentWidget::getTrack() -/*! \brief Return the end position of the trackContentWidget in Tacts. +/*! \brief Return the end position of the trackContentWidget in Bars. * * \param posStart the starting position of the Widget (from getPosition()) */ MidiTime TrackContentWidget::endPosition( const MidiTime & posStart ) { - const float ppt = m_trackView->trackContainerView()->pixelsPerTact(); + const float ppb = m_trackView->trackContainerView()->pixelsPerBar(); const int w = width(); - return posStart + static_cast( w * MidiTime::ticksPerTact() / ppt ); + return posStart + static_cast( w * MidiTime::ticksPerBar() / ppb ); } +void TrackContentWidget::contextMenuEvent( QContextMenuEvent * cme ) +{ + if( cme->modifiers() ) + { + return; + } + + // If we don't have TCO data in the clipboard there's no need to create this menu + // since "paste" is the only action at the moment. + const QMimeData *md = QApplication::clipboard()->mimeData( QClipboard::Clipboard ); + if( !md->hasFormat( StringPairDrag::mimeType() ) ) + { + return; + } + + QMenu contextMenu( this ); + QAction *pasteA = contextMenu.addAction( embed::getIconPixmap( "edit_paste" ), + tr( "Paste" ), [this, cme](){ contextMenuAction( cme, Paste ); } ); + // If we can't paste in the current TCW for some reason, disable the action so the user knows + pasteA->setEnabled( canPasteSelection( getPosition( cme->x() ), md ) ? true : false ); + + contextMenu.exec( QCursor::pos() ); +} + +void TrackContentWidget::contextMenuAction( QContextMenuEvent * cme, ContextMenuAction action ) +{ + switch( action ) + { + case Paste: + // Paste the selection on the MidiTime of the context menu event + const QMimeData *md = QApplication::clipboard()->mimeData( QClipboard::Clipboard ); + MidiTime tcoPos = getPosition( cme->x() ); + + pasteSelection( tcoPos, md ); + break; + } +} @@ -1707,10 +2068,6 @@ void TrackContentWidget::setEmbossColor( const QBrush & c ) // trackOperationsWidget // =========================================================================== - -QPixmap * TrackOperationsWidget::s_grip = NULL; /*!< grip pixmap */ - - /*! \brief Create a new trackOperationsWidget * * The trackOperationsWidget is the grip and the mute button of a track. @@ -1837,17 +2194,11 @@ void TrackOperationsWidget::paintEvent( QPaintEvent * pe ) if( m_trackView->isMovingTrack() == false ) { - s_grip = new QPixmap( embed::getIconPixmap( - "track_op_grip" ) ); - - p.drawPixmap( 2, 2, *s_grip ); + p.drawPixmap( 2, 2, embed::getIconPixmap("track_op_grip")); } else { - s_grip = new QPixmap( embed::getIconPixmap( - "track_op_grip_c" ) ); - - p.drawPixmap( 2, 2, *s_grip ); + p.drawPixmap( 2, 2, embed::getIconPixmap("track_op_grip_c")); } } @@ -2128,6 +2479,8 @@ void Track::saveSettings( QDomDocument & doc, QDomElement & element ) element.setAttribute( "name", name() ); m_mutedModel.saveSettings( doc, element, "muted" ); m_soloModel.saveSettings( doc, element, "solo" ); + // Save the mutedBeforeSolo value so we can recover the muted state if any solo was active (issue 5562) + element.setAttribute( "mutedBeforeSolo", int(m_mutedBeforeSolo) ); if( m_height >= MINIMAL_TRACK_HEIGHT ) { @@ -2182,6 +2535,9 @@ void Track::loadSettings( const QDomElement & element ) m_mutedModel.loadSettings( element, "muted" ); m_soloModel.loadSettings( element, "solo" ); + // Get the mutedBeforeSolo value so we can recover the muted state if any solo was active. + // Older project files that didn't have this attribute will set the value to false (issue 5562) + m_mutedBeforeSolo = QVariant( element.attribute( "mutedBeforeSolo", "0" ) ).toBool(); if( m_simpleSerializingMode ) { @@ -2317,7 +2673,7 @@ TrackContentObject * Track::getTCO( int tcoNum ) } printf( "called Track::getTCO( %d ), " "but TCO %d doesn't exist\n", tcoNum, tcoNum ); - return createTCO( tcoNum * MidiTime::ticksPerTact() ); + return createTCO( tcoNum * MidiTime::ticksPerBar() ); } @@ -2425,17 +2781,17 @@ void Track::createTCOsForBB( int bb ) * in ascending order by TCO time, once we hit a TCO that was earlier * than the insert time, we could fall out of the loop early. */ -void Track::insertTact( const MidiTime & pos ) +void Track::insertBar( const MidiTime & pos ) { // we'll increase the position of every TCO, positioned behind pos, by - // one tact + // one bar for( tcoVector::iterator it = m_trackContentObjects.begin(); it != m_trackContentObjects.end(); ++it ) { if( ( *it )->startPosition() >= pos ) { ( *it )->movePosition( (*it)->startPosition() + - MidiTime::ticksPerTact() ); + MidiTime::ticksPerBar() ); } } } @@ -2447,17 +2803,17 @@ void Track::insertTact( const MidiTime & pos ) * * \param pos The time at which we want to remove the bar. */ -void Track::removeTact( const MidiTime & pos ) +void Track::removeBar( const MidiTime & pos ) { // we'll decrease the position of every TCO, positioned behind pos, by - // one tact + // one bar for( tcoVector::iterator it = m_trackContentObjects.begin(); it != m_trackContentObjects.end(); ++it ) { if( ( *it )->startPosition() >= pos ) { ( *it )->movePosition( qMax( ( *it )->startPosition() - - MidiTime::ticksPerTact(), 0 ) ); + MidiTime::ticksPerBar(), 0 ) ); } } } @@ -2471,7 +2827,7 @@ void Track::removeTact( const MidiTime & pos ) * keeping track of the latest time found in ticks. Then we return * that in bars by dividing by the number of ticks per bar. */ -tact_t Track::length() const +bar_t Track::length() const { // find last end-position tick_t last = 0; @@ -2491,7 +2847,7 @@ tact_t Track::length() const } } - return last / MidiTime::ticksPerTact(); + return last / MidiTime::ticksPerBar(); } @@ -2521,6 +2877,9 @@ void Track::toggleSolo() } const bool solo = m_soloModel.value(); + // Should we use the new behavior of solo or the older/legacy one? + const bool soloLegacyBehavior = ConfigManager::inst()->value("app", "sololegacybehavior", "0").toInt(); + for( TrackContainer::TrackList::const_iterator it = tl.begin(); it != tl.end(); ++it ) { @@ -2531,7 +2890,15 @@ void Track::toggleSolo() { ( *it )->m_mutedBeforeSolo = ( *it )->isMuted(); } - ( *it )->setMuted( *it == this ? false : true ); + // Don't mute AutomationTracks (keep their original state) unless we are on the sololegacybehavior mode + if( *it == this ) + { + ( *it )->setMuted( false ); + } + else if( soloLegacyBehavior || ( *it )->type() != AutomationTrack ) + { + ( *it )->setMuted( true ); + } if( *it != this ) { ( *it )->m_soloModel.setValue( false ); @@ -2539,7 +2906,12 @@ void Track::toggleSolo() } else if( !soloBefore ) { - ( *it )->setMuted( ( *it )->m_mutedBeforeSolo ); + // Unless we are on the sololegacybehavior mode, only restores the + // mute state if the track isn't an Automation Track + if( soloLegacyBehavior || ( *it )->type() != AutomationTrack ) + { + ( *it )->setMuted( ( *it )->m_mutedBeforeSolo ); + } } } } @@ -2610,6 +2982,9 @@ TrackView::TrackView( Track * track, TrackContainerView * tcv ) : connect( &m_track->m_mutedModel, SIGNAL( dataChanged() ), &m_trackContentWidget, SLOT( update() ) ); + connect(&m_track->m_mutedModel, SIGNAL(dataChanged()), + this, SLOT(muteChanged())); + connect( &m_track->m_soloModel, SIGNAL( dataChanged() ), m_track, SLOT( toggleSolo() ), Qt::DirectConnection ); // create views for already existing TCOs @@ -2942,3 +3317,21 @@ void TrackView::createTCOView( TrackContentObject * tco ) } tco->selectViewOnCreate( false ); } + + + + +void TrackView::muteChanged() +{ + FadeButton * indicator = getActivityIndicator(); + if (indicator) { setIndicatorMute(indicator, m_track->m_mutedModel.value()); } +} + + + + +void TrackView::setIndicatorMute(FadeButton* indicator, bool muted) +{ + QPalette::ColorRole role = muted ? QPalette::Highlight : QPalette::BrightText; + indicator->setActiveColor(QApplication::palette().color(QPalette::Active, role)); +} diff --git a/src/core/TrackContainer.cpp b/src/core/TrackContainer.cpp index edea9aa14b7..1aabf279094 100644 --- a/src/core/TrackContainer.cpp +++ b/src/core/TrackContainer.cpp @@ -181,6 +181,9 @@ void TrackContainer::addTrack( Track * _track ) m_tracksMutex.unlock(); _track->unlock(); emit trackAdded( _track ); + + connect( _track, SIGNAL( nameChanged() ), + this, SIGNAL( trackRenamed() ) ); } } @@ -207,6 +210,8 @@ void TrackContainer::removeTrack( Track * _track ) { Engine::getSong()->setModified(); } + + emit trackRemoved(); } } @@ -313,7 +318,7 @@ AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tra MidiTime bbTime = time - tco->startPosition(); bbTime = std::min(bbTime, tco->length()); - bbTime = bbTime % (bbContainer->lengthOfBB(bbIndex) * MidiTime::ticksPerTact()); + bbTime = bbTime % (bbContainer->lengthOfBB(bbIndex) * MidiTime::ticksPerBar()); auto bbValues = bbContainer->automatedValuesAt(bbTime, bbIndex); for (auto it=bbValues.begin(); it != bbValues.end(); it++) @@ -344,8 +349,3 @@ DummyTrackContainer::DummyTrackContainer() : m_dummyInstrumentTrack->setJournalling( false ); } - - - - - diff --git a/src/core/VstSyncController.cpp b/src/core/VstSyncController.cpp index dd9660cb595..c09ce946b45 100644 --- a/src/core/VstSyncController.cpp +++ b/src/core/VstSyncController.cpp @@ -42,45 +42,14 @@ VstSyncController::VstSyncController() : - m_syncData( NULL ), - m_shmID( -1 ), - m_shm( "/usr/bin/lmms" ) + m_syncData( NULL ) { if( ConfigManager::inst()->value( "ui", "syncvstplugins" ).toInt() ) { connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSampleRate() ) ); -#ifdef USE_QT_SHMEM - if ( m_shm.create( sizeof( VstSyncData ) ) ) - { - m_syncData = (VstSyncData*) m_shm.data(); - } - else - { - qWarning() << QString( "Failed to allocate shared memory for VST sync: %1" ).arg( m_shm.errorString() ); - } -#else - key_t key; // make the key: - if( ( key = ftok( VST_SNC_SHM_KEY_FILE, 'R' ) ) == -1 ) - { - qWarning( "VstSyncController: ftok() failed" ); - } - else - { // connect to shared memory segment - if( ( m_shmID = shmget( key, sizeof( VstSyncData ), 0644 | IPC_CREAT ) ) == -1 ) - { - qWarning( "VstSyncController: shmget() failed" ); - } - else - { // attach segment - m_syncData = (VstSyncData *)shmat( m_shmID, 0, 0 ); - if( m_syncData == (VstSyncData *)( -1 ) ) - { - qWarning( "VstSyncController: shmat() failed" ); - } - } - } -#endif + key_t key = 0; + m_syncData = (VstSyncData*)createShmWithFreeKey(m_shm, sizeof(VstSyncData), key); } else { @@ -113,25 +82,6 @@ VstSyncController::~VstSyncController() { delete m_syncData; } - else - { -#ifdef USE_QT_SHMEM - if( m_shm.data() ) - { - // detach shared memory, delete it: - m_shm.detach(); - } -#else - if( shmdt( m_syncData ) != -1 ) - { - shmctl( m_shmID, IPC_RMID, NULL ); - } - else - { - qWarning( "VstSyncController: shmdt() failed" ); - } -#endif - } } diff --git a/src/core/audio/AudioDevice.cpp b/src/core/audio/AudioDevice.cpp index ab69e144b12..f794602299b 100644 --- a/src/core/audio/AudioDevice.cpp +++ b/src/core/audio/AudioDevice.cpp @@ -93,10 +93,8 @@ fpp_t AudioDevice::getNextBuffer( surroundSampleFrame * _ab ) // resample if necessary if( mixer()->processingSampleRate() != m_sampleRate ) { - resample( b, frames, _ab, mixer()->processingSampleRate(), - m_sampleRate ); - frames = frames * m_sampleRate / - mixer()->processingSampleRate(); + frames = resample( b, frames, _ab, mixer()->processingSampleRate(), + m_sampleRate ); } else { @@ -184,7 +182,7 @@ void AudioDevice::renamePort( AudioPort * ) -void AudioDevice::resample( const surroundSampleFrame * _src, +fpp_t AudioDevice::resample( const surroundSampleFrame * _src, const fpp_t _frames, surroundSampleFrame * _dst, const sample_rate_t _src_sr, @@ -192,7 +190,7 @@ void AudioDevice::resample( const surroundSampleFrame * _src, { if( m_srcState == NULL ) { - return; + return _frames; } m_srcData.input_frames = _frames; m_srcData.output_frames = _frames; @@ -206,6 +204,7 @@ void AudioDevice::resample( const surroundSampleFrame * _src, printf( "AudioDevice::resample(): error while resampling: %s\n", src_strerror( error ) ); } + return static_cast(m_srcData.output_frames_gen); } diff --git a/src/core/audio/AudioFileFlac.cpp b/src/core/audio/AudioFileFlac.cpp index d9d91f54bea..cb159e46d5e 100644 --- a/src/core/audio/AudioFileFlac.cpp +++ b/src/core/audio/AudioFileFlac.cpp @@ -22,6 +22,9 @@ * */ +#include + +#include #include #include "AudioFileFlac.h" @@ -86,6 +89,7 @@ bool AudioFileFlac::startEncoding() void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const frames, float master_gain) { OutputSettings::BitDepth depth = getOutputSettings().getBitDepth(); + float clipvalue = std::nextafterf( -1.0f, 0.0f ); if (depth == OutputSettings::Depth_24Bit || depth == OutputSettings::Depth_32Bit) // Float encoding { @@ -94,7 +98,10 @@ void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const fram { for(ch_cnt_t channel=0; channel(buf.get()),frames); diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index e149f5cbd96..44ecafa23a0 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -55,6 +55,8 @@ AudioJack::AudioJack( bool & _success_ful, Mixer* _mixer ) : m_framesDoneInCurBuf( 0 ), m_framesToDoInCurBuf( 0 ) { + m_stopped = true; + _success_ful = initJackClient(); if( _success_ful ) { @@ -200,8 +202,6 @@ bool AudioJack::initJackClient() void AudioJack::startProcessing() { - m_stopped = false; - if( m_active || m_client == NULL ) { return; @@ -244,6 +244,7 @@ void AudioJack::startProcessing() } } + m_stopped = false; free( ports ); } @@ -344,8 +345,8 @@ int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata ) // add to the following sound processing if( m_midiClient && _nframes > 0 ) { - m_midiClient->JackMidiRead(_nframes); - m_midiClient->JackMidiWrite(_nframes); + m_midiClient.load()->JackMidiRead(_nframes); + m_midiClient.load()->JackMidiWrite(_nframes); } for( int c = 0; c < channels(); ++c ) @@ -454,7 +455,7 @@ AudioJack::setupWidget::setupWidget( QWidget * _parent ) : m_clientName = new QLineEdit( cn, this ); m_clientName->setGeometry( 10, 20, 160, 20 ); - QLabel * cn_lbl = new QLabel( tr( "CLIENT-NAME" ), this ); + QLabel * cn_lbl = new QLabel( tr( "Client name" ), this ); cn_lbl->setFont( pointSize<7>( cn_lbl->font() ) ); cn_lbl->setGeometry( 10, 40, 160, 10 ); @@ -466,7 +467,7 @@ AudioJack::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setLabel( tr( "Channels" ) ); m_channels->move( 180, 20 ); } diff --git a/src/core/audio/AudioOss.cpp b/src/core/audio/AudioOss.cpp index c9ad01801b2..cbf9278a794 100644 --- a/src/core/audio/AudioOss.cpp +++ b/src/core/audio/AudioOss.cpp @@ -59,7 +59,7 @@ #ifndef _PATH_DEV_DSP -#ifdef __OpenBSD__ +#if defined(__NetBSD__) || defined(__OpenBSD__) #define _PATH_DEV_DSP "/dev/audio" #else #define _PATH_DEV_DSP "/dev/dsp" @@ -327,7 +327,7 @@ AudioOss::setupWidget::setupWidget( QWidget * _parent ) : m_device = new QLineEdit( probeDevice(), this ); m_device->setGeometry( 10, 20, 160, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); dev_lbl->setGeometry( 10, 40, 160, 10 ); @@ -339,7 +339,7 @@ AudioOss::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setLabel( tr( "Channels" ) ); m_channels->move( 180, 20 ); } diff --git a/src/core/audio/AudioPortAudio.cpp b/src/core/audio/AudioPortAudio.cpp index 61dca4a2271..865eeca8d5a 100644 --- a/src/core/audio/AudioPortAudio.cpp +++ b/src/core/audio/AudioPortAudio.cpp @@ -410,16 +410,16 @@ AudioPortAudio::setupWidget::setupWidget( QWidget * _parent ) : AudioDeviceSetupWidget( AudioPortAudio::name(), _parent ) { m_backend = new ComboBox( this, "BACKEND" ); - m_backend->setGeometry( 64, 15, 260, 20 ); + m_backend->setGeometry( 64, 15, 260, ComboBox::DEFAULT_HEIGHT ); - QLabel * backend_lbl = new QLabel( tr( "BACKEND" ), this ); + QLabel * backend_lbl = new QLabel( tr( "Backend" ), this ); backend_lbl->setFont( pointSize<7>( backend_lbl->font() ) ); backend_lbl->move( 8, 18 ); m_device = new ComboBox( this, "DEVICE" ); - m_device->setGeometry( 64, 35, 260, 20 ); + m_device->setGeometry( 64, 35, 260, ComboBox::DEFAULT_HEIGHT ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); dev_lbl->move( 8, 38 ); @@ -431,7 +431,7 @@ AudioPortAudio::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setLabel( tr( "Channels" ) ); m_channels->move( 308, 20 );*/ connect( &m_setupUtil.m_backendModel, SIGNAL( dataChanged() ), diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index 050086c603e..af14960a700 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -139,7 +139,7 @@ static void stream_state_callback( pa_stream *s, void * userdata ) case PA_STREAM_FAILED: default: - qCritical( "Stream errror: %s\n", + qCritical( "Stream error: %s\n", pa_strerror(pa_context_errno( pa_stream_get_context( s ) ) ) ); } @@ -314,7 +314,7 @@ AudioPulseAudio::setupWidget::setupWidget( QWidget * _parent ) : m_device = new QLineEdit( AudioPulseAudio::probeDevice(), this ); m_device->setGeometry( 10, 20, 160, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); dev_lbl->setGeometry( 10, 40, 160, 10 ); @@ -326,7 +326,7 @@ AudioPulseAudio::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setLabel( tr( "Channels" ) ); m_channels->move( 180, 20 ); } diff --git a/src/core/audio/AudioSdl.cpp b/src/core/audio/AudioSdl.cpp index 42adb9b33c9..b970ba6307f 100644 --- a/src/core/audio/AudioSdl.cpp +++ b/src/core/audio/AudioSdl.cpp @@ -325,7 +325,7 @@ AudioSdl::setupWidget::setupWidget( QWidget * _parent ) : m_device = new QLineEdit( dev, this ); m_device->setGeometry( 10, 20, 160, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); dev_lbl->setGeometry( 10, 40, 160, 10 ); diff --git a/src/core/audio/AudioSndio.cpp b/src/core/audio/AudioSndio.cpp index 853d734d5e2..24bef924652 100644 --- a/src/core/audio/AudioSndio.cpp +++ b/src/core/audio/AudioSndio.cpp @@ -193,7 +193,7 @@ AudioSndio::setupWidget::setupWidget( QWidget * _parent ) : m_device = new QLineEdit( "", this ); m_device->setGeometry( 10, 20, 160, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) ); dev_lbl->setGeometry( 10, 40, 160, 10 ); @@ -205,7 +205,7 @@ AudioSndio::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setLabel( tr( "Channels" ) ); m_channels->move( 180, 20 ); } diff --git a/src/core/audio/AudioSoundIo.cpp b/src/core/audio/AudioSoundIo.cpp index cde14a1c5a3..2c3d493a6de 100644 --- a/src/core/audio/AudioSoundIo.cpp +++ b/src/core/audio/AudioSoundIo.cpp @@ -426,14 +426,14 @@ AudioSoundIo::setupWidget::setupWidget( QWidget * _parent ) : m_backend = new ComboBox( this, "BACKEND" ); m_backend->setGeometry( 64, 15, 260, 20 ); - QLabel * backend_lbl = new QLabel( tr( "BACKEND" ), this ); + QLabel * backend_lbl = new QLabel( tr( "Backend" ), this ); backend_lbl->setFont( pointSize<7>( backend_lbl->font() ) ); backend_lbl->move( 8, 18 ); m_device = new ComboBox( this, "DEVICE" ); m_device->setGeometry( 64, 35, 260, 20 ); - QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); dev_lbl->move( 8, 38 ); diff --git a/src/core/fft_helpers.cpp b/src/core/fft_helpers.cpp index a17ebf719a6..0dcf77e3a90 100644 --- a/src/core/fft_helpers.cpp +++ b/src/core/fft_helpers.cpp @@ -2,6 +2,7 @@ * fft_helpers.cpp - some functions around FFT analysis * * Copyright (c) 2008-2012 Tobias Doerffel + * Copyright (c) 2019 Martin Pavelek * * This file is part of LMMS - https://lmms.io * @@ -28,216 +29,186 @@ #include #include "lmms_constants.h" -/* returns biggest value from abs_spectrum[spec_size] array - - returns -1 on error -*/ -float maximum(float *abs_spectrum, unsigned int spec_size) +/* Returns biggest value from abs_spectrum[spec_size] array. + * + * return -1 on error, otherwise the maximum value + */ +float maximum(const float *abs_spectrum, unsigned int spec_size) { - float maxi=0; - unsigned int i; + if (abs_spectrum == NULL) {return -1;} + if (spec_size == 0) {return -1;} - if ( abs_spectrum==NULL ) - return -1; + float maxi = 0; - if (spec_size<=0) - return -1; - - for ( i=0; imaxi ) - maxi=abs_spectrum[i]; + if (abs_spectrum[i] > maxi) {maxi = abs_spectrum[i];} } - return maxi; } - -/* apply hanning or hamming window to channel - - returns -1 on error */ -int hanming(float *timebuffer, int length, WINDOWS type) +float maximum(const std::vector &abs_spectrum) { - int i; - float alpha; + return maximum(abs_spectrum.data(), abs_spectrum.size()); +} - if ( (timebuffer==NULL)||(length<=0) ) - return -1; - switch (type) - { - case HAMMING: alpha=0.54; break; - case HANNING: - default: alpha=0.5; break; - } +/* Normalize the array of absolute magnitudes to a 0..1 range. + * Block size refers to FFT block size before any zero padding. + * + * return -1 on error, 0 on success + */ +int normalize(const float *abs_spectrum, float *norm_spectrum, unsigned int bin_count, unsigned int block_size) +{ + if (abs_spectrum == NULL || norm_spectrum == NULL) {return -1;} + if (bin_count == 0 || block_size == 0) {return -1;} - for ( i=0; i &abs_spectrum, std::vector &norm_spectrum, unsigned int block_size) { - int i; + if (abs_spectrum.size() != norm_spectrum.size()) {return -1;} - if ( (complex_buffer==NULL)||(absspec_buffer==NULL) ) - return -1; - if ( compl_length<=0 ) - return -1; + return normalize(abs_spectrum.data(), norm_spectrum.data(), abs_spectrum.size(), block_size); +} - for (i=0; i &spectrum) +{ + for (float s : spectrum) { - absspec_buffer[i]=(float )sqrt(complex_buffer[i][0]*complex_buffer[i][0] + complex_buffer[i][1]*complex_buffer[i][1]); + if (s != 0) {return 1;} } - return 0; } -/* build fewer subbands from many absolute spectrum values - take care that - compressedbands[] array num_new elements long - - num_old > num_new - - returns 0 on success, else -1 */ -int compressbands(float *absspec_buffer, float *compressedband, int num_old, int num_new, int bottom, int top) +/* Precompute an FFT window function for later real-time use. + * + * return -1 on error + */ +int precomputeWindow(float *window, unsigned int length, FFT_WINDOWS type, bool normalized) { - float ratio; - int i, usefromold; - float j; - float j_min, j_max; - - if ( (absspec_buffer==NULL)||(compressedband==NULL) ) - return -1; + if (window == NULL) {return -1;} - if ( num_old=num_old ) - top=num_old-1; - - usefromold=num_old-(num_old-top)-bottom; - - ratio=(float)usefromold/(float)num_new; - - // for each new subband - for ( i=0; i num_new + * + * return 0 on success, else -1 + */ +int compressbands(const float *absspec_buffer, float *compressedband, int num_old, int num_new, int bottom, int top) +{ + if (absspec_buffer == NULL || compressedband == NULL) {return -1;} + if (num_old < num_new) {return -1;} + if (num_old <= 0 || num_new <= 0) {return -1;} + if (bottom < 0) {bottom = 0;} + if (top >= num_old) {top = num_old - 1;} - bandwidth=(pow(2, 1.0/3.0)-1)*frequency; + int usefromold = num_old - (num_old - top) - bottom; - f_min=frequency-bandwidth/2.0; - f_max=frequency+bandwidth/2.0; + float ratio = (float)usefromold / (float)num_new; - j_min=(int)(f_min/max_frequency*(float)num_spec); + // for each new subband + for (int i = 0; i < num_new; i++) + { + compressedband[i] = 0; - j_max=(int)(f_max/max_frequency*(float)num_spec); + float j_min = (i * ratio) + bottom; + if (j_min < 0) {j_min = bottom;} - if ( (j_min<0)||(j_max<0) ) - { - fprintf(stderr, "Error: calc13octaveband31() in fft_helpers.cpp line %d failed.\n", __LINE__); - return -1; - } + float j_max = j_min + ratio; - for ( j=j_min; j<=j_max; j++ ) + for (float j = (int)j_min; j <= j_max; j++) { - if( j_max + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Lv2Basics.h" + +#ifdef LMMS_HAVE_LV2 + +QString qStringFromPluginNode(const LilvPlugin* plug, + LilvNode* (*getFunc)(const LilvPlugin*)) +{ + return QString::fromUtf8( + lilv_node_as_string(AutoLilvNode((*getFunc)(plug)).get())); +} + +QString qStringFromPortName(const LilvPlugin* plug, const LilvPort* port) +{ + return QString::fromUtf8( + lilv_node_as_string(AutoLilvNode(lilv_port_get_name(plug, port)).get())); +} + +std::string stdStringFromPortName(const LilvPlugin* plug, const LilvPort* port) +{ + return std::string( + lilv_node_as_string(AutoLilvNode(lilv_port_get_name(plug, port)).get())); +} + +#endif // LMMS_HAVE_LV2 + diff --git a/src/core/lv2/Lv2ControlBase.cpp b/src/core/lv2/Lv2ControlBase.cpp new file mode 100644 index 00000000000..3f50325e7d2 --- /dev/null +++ b/src/core/lv2/Lv2ControlBase.cpp @@ -0,0 +1,191 @@ +/* + * Lv2ControlBase.cpp - Lv2 control base class + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Lv2ControlBase.h" + +#ifdef LMMS_HAVE_LV2 + +#include + +#include "Engine.h" +#include "Lv2Manager.h" +#include "Lv2Proc.h" +#include "stdshims.h" + + + + +Plugin::PluginTypes Lv2ControlBase::check(const LilvPlugin *plugin, + std::vector &issues, bool printIssues) +{ + // for some reason, all checks can be done by one processor... + return Lv2Proc::check(plugin, issues, printIssues); +} + + + + +Lv2ControlBase::Lv2ControlBase(Model* that, const QString &uri) : + m_plugin(Engine::getLv2Manager()->getPlugin(uri)) +{ + if (m_plugin) + { + int channelsLeft = DEFAULT_CHANNELS; // LMMS plugins are stereo + while (channelsLeft > 0) + { + std::unique_ptr newOne = make_unique(m_plugin, that); + if (newOne->isValid()) + { + channelsLeft -= std::max( + 1 + static_cast(newOne->inPorts().m_right), + 1 + static_cast(newOne->outPorts().m_right)); + Q_ASSERT(channelsLeft >= 0); + m_procs.push_back(std::move(newOne)); + } + else + { + qCritical() << "Failed instantiating LV2 processor"; + m_valid = false; + channelsLeft = 0; + } + } + if (m_valid) + { + m_channelsPerProc = DEFAULT_CHANNELS / m_procs.size(); + linkAllModels(); + } + } + else + { + qCritical() << "No Lv2 plugin found for URI" << uri; + m_valid = false; + } +} + + + + +Lv2ControlBase::~Lv2ControlBase() {} + + + + +LinkedModelGroup *Lv2ControlBase::getGroup(std::size_t idx) +{ + return (m_procs.size() > idx) ? m_procs[idx].get() : nullptr; +} + + + + +const LinkedModelGroup *Lv2ControlBase::getGroup(std::size_t idx) const +{ + return (m_procs.size() > idx) ? m_procs[idx].get() : nullptr; +} + + + + +void Lv2ControlBase::copyModelsFromLmms() { + for (auto& c : m_procs) { c->copyModelsFromCore(); } +} + + + + +void Lv2ControlBase::copyBuffersFromLmms(const sampleFrame *buf, fpp_t frames) { + unsigned firstChan = 0; // tell the procs which channels they shall read from + for (auto& c : m_procs) { + c->copyBuffersFromCore(buf, firstChan, m_channelsPerProc, frames); + firstChan += m_channelsPerProc; + } +} + + + + +void Lv2ControlBase::copyBuffersToLmms(sampleFrame *buf, fpp_t frames) const { + unsigned firstChan = 0; // tell the procs which channels they shall write to + for (const auto& c : m_procs) { + c->copyBuffersToCore(buf, firstChan, m_channelsPerProc, frames); + firstChan += m_channelsPerProc; + } +} + + + + +void Lv2ControlBase::run(fpp_t frames) { + for (auto& c : m_procs) { c->run(frames); } +} + + + + +void Lv2ControlBase::saveSettings(QDomDocument &doc, QDomElement &that) +{ + LinkedModelGroups::saveSettings(doc, that); + + // TODO: save state if supported by plugin +} + + + + +void Lv2ControlBase::loadSettings(const QDomElement &that) +{ + LinkedModelGroups::loadSettings(that); + + // TODO: load state if supported by plugin +} + + + + +void Lv2ControlBase::loadFile(const QString &file) +{ + (void)file; +} + + + + +void Lv2ControlBase::reloadPlugin() +{ + // TODO +} + + + + +std::size_t Lv2ControlBase::controlCount() const { + std::size_t res = 0; + for (const auto& c : m_procs) { res += c->controlCount(); } + return res; +} + + + + +#endif // LMMS_HAVE_LV2 diff --git a/src/core/lv2/Lv2Features.cpp b/src/core/lv2/Lv2Features.cpp new file mode 100644 index 00000000000..fe668807e06 --- /dev/null +++ b/src/core/lv2/Lv2Features.cpp @@ -0,0 +1,97 @@ +/* + * Lv2Features.cpp - Lv2Features implementation + * + * Copyright (c) 2020-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Lv2Features.h" + +#ifdef LMMS_HAVE_LV2 + +#include + +#include "Engine.h" +#include "Lv2Manager.h" + + +bool Lv2Features::isFeatureSupported(const char* featName) +{ + return Engine::getLv2Manager()->isFeatureSupported(featName); +} + + + + +Lv2Features::Lv2Features() +{ + const Lv2Manager* man = Engine::getLv2Manager(); + // create (yet empty) map feature URI -> feature + for(const char* uri : man->supportedFeatureURIs()) + { + m_featureByUri.emplace(uri, nullptr); + } +} + + + + +void Lv2Features::initCommon() +{ + Lv2Manager* man = Engine::getLv2Manager(); + // init m_featureByUri with the plugin-common features + operator[](LV2_URID__map) = man->uridMap().mapFeature(); + operator[](LV2_URID__unmap) = man->uridMap().unmapFeature(); +} + + + + +void Lv2Features::createFeatureVectors() +{ + // create vector of features + for(std::pair& pr : m_featureByUri) + { + Q_ASSERT(pr.second != nullptr); + m_features.push_back(LV2_Feature { pr.first, pr.second }); + } + + // create pointer vector (for lilv_plugin_instantiate) + m_featurePointers.reserve(m_features.size() + 1); + for(std::size_t i = 0; i < m_features.size(); ++i) + { + m_featurePointers.push_back(&m_features[i]); + } + m_featurePointers.push_back(nullptr); +} + + + + +void *&Lv2Features::operator[](const char *featName) +{ + auto itr = m_featureByUri.find(featName); + Q_ASSERT(itr != m_featureByUri.end()); + return itr->second; +} + + +#endif // LMMS_HAVE_LV2 + diff --git a/src/core/lv2/Lv2Manager.cpp b/src/core/lv2/Lv2Manager.cpp new file mode 100644 index 00000000000..69fbd0137c5 --- /dev/null +++ b/src/core/lv2/Lv2Manager.cpp @@ -0,0 +1,183 @@ +/* + * Lv2Manager.cpp - Implementation of Lv2Manager class + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Lv2Manager.h" + +#ifdef LMMS_HAVE_LV2 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ConfigManager.h" +#include "Plugin.h" +#include "PluginFactory.h" +#include "Lv2ControlBase.h" +#include "PluginIssue.h" + + + + +Lv2Manager::Lv2Manager() +{ + const char* dbgStr = getenv("LMMS_LV2_DEBUG"); + m_debug = (dbgStr && *dbgStr); + + m_world = lilv_world_new(); + lilv_world_load_all(m_world); + + m_supportedFeatureURIs.insert(LV2_URID__map); + m_supportedFeatureURIs.insert(LV2_URID__unmap); +} + + + + +Lv2Manager::~Lv2Manager() +{ + lilv_world_free(m_world); +} + + + + +AutoLilvNode Lv2Manager::uri(const char *uriStr) +{ + return AutoLilvNode(lilv_new_uri(m_world, uriStr)); +} + + + + +const LilvPlugin *Lv2Manager::getPlugin(const std::string &uri) +{ + auto itr = m_lv2InfoMap.find(uri); + return itr == m_lv2InfoMap.end() ? nullptr : itr->second.plugin(); +} + + + + +const LilvPlugin *Lv2Manager::getPlugin(const QString &uri) +{ + return getPlugin(uri.toStdString()); +} + + + + +void Lv2Manager::initPlugins() +{ + const LilvPlugins* plugins = lilv_world_get_all_plugins(m_world); + std::size_t pluginCount = 0, pluginsLoaded = 0; + QElapsedTimer timer; + timer.start(); + + LILV_FOREACH(plugins, itr, plugins) + { + const LilvPlugin* curPlug = lilv_plugins_get(plugins, itr); + + std::vector issues; + Plugin::PluginTypes type = Lv2ControlBase::check(curPlug, issues, m_debug); + Lv2Info info(curPlug, type, issues.empty()); + + m_lv2InfoMap[lilv_node_as_uri(lilv_plugin_get_uri(curPlug))] + = std::move(info); + if(issues.empty()) { ++pluginsLoaded; } + ++pluginCount; + } + + qDebug() << "Lv2 plugin SUMMARY:" + << pluginsLoaded << "of" << pluginCount << " loaded in" + << timer.elapsed() << "msecs."; + if(pluginsLoaded != pluginCount) + { + if (m_debug) + { + qDebug() << + "If you don't want to see all this debug output, please set\n" + " environment variable \"LMMS_LV2_DEBUG\" to empty or\n" + " do not set it."; + } + else + { + qDebug() << + "For details about not loaded plugins, please set\n" + " environment variable \"LMMS_LV2_DEBUG\" to nonempty."; + } + } +} + + + + +bool Lv2Manager::CmpStr::operator()(const char *a, const char *b) const +{ + return std::strcmp(a, b) < 0; +} + + + + +bool Lv2Manager::isFeatureSupported(const char *featName) const +{ + return m_supportedFeatureURIs.find(featName) != m_supportedFeatureURIs.end(); +} + + + + +// unused + untested yet +bool Lv2Manager::isSubclassOf(const LilvPluginClass* clvss, const char* uriStr) +{ + const LilvPluginClasses* allClasses = lilv_world_get_plugin_classes(m_world); + const LilvPluginClass* root = lilv_world_get_plugin_class(m_world); + const LilvPluginClass* search = lilv_plugin_classes_get_by_uri(allClasses, + uri(uriStr).get()); + + auto clssEq = [](const LilvPluginClass* pc1, + const LilvPluginClass* pc2) -> bool + { + return lilv_node_equals( + lilv_plugin_class_get_uri(pc1), + lilv_plugin_class_get_uri(pc2)); + }; + bool isFound = false; + while (!(isFound = clssEq(clvss, search)) && !clssEq(clvss, root)) + { + clvss = lilv_plugin_classes_get_by_uri(allClasses, + lilv_plugin_class_get_parent_uri(clvss)); + } + return isFound; +} + + + + +#endif // LMMS_HAVE_LV2 diff --git a/src/core/lv2/Lv2Ports.cpp b/src/core/lv2/Lv2Ports.cpp new file mode 100644 index 00000000000..ae2d26d4971 --- /dev/null +++ b/src/core/lv2/Lv2Ports.cpp @@ -0,0 +1,256 @@ +/* + * Lv2Ports.cpp - Lv2 port classes implementation + * + * Copyright (c) 2019-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#include "Lv2Ports.h" + +#ifdef LMMS_HAVE_LV2 + +#include "Engine.h" +#include "Lv2Basics.h" +#include "Lv2Manager.h" + +namespace Lv2Ports { + + + + +const char *toStr(Flow pf) +{ + switch(pf) + { + case Flow::Unknown: return "unknown"; + case Flow::Input: return "input"; + case Flow::Output: return "output"; + } + return ""; +} + + + + +const char *toStr(Type pt) +{ + switch(pt) + { + case Type::Unknown: return "unknown"; + case Type::Control: return "control"; + case Type::Audio: return "audio"; + case Type::Event: return "event"; + case Type::Cv: return "cv"; + } + return ""; +} + + + + +const char *toStr(Vis pv) +{ + switch(pv) + { + case Vis::Toggled: return "toggled"; + case Vis::Enumeration: return "enumeration"; + case Vis::Integer: return "integer"; + case Vis::None: return "none"; + } + return ""; +} + + + + +std::vector Meta::get(const LilvPlugin *plugin, + std::size_t portNum) +{ + std::vector portIssues; + auto issue = [&portIssues](PluginIssueType i, std::string msg = "") { + portIssues.emplace_back(i, std::move(msg)); }; + + Lv2Manager* man = Engine::getLv2Manager(); + + const LilvPort* lilvPort = lilv_plugin_get_port_by_index( + plugin, static_cast(portNum)); + + auto portFunc = [&plugin, &lilvPort, &man]( + bool (*fptr)(const LilvPlugin*, const LilvPort*, const LilvNode*), + const char* str) { + return fptr(plugin, lilvPort, man->uri(str).get()); + }; + + auto hasProperty = [&portFunc](const char* str) { + return portFunc(lilv_port_has_property, str); }; + auto isA = [&portFunc](const char* str) { + return portFunc(lilv_port_is_a, str); }; + + const std::string portName = stdStringFromPortName(plugin, lilvPort); + + m_optional = hasProperty(LV2_CORE__connectionOptional); + + m_vis = hasProperty(LV2_CORE__integer) + ? Vis::Integer // WARNING: this may still be changed below + : hasProperty(LV2_CORE__enumeration) + ? Vis::Enumeration + : hasProperty(LV2_CORE__toggled) + ? Vis::Toggled + : Vis::None; + + if (isA(LV2_CORE__InputPort)) { m_flow = Flow::Input; } + else if (isA(LV2_CORE__OutputPort)) { m_flow = Flow::Output; } + else { + m_flow = Flow::Unknown; + issue(unknownPortFlow, portName); + } + + m_def = .0f; m_min = .0f; m_max = .0f; + + if (isA(LV2_CORE__ControlPort)) + { + m_type = Type::Control; + + if (m_flow == Flow::Input) + { + bool isToggle = m_vis == Vis::Toggled; + + LilvNode * defN, * minN = nullptr, * maxN = nullptr; + lilv_port_get_range(plugin, lilvPort, &defN, + isToggle ? nullptr : &minN, + isToggle ? nullptr : &maxN); + AutoLilvNode def(defN), min(minN), max(maxN); + + auto takeRangeValue = [&](LilvNode* node, + float& storeHere, PluginIssueType it) + { + if (node) { storeHere = lilv_node_as_float(node); } + else { issue(it, portName); } + }; + + takeRangeValue(def.get(), m_def, portHasNoDef); + if (!isToggle) + { + takeRangeValue(min.get(), m_min, portHasNoMin); + takeRangeValue(max.get(), m_max, portHasNoMax); + + if (m_max - m_min > 15.0f) + { + // range too large for spinbox visualisation, use knobs + // e.g. 0...15 would be OK + m_vis = Vis::None; + } + } + } + } + else if (isA(LV2_CORE__AudioPort)) { m_type = Type::Audio; } + else if (isA(LV2_CORE__CVPort)) { + issue(badPortType, "cvPort"); + m_type = Type::Cv; + } else { + if (m_optional) { m_used = false; } + else { + issue(PluginIssueType::unknownPortType, portName); + m_type = Type::Unknown; + } + } + + return portIssues; +} + + + + +QString PortBase::name() const +{ + AutoLilvNode node(lilv_port_get_name(m_plugin, m_port)); + QString res = lilv_node_as_string(node.get()); + return res; +} + + + + +QString PortBase::uri() const +{ + return lilv_node_as_string(lilv_port_get_symbol(m_plugin, m_port)); +} + + + + +Audio::Audio(std::size_t bufferSize, bool isSidechain, bool isOptional) + : m_buffer(bufferSize), m_sidechain(isSidechain), m_optional(isOptional) +{ +} + + + + +void Audio::copyBuffersFromCore(const sampleFrame *lmmsBuf, + unsigned channel, fpp_t frames) +{ + for (std::size_t f = 0; f < static_cast(frames); ++f) + { + m_buffer[f] = lmmsBuf[f][channel]; + } +} + + + + +void Audio::averageWithBuffersFromCore(const sampleFrame *lmmsBuf, + unsigned channel, fpp_t frames) +{ + for (std::size_t f = 0; f < static_cast(frames); ++f) + { + m_buffer[f] = (m_buffer[f] + lmmsBuf[f][channel]) / 2.0f; + } +} + + + + +void Audio::copyBuffersToCore(sampleFrame *lmmsBuf, + unsigned channel, fpp_t frames) const +{ + for (std::size_t f = 0; f < static_cast(frames); ++f) + { + lmmsBuf[f][channel] = m_buffer[f]; + } +} + + + + +// make the compiler happy, give each class with virtuals +// a function (the destructor here) which is in a cpp file +PortBase::~PortBase() {} +ConstVisitor::~ConstVisitor() {} +Visitor::~Visitor() {} + + + + +} // namespace Lv2Ports + +#endif // LMMS_HAVE_LV2 + diff --git a/src/core/lv2/Lv2Proc.cpp b/src/core/lv2/Lv2Proc.cpp new file mode 100644 index 00000000000..86235f145b2 --- /dev/null +++ b/src/core/lv2/Lv2Proc.cpp @@ -0,0 +1,563 @@ +/* + * Lv2Proc.cpp - Lv2 processor class + * + * Copyright (c) 2019-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Lv2Proc.h" + +#ifdef LMMS_HAVE_LV2 + +#include + +#include "AutomatableModel.h" +#include "ComboBoxModel.h" +#include "Engine.h" +#include "Lv2Features.h" +#include "Lv2Manager.h" +#include "Lv2Ports.h" +#include "Mixer.h" + + + + +Plugin::PluginTypes Lv2Proc::check(const LilvPlugin *plugin, + std::vector& issues, bool printIssues) +{ + unsigned maxPorts = lilv_plugin_get_num_ports(plugin); + enum { inCount, outCount, maxCount }; + unsigned audioChannels[maxCount] = { 0, 0 }; // input and output count + + for (unsigned portNum = 0; portNum < maxPorts; ++portNum) + { + Lv2Ports::Meta meta; + // does all port checks: + std::vector tmp = meta.get(plugin, portNum); + std::move(tmp.begin(), tmp.end(), std::back_inserter(issues)); + + bool portMustBeUsed = + !portIsSideChain(plugin, + lilv_plugin_get_port_by_index(plugin, portNum)) && + !portIsOptional(plugin, + lilv_plugin_get_port_by_index(plugin, portNum)); + if (meta.m_type == Lv2Ports::Type::Audio && portMustBeUsed) + ++audioChannels[meta.m_flow == Lv2Ports::Flow::Output + ? outCount : inCount]; + } + + if (audioChannels[inCount] > 2) + issues.emplace_back(tooManyInputChannels, + std::to_string(audioChannels[inCount])); + if (audioChannels[outCount] == 0) + issues.emplace_back(noOutputChannel); + else if (audioChannels[outCount] > 2) + issues.emplace_back(tooManyOutputChannels, + std::to_string(audioChannels[outCount])); + + AutoLilvNodes reqFeats(lilv_plugin_get_required_features(plugin)); + LILV_FOREACH (nodes, itr, reqFeats.get()) + { + const char* reqFeatName = lilv_node_as_string( + lilv_nodes_get(reqFeats.get(), itr)); + if(!Lv2Features::isFeatureSupported(reqFeatName)) + { + issues.emplace_back(featureNotSupported, reqFeatName); + } + } + + if (printIssues && issues.size()) + { + qDebug() << "Lv2 plugin" + << qStringFromPluginNode(plugin, lilv_plugin_get_name) + << "(URI:" + << lilv_node_as_uri(lilv_plugin_get_uri(plugin)) + << ") can not be loaded:"; + for (const PluginIssue& iss : issues) { qDebug() << " - " << iss; } + } + + return (audioChannels[inCount] > 2 || audioChannels[outCount] > 2) + ? Plugin::Undefined + : (audioChannels[inCount] > 0) + ? Plugin::Effect + : Plugin::Instrument; +} + + + + +Lv2Proc::Lv2Proc(const LilvPlugin *plugin, Model* parent) : + LinkedModelGroup(parent), + m_plugin(plugin) +{ + initPlugin(); +} + + + + +Lv2Proc::~Lv2Proc() { shutdownPlugin(); } + + + + +void Lv2Proc::dumpPorts() +{ + std::size_t num = 0; + for (const std::unique_ptr& port: m_ports) + { + (void)port; + dumpPort(num++); + } +} + + + + +void Lv2Proc::copyModelsFromCore() +{ + struct FloatFromModelVisitor : public ConstModelVisitor + { + const std::vector* m_scalePointMap; // in + float m_res; // out + void visit(const FloatModel& m) override { m_res = m.value(); } + void visit(const IntModel& m) override { + m_res = static_cast(m.value()); } + void visit(const BoolModel& m) override { + m_res = static_cast(m.value()); } + void visit(const ComboBoxModel& m) override { + m_res = (*m_scalePointMap)[static_cast(m.value())]; } + }; + + struct Copy : public Lv2Ports::Visitor + { + void visit(Lv2Ports::Control& ctrl) override + { + if (ctrl.m_flow == Lv2Ports::Flow::Input) + { + FloatFromModelVisitor ffm; + ffm.m_scalePointMap = &ctrl.m_scalePointMap; + ctrl.m_connectedModel->accept(ffm); + ctrl.m_val = ffm.m_res; + } + } + void visit(Lv2Ports::Cv& cv) override + { + if (cv.m_flow == Lv2Ports::Flow::Input) + { + FloatFromModelVisitor ffm; + ffm.m_scalePointMap = &cv.m_scalePointMap; + cv.m_connectedModel->accept(ffm); + // dirty fix, needs better interpolation + std::fill(cv.m_buffer.begin(), cv.m_buffer.end(), ffm.m_res); + } + } + } copy; + + for (const std::unique_ptr& port : m_ports) { + port->accept(copy); } +} + + + + +void Lv2Proc::copyBuffersFromCore(const sampleFrame *buf, + unsigned firstChan, unsigned num, + fpp_t frames) +{ + inPorts().m_left->copyBuffersFromCore(buf, firstChan, frames); + if (num > 1) + { + // if the caller requests to take input from two channels, but we only + // have one input channel... take medium of left and right for + // mono input + // (this happens if we have two outputs and only one input) + if (inPorts().m_right) + { + inPorts().m_right->copyBuffersFromCore(buf, firstChan + 1, frames); + } + else + { + inPorts().m_left->averageWithBuffersFromCore(buf, firstChan + 1, frames); + } + } +} + + + + +void Lv2Proc::copyBuffersToCore(sampleFrame* buf, + unsigned firstChan, unsigned num, + fpp_t frames) const +{ + outPorts().m_left->copyBuffersToCore(buf, firstChan + 0, frames); + if (num > 1) + { + // if the caller requests to copy into two channels, but we only have + // one output channel, duplicate our output + // (this happens if we have two inputs and only one output) + Lv2Ports::Audio* ap = outPorts().m_right + ? outPorts().m_right : outPorts().m_left; + ap->copyBuffersToCore(buf, firstChan + 1, frames); + } +} + + + + +void Lv2Proc::run(fpp_t frames) +{ + lilv_instance_run(m_instance, static_cast(frames)); +} + + + + +AutomatableModel *Lv2Proc::modelAtPort(const QString &uri) +{ + // unused currently + AutomatableModel *mod; + auto itr = m_connectedModels.find(uri.toUtf8().data()); + if (itr != m_connectedModels.end()) { mod = itr->second; } + else { mod = nullptr; } + return mod; +} + + + + +void Lv2Proc::initPlugin() +{ + m_features.initCommon(); + initPluginSpecificFeatures(); + m_features.createFeatureVectors(); + + createPorts(); + + m_instance = lilv_plugin_instantiate(m_plugin, + Engine::mixer()->processingSampleRate(), + m_features.featurePointers()); + + if (m_instance) + { + for (std::size_t portNum = 0; portNum < m_ports.size(); ++portNum) + connectPort(portNum); + lilv_instance_activate(m_instance); + } + else + { + qCritical() << "Failed to create an instance of" + << qStringFromPluginNode(m_plugin, lilv_plugin_get_name) + << "(URI:" + << lilv_node_as_uri(lilv_plugin_get_uri(m_plugin)) + << ")"; + m_valid = false; + } +} + + + + +void Lv2Proc::shutdownPlugin() +{ + lilv_instance_deactivate(m_instance); + lilv_instance_free(m_instance); + m_instance = nullptr; +} + + + + +void Lv2Proc::initPluginSpecificFeatures() +{ + // nothing yet + // it would look like this: + // m_features[LV2_URID__map] = m_uridMapFeature +} + + + + +void Lv2Proc::loadFileInternal(const QString &file) +{ + (void)file; +} + + + + +void Lv2Proc::createPort(std::size_t portNum) +{ + Lv2Ports::Meta meta; + meta.get(m_plugin, portNum); + + const LilvPort* lilvPort = lilv_plugin_get_port_by_index(m_plugin, + static_cast(portNum)); + Lv2Ports::PortBase* port; + if (meta.m_type == Lv2Ports::Type::Control) + { + Lv2Ports::Control* ctrl = new Lv2Ports::Control; + if (meta.m_flow == Lv2Ports::Flow::Input) + { + AutoLilvNode node(lilv_port_get_name(m_plugin, lilvPort)); + QString dispName = lilv_node_as_string(node.get()); + switch (meta.m_vis) + { + case Lv2Ports::Vis::None: + { + // allow ~1000 steps + float stepSize = (meta.m_max - meta.m_min) / 1000.0f; + + // make multiples of 0.01 (or 0.1 for larger values) + float minStep = (stepSize >= 1.0f) ? 0.1f : 0.01f; + stepSize -= fmodf(stepSize, minStep); + stepSize = std::max(stepSize, minStep); + + ctrl->m_connectedModel.reset( + new FloatModel(meta.m_def, meta.m_min, meta.m_max, + stepSize, nullptr, dispName)); + break; + } + case Lv2Ports::Vis::Integer: + ctrl->m_connectedModel.reset( + new IntModel(static_cast(meta.m_def), + static_cast(meta.m_min), + static_cast(meta.m_max), + nullptr, dispName)); + break; + case Lv2Ports::Vis::Enumeration: + { + ComboBoxModel* comboModel + = new ComboBoxModel( + nullptr, dispName); + LilvScalePoints* sps = + lilv_port_get_scale_points(m_plugin, lilvPort); + LILV_FOREACH(scale_points, i, sps) + { + const LilvScalePoint* sp = lilv_scale_points_get(sps, i); + ctrl->m_scalePointMap.push_back(lilv_node_as_float( + lilv_scale_point_get_value(sp))); + comboModel->addItem( + lilv_node_as_string( + lilv_scale_point_get_label(sp))); + } + lilv_scale_points_free(sps); + ctrl->m_connectedModel.reset(comboModel); + break; + } + case Lv2Ports::Vis::Toggled: + ctrl->m_connectedModel.reset( + new BoolModel(static_cast(meta.m_def), + nullptr, dispName)); + break; + } + } + port = ctrl; + } + else if (meta.m_type == Lv2Ports::Type::Audio) + { + Lv2Ports::Audio* audio = + new Lv2Ports::Audio( + static_cast( + Engine::mixer()->framesPerPeriod()), + portIsSideChain(m_plugin, lilvPort), + portIsOptional(m_plugin, lilvPort) + ); + port = audio; + } else { + port = new Lv2Ports::Unknown; + } + + // `meta` is of class `Lv2Ports::Meta` and `port` is of a child class + // we can now assign the `Lv2Ports::Meta` part of meta to ports, leaving + // the additional members of `port` unchanged + *static_cast(port) = meta; + port->m_port = lilvPort; + port->m_plugin = m_plugin; + + m_ports[portNum].reset(port); +} + + + + +void Lv2Proc::createPorts() +{ + // register ports at the processor after creation, + // i.e. link their data or count them + struct RegisterPort : public Lv2Ports::Visitor + { + Lv2Proc* m_proc; + + void visit(Lv2Ports::Control& ctrl) override + { + if (ctrl.m_flow == Lv2Ports::Flow::Input) + { + AutomatableModel* amo = ctrl.m_connectedModel.get(); + m_proc->m_connectedModels.emplace( + lilv_node_as_string(lilv_port_get_symbol( + m_proc->m_plugin, ctrl.m_port)), + amo); + m_proc->addModel(amo, ctrl.uri()); + } + } + + void visit(Lv2Ports::Audio& audio) override + { + if (audio.mustBeUsed()) + { + StereoPortRef dummy; + StereoPortRef* portRef = &dummy; + switch (audio.m_flow) + { + case Lv2Ports::Flow::Input: + portRef = &m_proc->m_inPorts; + break; + case Lv2Ports::Flow::Output: + portRef = &m_proc->m_outPorts; + break; + case Lv2Ports::Flow::Unknown: + break; + } + // in Lv2, leftPort is defined to be the first port + if (!portRef->m_left) { portRef->m_left = &audio; } + else if (!portRef->m_right) { portRef->m_right = &audio; } + } + } + }; + + std::size_t maxPorts = lilv_plugin_get_num_ports(m_plugin); + m_ports.resize(maxPorts); + + for (std::size_t portNum = 0; portNum < maxPorts; ++portNum) + { + createPort(portNum); + RegisterPort registerPort; + registerPort.m_proc = this; + m_ports[portNum]->accept(registerPort); + } + + // initially assign model values to port values + copyModelsFromCore(); + + // debugging: + //dumpPorts(); +} + + + + +struct ConnectPortVisitor : public Lv2Ports::Visitor +{ + std::size_t m_num; + LilvInstance* m_instance; + void connectPort(void* location) { + lilv_instance_connect_port(m_instance, + static_cast(m_num), location); + } + void visit(Lv2Ports::Control& ctrl) override { connectPort(&ctrl.m_val); } + void visit(Lv2Ports::Audio& audio) override + { + connectPort((audio.mustBeUsed()) ? audio.m_buffer.data() : nullptr); + } + void visit(Lv2Ports::Unknown&) override { connectPort(nullptr); } + ~ConnectPortVisitor() override; +}; + +ConnectPortVisitor::~ConnectPortVisitor() {} + +void Lv2Proc::connectPort(std::size_t num) +{ + ConnectPortVisitor connect; + connect.m_num = num; + connect.m_instance = m_instance; + m_ports[num]->accept(connect); +} + + + + +void Lv2Proc::dumpPort(std::size_t num) +{ + struct DumpPortDetail : public Lv2Ports::ConstVisitor + { + void visit(const Lv2Ports::Control& ctrl) override { + qDebug() << " control port"; + // output ports may be uninitialized yet, only print inputs + if (ctrl.m_flow == Lv2Ports::Flow::Input) + { + qDebug() << " value:" << ctrl.m_val; + } + } + void visit(const Lv2Ports::Audio& audio) override { + qDebug() << (audio.isSideChain() ? " audio port (sidechain)" + : " audio port"); + qDebug() << " buffer size:" << audio.bufferSize(); + } + }; + + const Lv2Ports::PortBase& port = *m_ports[num]; + qDebug().nospace() << "port " << num << ":"; + qDebug() << " name:" + << qStringFromPortName(m_plugin, port.m_port); + qDebug() << " flow: " << Lv2Ports::toStr(port.m_flow); + qDebug() << " type: " << Lv2Ports::toStr(port.m_type); + qDebug() << " visualization: " << Lv2Ports::toStr(port.m_vis); + if (port.m_type == Lv2Ports::Type::Control || port.m_type == Lv2Ports::Type::Cv) + { + qDebug() << " default:" << port.m_def; + qDebug() << " min:" << port.m_min; + qDebug() << " max:" << port.m_max; + } + qDebug() << " optional: " << port.m_optional; + qDebug() << " => USED: " << port.m_used; + + DumpPortDetail dumper; + port.accept(dumper); +} + + + + +bool Lv2Proc::portIsSideChain(const LilvPlugin *plugin, const LilvPort *port) +{ + return lilv_port_has_property(plugin, port, + uri(LV2_CORE_PREFIX "isSidechain").get()); +} + + + + +bool Lv2Proc::portIsOptional(const LilvPlugin *plugin, const LilvPort *port) +{ + return lilv_port_has_property(plugin, port, + uri(LV2_CORE__connectionOptional).get()); +} + + + + +AutoLilvNode Lv2Proc::uri(const char *uriStr) +{ + return Engine::getLv2Manager()->uri(uriStr); +} + + +#endif // LMMS_HAVE_LV2 diff --git a/src/core/lv2/Lv2SubPluginFeatures.cpp b/src/core/lv2/Lv2SubPluginFeatures.cpp new file mode 100644 index 00000000000..3f86c5324e2 --- /dev/null +++ b/src/core/lv2/Lv2SubPluginFeatures.cpp @@ -0,0 +1,184 @@ +/* + * Lv2SubPluginFeatures.cpp - derivation from + * Plugin::Descriptor::SubPluginFeatures for + * hosting LV2 plugins + * + * Copyright (c) 2018-2020 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "Lv2SubPluginFeatures.h" + +#ifdef LMMS_HAVE_LV2 + +#include +#include +#include + +#include "Engine.h" +#include "Lv2Basics.h" +#include "Lv2Manager.h" + + +const LilvPlugin *Lv2SubPluginFeatures::getPlugin( + const Plugin::Descriptor::SubPluginFeatures::Key &k) +{ + const LilvPlugin* result = Engine::getLv2Manager()-> + getPlugin(k.attributes["uri"]); + Q_ASSERT(result); + return result; +} + + + + +QString Lv2SubPluginFeatures::pluginName(const LilvPlugin *plug) +{ + return qStringFromPluginNode(plug, lilv_plugin_get_name); +} + + + + +Lv2SubPluginFeatures::Lv2SubPluginFeatures(Plugin::PluginTypes type) : + SubPluginFeatures(type) +{ +} + + + + +void Lv2SubPluginFeatures::fillDescriptionWidget(QWidget *parent, + const Key *k) const +{ + const LilvPlugin *plug = getPlugin(*k); + + QLabel *label = new QLabel(parent); + label->setText(QWidget::tr("Name: ") + pluginName(plug)); + + QLabel *label2 = new QLabel(parent); + label2->setText(QWidget::tr("URI: ") + + lilv_node_as_uri(lilv_plugin_get_uri(plug))); + + QWidget *maker = new QWidget(parent); + QHBoxLayout *l = new QHBoxLayout(maker); + l->setMargin(0); + l->setSpacing(0); + + QLabel *maker_label = new QLabel(maker); + maker_label->setText(QWidget::tr("Maker: ")); + maker_label->setAlignment(Qt::AlignTop); + + QLabel *maker_content = new QLabel(maker); + maker_content->setText( + qStringFromPluginNode(plug, lilv_plugin_get_author_name)); + maker_content->setWordWrap(true); + + l->addWidget(maker_label); + l->addWidget(maker_content, 1); + + QWidget *copyright = new QWidget(parent); + l = new QHBoxLayout(copyright); + l->setMargin(0); + l->setSpacing(0); + copyright->setMinimumWidth(parent->minimumWidth()); + + QLabel *copyright_label = new QLabel(copyright); + copyright_label->setText(QWidget::tr("Copyright: ")); + copyright_label->setAlignment(Qt::AlignTop); + + QLabel *copyright_content = new QLabel(copyright); + copyright_content->setText(""); + copyright_content->setWordWrap(true); + l->addWidget(copyright_label); + l->addWidget(copyright_content, 1); + + AutoLilvNodes extensions(lilv_plugin_get_extension_data(plug)); + (void)extensions; + // possibly TODO: version, project, plugin type, number of channels +} + + + + +QString Lv2SubPluginFeatures::additionalFileExtensions( + const Plugin::Descriptor::SubPluginFeatures::Key &k) const +{ + (void)k; + // lv2 only loads .lv2 files + // maybe add conversions later, e.g. for loading xmz + return QString(); +} + + + + +QString Lv2SubPluginFeatures::displayName( + const Plugin::Descriptor::SubPluginFeatures::Key &k) const +{ + return pluginName(getPlugin(k)); +} + + + + +QString Lv2SubPluginFeatures::description( + const Plugin::Descriptor::SubPluginFeatures::Key &k) const +{ + (void)k; + return QString::fromUtf8("description not implemented yet"); // TODO +} + + + + +const PixmapLoader *Lv2SubPluginFeatures::logo( + const Plugin::Descriptor::SubPluginFeatures::Key &k) const +{ + (void)k; // TODO + return nullptr; +} + + + + +void Lv2SubPluginFeatures::listSubPluginKeys(const Plugin::Descriptor *desc, + KeyList &kl) const +{ + Lv2Manager *lv2Mgr = Engine::getLv2Manager(); + for (const auto &uriInfoPair : *lv2Mgr) + { + if (uriInfoPair.second.type() == m_type && uriInfoPair.second.isValid()) + { + using KeyType = + Plugin::Descriptor::SubPluginFeatures::Key; + KeyType::AttributeMap atm; + atm["uri"] = QString::fromUtf8(uriInfoPair.first.c_str()); + const LilvPlugin* plug = uriInfoPair.second.plugin(); + + kl.push_back(KeyType(desc, pluginName(plug), atm)); + //qDebug() << "Found LV2 sub plugin key of type" << + // m_type << ":" << pr.first.c_str(); + } + } +} + +#endif // LMMS_HAVE_LV2 + diff --git a/src/core/lv2/Lv2UridMap.cpp b/src/core/lv2/Lv2UridMap.cpp new file mode 100644 index 00000000000..7e4fa864f1e --- /dev/null +++ b/src/core/lv2/Lv2UridMap.cpp @@ -0,0 +1,99 @@ +/* + * Lv2UridMap.cpp - Lv2UridMap implementation + * + * Copyright (c) 2019 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#include "Lv2UridMap.h" + +#ifdef LMMS_HAVE_LV2 + +static LV2_URID staticMap(LV2_URID_Map_Handle handle, const char* uri) +{ + UridMap* map = static_cast(handle); + return map->map(uri); +} + +static const char* staticUnmap(LV2_URID_Unmap_Handle handle, LV2_URID urid) +{ + UridMap* map = static_cast(handle); + return map->unmap(urid); +} + +UridMap::UridMap() +{ + m_mapFeature.handle = static_cast(this); + m_mapFeature.map = staticMap; + m_unmapFeature.handle = static_cast(this); + m_unmapFeature.unmap = staticUnmap; +} + +LV2_URID UridMap::map(const char *uri) +{ + LV2_URID result = 0u; + + // the Lv2 docs say that 0 should be returned in any case + // where creating an ID for the given URI fails + try + { + // TODO: + // when using C++14, we can get around any string allocation + // in the case the URI is already inside the map: + // * use `m_map.find(uri)` instead of `m_map.find(uriStr)` + // * to avoid temporary string construction in the `find` call, create + // m_map like this: + // std::unordered_map, std::equal<>> m_map; + // * move the try block inside the case where the URI is not in the map + const std::string uriStr = uri; + + std::lock_guard guard (m_MapMutex); + + auto itr = m_map.find(uriStr); + if (itr == m_map.end()) + { + // 1 is the first free URID + std::size_t index = 1u + m_unMap.size(); + auto pr = m_map.emplace(std::move(uriStr), index); + if (pr.second) + { + m_unMap.emplace_back(pr.first->first.c_str()); + result = static_cast(index); + } + } + else { result = itr->second; } + } + catch(...) { /* result variable is already 0 */ } + + return result; +} + +const char *UridMap::unmap(LV2_URID urid) +{ + std::size_t idx = static_cast(urid) - 1; + + std::lock_guard guard (m_MapMutex); + return (idx < m_unMap.size()) ? m_unMap[idx] : nullptr; +} + +#endif // LMMS_HAVE_LV2 + diff --git a/src/core/main.cpp b/src/core/main.cpp index f579ec8f694..c81d4c83b0a 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #ifdef LMMS_BUILD_WIN32 #include @@ -64,9 +66,12 @@ #include "Engine.h" #include "GuiApplication.h" #include "ImportFilter.h" +#include "JsonDataFile.h" #include "MainWindow.h" +#include "Mixer.h" #include "MixHelpers.h" #include "OutputSettings.h" +#include "ScriptPlugin.h" #include "ProjectRenderer.h" #include "RenderManager.h" #include "Song.h" @@ -80,6 +85,21 @@ #endif +class EngineGuard { +public: + EngineGuard(bool coreOnly) : m_coreOnly(coreOnly) + { + if (coreOnly) {Engine::init(true);} + } + ~EngineGuard() + { + if (m_coreOnly) {Engine::destroy();} + } +private: + bool m_coreOnly; +}; + + #ifdef LMMS_DEBUG_FPE void signalHandler( int signum ) { @@ -129,9 +149,10 @@ inline void loadTranslation( const QString & tname, QTranslator * t = new QTranslator( QCoreApplication::instance() ); QString name = tname + ".qm"; - t->load( name, dir ); - - QCoreApplication::instance()->installTranslator( t ); + if (t->load(name, dir)) + { + QCoreApplication::instance()->installTranslator(t); + } } @@ -161,11 +182,12 @@ void printHelp() "Actions:\n" " [options...] [] Start LMMS in normal GUI mode\n" " dump Dump XML of compressed file \n" + " compress Compress file \n" " render [options...] Render given project file\n" " rendertracks [options...] Render each track to a different file\n" " upgrade [out] Upgrade file and save as \n" " Standard out is used if no output file\n" - " is specifed\n" + " is specified\n" "\nGlobal options:\n" " --allowroot Bypass root user startup check (use with\n" " caution).\n" @@ -176,9 +198,11 @@ void printHelp() " --geometry Specify the size and position of\n" " the main window\n" " geometry is .\n" - " --import [-e] Import MIDI or Hydrogen file .\n" - " If -e is specified lmms exits after importing the file.\n" - "\nOptions for \"render\" and \"rendertracks\":\n" + " --import [--import-config ]\n" + " Import MIDI or Hydrogen file .\n" + " If --import-config is specified, use for importing.\n" + " --base-template