Merge branch 'master' into groove
This commit is contained in:
127
.circleci/config.yml
Normal file
127
.circleci/config.yml
Normal file
@@ -0,0 +1,127 @@
|
||||
version: 2
|
||||
|
||||
shared:
|
||||
restore_cache: &restore_cache
|
||||
restore_cache:
|
||||
keys:
|
||||
- ccache-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }}
|
||||
- ccache-{{ arch }}-{{ .Environment.CIRCLE_JOB }}
|
||||
- ccache-{{ arch }}
|
||||
save_cache: &save_cache
|
||||
save_cache:
|
||||
key: ccache-{{ arch }}-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }}-{{ .BuildNum }}
|
||||
paths:
|
||||
- ~/.ccache
|
||||
|
||||
ccache_stats: &ccache_stats
|
||||
run:
|
||||
name: Print ccache statistics
|
||||
command: |
|
||||
echo "[ccache config]"
|
||||
ccache -p
|
||||
echo "[ccache stats]"
|
||||
ccache -s
|
||||
|
||||
# Commmon initializing commands
|
||||
init: &init
|
||||
run:
|
||||
name: Initialize
|
||||
command: |
|
||||
mkdir -p /tmp/artifacts
|
||||
|
||||
# Commmon environment variables
|
||||
common_environment: &common_environment
|
||||
QT5: True
|
||||
CMAKE_OPTS: -DUSE_WERROR=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DUSE_CCACHE=ON
|
||||
CCACHE_MAXSIZE: 500M
|
||||
CCACHE_LOGFILE: /tmp/artifacts/ccache.log
|
||||
MAKEFLAGS: -j6
|
||||
|
||||
jobs:
|
||||
mingw32:
|
||||
environment:
|
||||
<<: *common_environment
|
||||
docker:
|
||||
- image: lmmsci/linux.mingw32:18.04
|
||||
steps:
|
||||
- checkout
|
||||
- *init
|
||||
- *restore_cache
|
||||
- run:
|
||||
name: Building
|
||||
command: |
|
||||
mkdir build && cd build
|
||||
../cmake/build_win32.sh
|
||||
make lmms
|
||||
make
|
||||
- *ccache_stats
|
||||
- *save_cache
|
||||
mingw64:
|
||||
environment:
|
||||
<<: *common_environment
|
||||
docker:
|
||||
- image: lmmsci/linux.mingw64:18.04
|
||||
steps:
|
||||
- checkout
|
||||
- *init
|
||||
- *restore_cache
|
||||
- run:
|
||||
name: Building
|
||||
command: |
|
||||
mkdir build && cd build
|
||||
../cmake/build_win64.sh
|
||||
make
|
||||
- *ccache_stats
|
||||
- *save_cache
|
||||
linux.gcc:
|
||||
docker:
|
||||
- image: lmmsci/linux.gcc:18.04
|
||||
environment:
|
||||
<<: *common_environment
|
||||
steps:
|
||||
- checkout
|
||||
- *init
|
||||
- *restore_cache
|
||||
- run:
|
||||
name: Configure
|
||||
command: mkdir build && cd build && cmake .. $CMAKE_OPTS -DCMAKE_INSTALL_PREFIX=./install
|
||||
- run:
|
||||
name: Build
|
||||
command: cd build && make
|
||||
- run:
|
||||
name: Build tests
|
||||
command: cd build && make tests
|
||||
- run:
|
||||
name: Run tests
|
||||
command: build/tests/tests
|
||||
- *ccache_stats
|
||||
- run:
|
||||
name: Build AppImage
|
||||
command: |
|
||||
cd build
|
||||
make install
|
||||
make appimage
|
||||
cp ./lmms-*.AppImage /tmp/artifacts/
|
||||
- store_artifacts:
|
||||
path: /tmp/artifacts/
|
||||
destination: /
|
||||
- store_artifacts:
|
||||
path: build/appimage.log
|
||||
destination: /
|
||||
- *save_cache
|
||||
shellcheck:
|
||||
docker:
|
||||
- image: koalaman/shellcheck-alpine:v0.4.6
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Shellcheck
|
||||
command: shellcheck $(find "./cmake/" -type f -name '*.sh' -o -name "*.sh.in")
|
||||
workflows:
|
||||
version: 2
|
||||
build-and-test:
|
||||
jobs:
|
||||
- mingw32
|
||||
- mingw64
|
||||
- linux.gcc
|
||||
- shellcheck
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -18,7 +18,7 @@
|
||||
url = https://github.com/lmms/veal
|
||||
[submodule "plugins/Xpressive/exprtk"]
|
||||
path = plugins/Xpressive/exprtk
|
||||
url = https://github.com/tresf/exprtk
|
||||
url = https://github.com/ArashPartow/exprtk
|
||||
[submodule "plugins/LadspaEffect/swh/ladspa"]
|
||||
path = plugins/LadspaEffect/swh/ladspa
|
||||
url = https://github.com/swh/ladspa
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
set -e
|
||||
|
||||
export CMAKE_OPTS="$CMAKE_FLAGS -DUSE_WERROR=ON"
|
||||
../cmake/build_mingw32.sh
|
||||
../cmake/build_win32.sh
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
set -e
|
||||
|
||||
export CMAKE_OPTS="$CMAKE_FLAGS -DUSE_WERROR=ON"
|
||||
../cmake/build_mingw64.sh
|
||||
../cmake/build_win64.sh
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
PACKAGES="cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libsoundio stk portaudio node fltk qt5"
|
||||
PACKAGES="cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk portaudio node fltk qt5"
|
||||
|
||||
if "${TRAVIS}"; then
|
||||
PACKAGES="$PACKAGES ccache"
|
||||
@@ -24,7 +24,4 @@ brew install fftw --ignore-dependencies
|
||||
|
||||
brew install --build-from-source "https://gist.githubusercontent.com/tresf/c9260c43270abd4ce66ff40359588435/raw/fluid-synth.rb"
|
||||
|
||||
# Build libgig 4.1.0 from source to avoid 3.3.0 "ISO C++11 does not allow access declarations"
|
||||
brew install --build-from-source "https://raw.githubusercontent.com/tresf/homebrew-core/gig/Formula/libgig.rb"
|
||||
|
||||
sudo npm install -g appdmg
|
||||
|
||||
@@ -124,6 +124,7 @@ CHECK_INCLUDE_FILES(sys/types.h LMMS_HAVE_SYS_TYPES_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/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)
|
||||
CHECK_INCLUDE_FILES(sys/soundcard.h LMMS_HAVE_SYS_SOUNDCARD_H)
|
||||
CHECK_INCLUDE_FILES(soundcard.h LMMS_HAVE_SOUNDCARD_H)
|
||||
@@ -250,7 +251,7 @@ IF(WANT_SDL AND NOT LMMS_HAVE_SDL2)
|
||||
IF(NOT SDL_INCLUDE_DIR)
|
||||
SET(SDL_INCLUDE_DIR "${CMAKE_FIND_ROOT_PATH}/include")
|
||||
ENDIF()
|
||||
|
||||
|
||||
ELSE()
|
||||
SET(STATUS_SDL "not found, please install libsdl2-dev (or similar) "
|
||||
"if you require SDL support")
|
||||
@@ -398,7 +399,11 @@ PKG_CHECK_MODULES(FFTW3F REQUIRED fftw3f>=3.0.0)
|
||||
|
||||
# check for FLTK
|
||||
FIND_PACKAGE(FLTK)
|
||||
|
||||
IF(FLTK_FOUND)
|
||||
SET(STATUS_ZYN "OK")
|
||||
ELSE()
|
||||
SET(STATUS_ZYN "not found, please install fltk")
|
||||
ENDIF()
|
||||
|
||||
# check for Fluidsynth
|
||||
IF(WANT_SF2)
|
||||
@@ -650,6 +655,7 @@ MESSAGE(
|
||||
MESSAGE(
|
||||
"Optional plugins\n"
|
||||
"----------------\n"
|
||||
"* ZynAddSubFX instrument : ${STATUS_ZYN}\n"
|
||||
"* Carla Patchbay & Rack : ${STATUS_CARLA}\n"
|
||||
"* SoundFont2 player : ${STATUS_FLUIDSYNTH}\n"
|
||||
"* Stk Mallets : ${STATUS_STK}\n"
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Accomodate both linux windows mingw locations
|
||||
MINGW=/mingw32
|
||||
if [ -z "$MSYSCON" ]; then
|
||||
MINGW=/opt$MINGW
|
||||
else
|
||||
CMAKE_OPTS="$CMAKE_OPTS -DLMMS_BUILD_MSYS=1"
|
||||
fi
|
||||
|
||||
export PATH=$MINGW/bin:$PATH
|
||||
export CFLAGS="-march=pentium3 -mtune=generic -mpreferred-stack-boundary=5 -mfpmath=sse"
|
||||
export CXXFLAGS="$CFLAGS"
|
||||
|
||||
CMAKE_OPTS="-DCMAKE_PREFIX_PATH=$MINGW $CMAKE_OPTS"
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
cmake "$DIR/.." -DCMAKE_TOOLCHAIN_FILE="$DIR/../cmake/modules/Win32Toolchain.cmake" -DCMAKE_MODULE_PATH="$DIR/../cmake/modules/" $CMAKE_OPTS
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Accomodate both linux windows mingw locations
|
||||
MINGW=/mingw64
|
||||
if [ -z "$MSYSCON" ]; then
|
||||
MINGW=/opt$MINGW
|
||||
else
|
||||
CMAKE_OPTS="$CMAKE_OPTS -DLMMS_BUILD_MSYS=1"
|
||||
fi
|
||||
|
||||
export PATH=$MINGW/bin:$PATH
|
||||
CMAKE_OPTS="-DCMAKE_PREFIX_PATH=$MINGW $CMAKE_OPTS"
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
cmake "$DIR/.." -DCMAKE_TOOLCHAIN_FILE="$DIR/../cmake/modules/Win64Toolchain.cmake" -DCMAKE_MODULE_PATH="$DIR/../cmake/modules/" $CMAKE_OPTS
|
||||
40
cmake/build_win32.sh
Executable file
40
cmake/build_win32.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
# Accomodate both linux windows mingw locations
|
||||
if [ -z "$ARCH" ]; then
|
||||
ARCH=32
|
||||
fi
|
||||
|
||||
MINGW=/mingw$ARCH
|
||||
|
||||
if [ -z "$MSYSCON" ]; then
|
||||
MINGW=/opt$MINGW
|
||||
|
||||
DISTRO=$(lsb_release -si)
|
||||
DISTRO_VERSION=$(lsb_release -sr)
|
||||
|
||||
if [ "$DISTRO" != "Ubuntu" ]; then
|
||||
echo "This script only supports Ubuntu"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$DISTRO_VERSION" == "14.04" ]; then
|
||||
TOOLCHAIN="$DIR/toolchains/Ubuntu-MinGW-X-Trusty-$ARCH.cmake"
|
||||
else
|
||||
TOOLCHAIN="$DIR/toolchains/Ubuntu-MinGW-W64-$ARCH.cmake"
|
||||
fi
|
||||
else
|
||||
CMAKE_OPTS="$CMAKE_OPTS -DLMMS_BUILD_MSYS=1"
|
||||
fi
|
||||
|
||||
export PATH=$MINGW/bin:$PATH
|
||||
export CXXFLAGS="$CFLAGS"
|
||||
if [ "$ARCH" == "32" ]; then
|
||||
export CFLAGS="-march=pentium3 -mtune=generic -mpreferred-stack-boundary=5 -mfpmath=sse"
|
||||
fi
|
||||
|
||||
CMAKE_OPTS="-DCMAKE_PREFIX_PATH=$MINGW $CMAKE_OPTS"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
cmake "$DIR/.." -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN" -DCMAKE_MODULE_PATH="$DIR/../cmake/modules/" $CMAKE_OPTS
|
||||
3
cmake/build_win64.sh
Executable file
3
cmake/build_win64.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
ARCH=64 "$DIR/build_win32.sh"
|
||||
@@ -15,5 +15,6 @@ ADD_CUSTOM_TARGET(removeappimage
|
||||
ADD_CUSTOM_TARGET(appimage
|
||||
COMMAND chmod +x "${CMAKE_BINARY_DIR}/package_linux.sh"
|
||||
COMMAND "${CMAKE_BINARY_DIR}/package_linux.sh"
|
||||
COMMENT "Generating AppImage")
|
||||
COMMENT "Generating AppImage"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
ADD_DEPENDENCIES(appimage removeappimage)
|
||||
|
||||
@@ -56,25 +56,27 @@ echo -e "\nWriting verbose output to \"${LOGFILE}\""
|
||||
PATH="$(pwd -P)/squashfs-root/usr/bin:$(dirname "@QT_QMAKE_EXECUTABLE@")":$PATH
|
||||
export PATH
|
||||
|
||||
# Fetch portable linuxdeployqt if cache is older than $DAYSOLD
|
||||
# Fetch portable linuxdeployqt if not in PATH
|
||||
echo -e "\nDownloading linuxdeployqt to ${LINUXDEPLOYQT}..."
|
||||
mkdir -p "$HOME/bin"
|
||||
DAYSOLD=2
|
||||
if env -i which linuxdeployqt > /dev/null 2>&1; then
|
||||
skipped "System already provides this utility"
|
||||
elif ! find "$LINUXDEPLOYQT" -mtime -$DAYSOLD 2>/dev/null|grep -q "." > /dev/null 2>&1; then
|
||||
url="https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-$(uname -p).AppImage"
|
||||
echo " [.......] Couldn't find linuxdeployqt newer than $DAYSOLD days old"
|
||||
else
|
||||
filename="linuxdeployqt-continuous-$(uname -p).AppImage"
|
||||
url="https://github.com/probonopd/linuxdeployqt/releases/download/continuous/$filename"
|
||||
down_file="$(pwd)/$filename"
|
||||
if [ ! -f "$LINUXDEPLOYQT" ]; then
|
||||
ln -s "$down_file" "$LINUXDEPLOYQT"
|
||||
fi
|
||||
echo " [.......] Downloading ($(uname -p)): ${url}"
|
||||
wget "$url" -O "$LINUXDEPLOYQT" -q || (rm "$LINUXDEPLOYQT" && false)
|
||||
wget -N -q "$url" || (rm "$filename" && false)
|
||||
chmod +x "$LINUXDEPLOYQT"
|
||||
touch "$LINUXDEPLOYQT"
|
||||
success "Downloaded $LINUXDEPLOYQT"
|
||||
# Extract AppImage and replace LINUXDEPLOYQT variable with extracted binary
|
||||
# to support systems without fuse
|
||||
"$LINUXDEPLOYQT" --appimage-extract > /dev/null 2>&1
|
||||
LINUXDEPLOYQT="squashfs-root/AppRun"
|
||||
APPIMAGETOOL="squashfs-root/usr/bin/appimagetool"
|
||||
success "Extracted $APPIMAGETOOL"
|
||||
else
|
||||
skipped "$LINUXDEPLOYQT is less than $DAYSOLD days old"
|
||||
fi
|
||||
|
||||
# Make skeleton AppDir
|
||||
|
||||
@@ -113,8 +113,8 @@ MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT FORCE_REMOTE)
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
|
||||
SET(MISSING_COMMIT_PHRASES "no such remote ref;reference is not a tree")
|
||||
SET(RETRY_PHRASES "Failed to recurse;unadvertised object;cannot create directory;already exists;${MISSING_COMMIT_PHRASES}")
|
||||
SET(MISSING_COMMIT_PHRASES "no such remote ref;reference is not a tree;unadvertised object")
|
||||
SET(RETRY_PHRASES "Failed to recurse;cannot create directory;already exists;${MISSING_COMMIT_PHRASES}")
|
||||
|
||||
# Attempt to do lazy clone
|
||||
FOREACH(_submodule ${SUBMODULE_LIST})
|
||||
|
||||
@@ -10,7 +10,7 @@ ELSE()
|
||||
SET(LMMS_BUILD_LINUX 1)
|
||||
ENDIF(WIN32)
|
||||
|
||||
# See build_mingwXX.sh for LMMS_BUILD_MSYS
|
||||
# See build_winXX.sh for LMMS_BUILD_MSYS
|
||||
|
||||
MESSAGE("PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
SET(LMMS_HOST_X86 FALSE)
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
# WINE_DEFINITIONS - Compiler switches required for using wine
|
||||
#
|
||||
|
||||
LIST(APPEND CMAKE_PREFIX_PATH /opt/wine-stable /opt/wine-devel /opt/wine-staging)
|
||||
LIST(APPEND CMAKE_PREFIX_PATH /opt/wine-stable /opt/wine-devel /opt/wine-staging /usr/lib/wine/)
|
||||
|
||||
FIND_PATH(WINE_INCLUDE_DIR windows/windows.h PATH_SUFFIXES wine)
|
||||
FIND_LIBRARY(WINE_LIBRARY NAMES wine PATH_SUFFIXES wine i386-linux-gnu/wine)
|
||||
FIND_PROGRAM(WINE_CXX NAMES wineg++ winegcc winegcc64 winegcc32)
|
||||
FIND_PROGRAM(WINE_CXX
|
||||
NAMES wineg++ winegcc winegcc64 winegcc32 winegcc-stable
|
||||
PATHS /usr/lib/wine)
|
||||
|
||||
SET(WINE_INCLUDE_DIRS ${WINE_INCLUDE_DIR} )
|
||||
SET(WINE_LIBRARIES ${WINE_LIBRARY} )
|
||||
@@ -37,6 +39,6 @@ FOREACH(FLAG ${WINEBUILD_FLAGS})
|
||||
ENDFOREACH()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Wine DEFAULT_MSG WINE_LIBRARIES WINE_INCLUDE_DIRS)
|
||||
find_package_handle_standard_args(Wine DEFAULT_MSG WINE_CXX WINE_LIBRARIES WINE_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(WINE_INCLUDE_DIR WINE_LIBRARY)
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
# Required by cmake if `uname -s` is inadaquate
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
|
||||
# The target environment
|
||||
SET(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX})
|
||||
SET(CMAKE_INSTALL_PREFIX ${MINGW_PREFIX})
|
||||
|
||||
# Windows msys mingw ships with a mostly-suitable preconfigured environment
|
||||
IF(LMMS_BUILD_MSYS)
|
||||
SET(STRIP ${MINGW_PREFIX}/bin/strip)
|
||||
SET(WINDRES ${MINGW_PREFIX}/bin/windres)
|
||||
SET(CMAKE_RC_COMPILER ${WINDRES})
|
||||
SET(CMAKE_C_COMPILER ${MINGW_PREFIX}/bin/gcc)
|
||||
SET(CMAKE_CXX_COMPILER ${MINGW_PREFIX}/bin/g++)
|
||||
|
||||
# For 32-bit vst support
|
||||
IF(WIN64)
|
||||
# Specify the 32-bit cross compiler
|
||||
SET(CMAKE_C_COMPILER32 ${MINGW_PREFIX32}/bin/gcc)
|
||||
SET(CMAKE_CXX_COMPILER32 ${MINGW_PREFIX32}/bin/g++)
|
||||
ENDIF()
|
||||
|
||||
# Msys compiler does not support @CMakeFiles/Include syntax
|
||||
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES OFF)
|
||||
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES OFF)
|
||||
|
||||
# Variable to assist override Qt debug libraries with release versions
|
||||
SET(QT_OVERRIDE_LIBRARIES
|
||||
optimized;${MINGW_PREFIX}/bin/QtGui4.dll;
|
||||
optimized;${MINGW_PREFIX}/bin/QtCore4.dll;
|
||||
optimized;${MINGW_PREFIX}/bin/QtXml4.dll;
|
||||
debug;${MINGW_PREFIX}/bin/QtGui4.dll;
|
||||
debug;${MINGW_PREFIX}/bin/QtCore4.dll;
|
||||
debug;${MINGW_PREFIX}/bin/QtXml4.dll;
|
||||
)
|
||||
IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
# Override Qt debug libraries with release versions
|
||||
SET(QT_LIBRARIES "${QT_OVERRIDE_LIBRARIES}")
|
||||
ENDIF()
|
||||
# Linux mingw requires explicitly defined tools to prevent clash with native system tools
|
||||
ELSE()
|
||||
SET(MINGW_TOOL_PREFIX ${MINGW_PREFIX}/bin/${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-)
|
||||
|
||||
# Specify the cross compiler
|
||||
SET(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}gcc)
|
||||
SET(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}g++)
|
||||
SET(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}gcc)
|
||||
|
||||
# Mingw tools
|
||||
SET(STRIP ${MINGW_TOOL_PREFIX}strip)
|
||||
SET(WINDRES ${MINGW_TOOL_PREFIX}windres)
|
||||
SET(ENV{PKG_CONFIG} ${MINGW_TOOL_PREFIX}pkg-config)
|
||||
|
||||
# Search for programs in the build host directories
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
# For libraries and headers in the target directories
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
# For 32-bit vst support
|
||||
IF(WIN64)
|
||||
# Specify the 32-bit cross compiler
|
||||
SET(MINGW_TOOL_PREFIX32 ${MINGW_PREFIX32}/bin/${CMAKE_SYSTEM_PROCESSOR32}-w64-mingw32-)
|
||||
SET(CMAKE_C_COMPILER32 ${MINGW_TOOL_PREFIX32}gcc)
|
||||
SET(CMAKE_CXX_COMPILER32 ${MINGW_TOOL_PREFIX32}g++)
|
||||
ENDIF()
|
||||
|
||||
INCLUDE_DIRECTORIES(${MINGW_PREFIX}/include)
|
||||
ENDIF()
|
||||
|
||||
LINK_DIRECTORIES(${MINGW_PREFIX}/lib ${MINGW_PREFIX}/bin)
|
||||
|
||||
# Qt tools
|
||||
SET(QT_BINARY_DIR ${MINGW_PREFIX}/bin)
|
||||
SET(QT_QMAKE_EXECUTABLE ${QT_BINARY_DIR}/qmake)
|
||||
|
||||
# Echo modified cmake vars to screen for debugging purposes
|
||||
IF(NOT DEFINED ENV{MINGW_DEBUG_INFO})
|
||||
MESSAGE("")
|
||||
MESSAGE("Custom cmake vars: (blank = system default)")
|
||||
MESSAGE("-----------------------------------------")
|
||||
MESSAGE("* CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}")
|
||||
MESSAGE("* CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}")
|
||||
MESSAGE("* CMAKE_RC_COMPILER : ${CMAKE_RC_COMPILER}")
|
||||
MESSAGE("* WINDRES : ${WINDRES}")
|
||||
MESSAGE("* ENV{PKG_CONFIG} : $ENV{PKG_CONFIG}")
|
||||
MESSAGE("* MINGW_TOOL_PREFIX32 : ${MINGW_TOOL_PREFIX32}")
|
||||
MESSAGE("* CMAKE_C_COMPILER32 : ${CMAKE_C_COMPILER32}")
|
||||
MESSAGE("* CMAKE_CXX_COMPILER32 : ${CMAKE_CXX_COMPILER32}")
|
||||
MESSAGE("* STRIP : ${STRIP}")
|
||||
MESSAGE("* QT_BINARY_DIR : ${QT_BINARY_DIR}")
|
||||
MESSAGE("* QT_QMAKE_EXECUTABLE : ${QT_QMAKE_EXECUTABLE}")
|
||||
MESSAGE("")
|
||||
# So that the debug info only appears once
|
||||
SET(ENV{MINGW_DEBUG_INFO} SHOWN)
|
||||
ENDIF()
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
IF(LMMS_BUILD_MSYS)
|
||||
SET(MINGW_PREFIX /mingw32)
|
||||
ELSE()
|
||||
SET(MINGW_PREFIX /opt/mingw32)
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_SYSTEM_PROCESSOR i686)
|
||||
|
||||
INCLUDE(MinGWCrossCompile)
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
IF(LMMS_BUILD_MSYS)
|
||||
SET(MINGW_PREFIX /mingw64)
|
||||
SET(MINGW_PREFIX32 /mingw32)
|
||||
ELSE()
|
||||
SET(MINGW_PREFIX /opt/mingw64)
|
||||
SET(MINGW_PREFIX32 /opt/mingw32)
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
SET(CMAKE_SYSTEM_PROCESSOR32 i686)
|
||||
|
||||
SET(WIN64 TRUE)
|
||||
|
||||
|
||||
INCLUDE(MinGWCrossCompile)
|
||||
|
||||
2
cmake/toolchains/MSYS-32.cmake
Normal file
2
cmake/toolchains/MSYS-32.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
INCLUDE(common/Win32)
|
||||
SET(LMMS_BUILD_MSYS 1)
|
||||
6
cmake/toolchains/MSYS-64.cmake
Normal file
6
cmake/toolchains/MSYS-64.cmake
Normal file
@@ -0,0 +1,6 @@
|
||||
INCLUDE(MSYS-32)
|
||||
INCLUDE(Win64)
|
||||
SET(LMMS_BUILD_MSYS 1)
|
||||
|
||||
SET(MINGW_PREFIX /mingw64)
|
||||
SET(MINGW_PREFIX32 /mingw32)
|
||||
2
cmake/toolchains/Ubuntu-MinGW-W64-32.cmake
Normal file
2
cmake/toolchains/Ubuntu-MinGW-W64-32.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Win32.cmake)
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Ubuntu-MinGW-W64.cmake)
|
||||
2
cmake/toolchains/Ubuntu-MinGW-W64-64.cmake
Normal file
2
cmake/toolchains/Ubuntu-MinGW-W64-64.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Win64.cmake)
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Ubuntu-MinGW-W64.cmake)
|
||||
3
cmake/toolchains/Ubuntu-MinGW-X-Trusty-32.cmake
Normal file
3
cmake/toolchains/Ubuntu-MinGW-X-Trusty-32.cmake
Normal file
@@ -0,0 +1,3 @@
|
||||
SET(MINGW_PREFIX /opt/mingw32)
|
||||
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Ubuntu-MinGW-X-Trusty.cmake)
|
||||
6
cmake/toolchains/Ubuntu-MinGW-X-Trusty-64.cmake
Normal file
6
cmake/toolchains/Ubuntu-MinGW-X-Trusty-64.cmake
Normal file
@@ -0,0 +1,6 @@
|
||||
SET(MINGW_PREFIX /opt/mingw64)
|
||||
SET(MINGW_PREFIX32 /opt/mingw32)
|
||||
|
||||
SET(WIN64 TRUE)
|
||||
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Ubuntu-MinGW-X-Trusty.cmake)
|
||||
34
cmake/toolchains/common/MSYS.cmake
Normal file
34
cmake/toolchains/common/MSYS.cmake
Normal file
@@ -0,0 +1,34 @@
|
||||
# The target environment
|
||||
SET(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX})
|
||||
SET(CMAKE_INSTALL_PREFIX ${MINGW_PREFIX})
|
||||
|
||||
# Windows msys mingw ships with a mostly-suitable preconfigured environment
|
||||
SET(STRIP ${MINGW_PREFIX}/bin/strip)
|
||||
SET(CMAKE_RC_COMPILER ${MINGW_PREFIX}/bin/windres)
|
||||
SET(CMAKE_C_COMPILER ${MINGW_PREFIX}/bin/gcc)
|
||||
SET(CMAKE_CXX_COMPILER ${MINGW_PREFIX}/bin/g++)
|
||||
|
||||
# For 32-bit vst support
|
||||
IF(WIN64)
|
||||
# Specify the 32-bit cross compiler
|
||||
SET(CMAKE_C_COMPILER32 ${MINGW_PREFIX32}/bin/gcc)
|
||||
SET(CMAKE_CXX_COMPILER32 ${MINGW_PREFIX32}/bin/g++)
|
||||
ENDIF()
|
||||
|
||||
# Msys compiler does not support @CMakeFiles/Include syntax
|
||||
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES OFF)
|
||||
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES OFF)
|
||||
|
||||
# Variable to assist override Qt debug libraries with release versions
|
||||
SET(QT_OVERRIDE_LIBRARIES
|
||||
optimized;${MINGW_PREFIX}/bin/QtGui4.dll;
|
||||
optimized;${MINGW_PREFIX}/bin/QtCore4.dll;
|
||||
optimized;${MINGW_PREFIX}/bin/QtXml4.dll;
|
||||
debug;${MINGW_PREFIX}/bin/QtGui4.dll;
|
||||
debug;${MINGW_PREFIX}/bin/QtCore4.dll;
|
||||
debug;${MINGW_PREFIX}/bin/QtXml4.dll;
|
||||
)
|
||||
IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
# Override Qt debug libraries with release versions
|
||||
SET(QT_LIBRARIES "${QT_OVERRIDE_LIBRARIES}")
|
||||
ENDIF()
|
||||
17
cmake/toolchains/common/Ubuntu-MinGW-W64.cmake
Normal file
17
cmake/toolchains/common/Ubuntu-MinGW-W64.cmake
Normal file
@@ -0,0 +1,17 @@
|
||||
# Toolchain for Ubuntu MinGw compiler shipped with the mingw-w64 and
|
||||
# g++-mingw-w64 packages
|
||||
SET(TOOLCHAIN_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32)
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
|
||||
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
|
||||
SET(PKG_CONFIG_EXECUTABLE /usr/bin/${TOOLCHAIN_PREFIX}-pkg-config)
|
||||
|
||||
IF(WIN64)
|
||||
SET(TOOLCHAIN_PREFIX32 ${CMAKE_SYSTEM_PROCESSOR32}-w64-mingw32)
|
||||
SET(CMAKE_C_COMPILER32 ${TOOLCHAIN_PREFIX32}-gcc)
|
||||
SET(CMAKE_CXX_COMPILER32 ${TOOLCHAIN_PREFIX32}-g++)
|
||||
ENDIF()
|
||||
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/WinCrossCompile.cmake)
|
||||
58
cmake/toolchains/common/Ubuntu-MinGW-X-Trusty.cmake
Normal file
58
cmake/toolchains/common/Ubuntu-MinGW-X-Trusty.cmake
Normal file
@@ -0,0 +1,58 @@
|
||||
IF(WIN64)
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Win64.cmake)
|
||||
ELSE()
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/Win32.cmake)
|
||||
ENDIF()
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/WinCrossCompile.cmake)
|
||||
|
||||
# The target environment
|
||||
SET(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX})
|
||||
SET(CMAKE_INSTALL_PREFIX ${MINGW_PREFIX})
|
||||
|
||||
# Linux mingw requires explicitly defined tools to prevent clash with native system tools
|
||||
SET(MINGW_TOOL_PREFIX ${MINGW_PREFIX}/bin/${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-)
|
||||
|
||||
# Specify the cross compiler
|
||||
SET(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}gcc)
|
||||
SET(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}g++)
|
||||
SET(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}windres)
|
||||
|
||||
# Mingw tools
|
||||
SET(STRIP ${MINGW_TOOL_PREFIX}strip)
|
||||
SET(PKG_CONFIG_EXECUTABLE ${MINGW_TOOL_PREFIX}pkg-config)
|
||||
|
||||
# For 32-bit vst support
|
||||
IF(WIN64)
|
||||
# Specify the 32-bit cross compiler
|
||||
SET(MINGW_TOOL_PREFIX32 ${MINGW_PREFIX32}/bin/${CMAKE_SYSTEM_PROCESSOR32}-w64-mingw32-)
|
||||
SET(CMAKE_C_COMPILER32 ${MINGW_TOOL_PREFIX32}gcc)
|
||||
SET(CMAKE_CXX_COMPILER32 ${MINGW_TOOL_PREFIX32}g++)
|
||||
ENDIF()
|
||||
|
||||
INCLUDE_DIRECTORIES(${MINGW_PREFIX}/include)
|
||||
|
||||
LINK_DIRECTORIES(${MINGW_PREFIX}/lib ${MINGW_PREFIX}/bin)
|
||||
|
||||
# Qt tools
|
||||
SET(QT_BINARY_DIR ${MINGW_PREFIX}/bin)
|
||||
SET(QT_QMAKE_EXECUTABLE ${QT_BINARY_DIR}/qmake)
|
||||
|
||||
# Echo modified cmake vars to screen for debugging purposes
|
||||
IF(NOT DEFINED ENV{MINGW_DEBUG_INFO})
|
||||
MESSAGE("")
|
||||
MESSAGE("Custom cmake vars: (blank = system default)")
|
||||
MESSAGE("-----------------------------------------")
|
||||
MESSAGE("* CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}")
|
||||
MESSAGE("* CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}")
|
||||
MESSAGE("* CMAKE_RC_COMPILER : ${CMAKE_RC_COMPILER}")
|
||||
MESSAGE("* PKG_CONFIG_EXECUTABLE : ${PKG_CONFIG_EXECUTABLE}")
|
||||
MESSAGE("* MINGW_TOOL_PREFIX32 : ${MINGW_TOOL_PREFIX32}")
|
||||
MESSAGE("* CMAKE_C_COMPILER32 : ${CMAKE_C_COMPILER32}")
|
||||
MESSAGE("* CMAKE_CXX_COMPILER32 : ${CMAKE_CXX_COMPILER32}")
|
||||
MESSAGE("* STRIP : ${STRIP}")
|
||||
MESSAGE("* QT_BINARY_DIR : ${QT_BINARY_DIR}")
|
||||
MESSAGE("* QT_QMAKE_EXECUTABLE : ${QT_QMAKE_EXECUTABLE}")
|
||||
MESSAGE("")
|
||||
# So that the debug info only appears once
|
||||
SET(ENV{MINGW_DEBUG_INFO} SHOWN)
|
||||
ENDIF()
|
||||
4
cmake/toolchains/common/Win32.cmake
Normal file
4
cmake/toolchains/common/Win32.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
|
||||
SET(CMAKE_SYSTEM_PROCESSOR i686)
|
||||
7
cmake/toolchains/common/Win64.cmake
Normal file
7
cmake/toolchains/common/Win64.cmake
Normal file
@@ -0,0 +1,7 @@
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
|
||||
SET(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
SET(CMAKE_SYSTEM_PROCESSOR32 i686)
|
||||
|
||||
SET(WIN64 TRUE)
|
||||
9
cmake/toolchains/common/WinCrossCompile.cmake
Normal file
9
cmake/toolchains/common/WinCrossCompile.cmake
Normal file
@@ -0,0 +1,9 @@
|
||||
# Required by cmake if `uname -s` is inadaquate
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
|
||||
# Search for programs in the build host directories
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
# For libraries and headers in the target directories
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,45 +0,0 @@
|
||||
/// \file AtomicInt.h
|
||||
/// \brief Compatibility subclass of QAtomicInt for supporting both Qt4 and Qt5
|
||||
|
||||
#ifndef LMMS_ATOMIC_H
|
||||
#define LMMS_ATOMIC_H
|
||||
|
||||
#include <QtCore/QAtomicInt>
|
||||
|
||||
#if QT_VERSION < 0x050300
|
||||
|
||||
class AtomicInt : public QAtomicInt
|
||||
{
|
||||
public:
|
||||
AtomicInt( int value = 0 ) :
|
||||
QAtomicInt( value )
|
||||
{
|
||||
}
|
||||
|
||||
int fetchAndAndOrdered( int valueToAnd )
|
||||
{
|
||||
int value;
|
||||
do
|
||||
{
|
||||
value = (int)*this;
|
||||
}
|
||||
while( !testAndSetOrdered( value, value & valueToAnd ) );
|
||||
return value;
|
||||
}
|
||||
|
||||
#if QT_VERSION >= 0x050000 && QT_VERSION < 0x050300
|
||||
operator int() const
|
||||
{
|
||||
return loadAcquire();
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
typedef QAtomicInt AtomicInt;
|
||||
|
||||
#endif // QT_VERSION < 0x050300
|
||||
|
||||
#endif
|
||||
@@ -25,6 +25,7 @@
|
||||
#ifndef AUDIO_PORT_H
|
||||
#define AUDIO_PORT_H
|
||||
|
||||
#include <memory>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QMutexLocker>
|
||||
@@ -79,7 +80,7 @@ public:
|
||||
|
||||
inline EffectChain * effects()
|
||||
{
|
||||
return m_effects;
|
||||
return m_effects.get();
|
||||
}
|
||||
|
||||
void setNextFxChannel( const fx_ch_t _chnl )
|
||||
@@ -119,7 +120,7 @@ private:
|
||||
|
||||
QString m_name;
|
||||
|
||||
EffectChain * m_effects;
|
||||
std::unique_ptr<EffectChain> m_effects;
|
||||
|
||||
PlayHandleList m_playHandles;
|
||||
QMutex m_playHandleLock;
|
||||
|
||||
@@ -77,30 +77,10 @@ public:
|
||||
Decibel
|
||||
};
|
||||
|
||||
enum DataType
|
||||
{
|
||||
Float,
|
||||
Integer,
|
||||
Bool
|
||||
} ;
|
||||
|
||||
AutomatableModel( DataType type,
|
||||
const float val = 0,
|
||||
const float min = 0,
|
||||
const float max = 0,
|
||||
const float step = 0,
|
||||
Model* parent = NULL,
|
||||
const QString& displayName = QString(),
|
||||
bool defaultConstructed = false );
|
||||
|
||||
virtual ~AutomatableModel();
|
||||
|
||||
|
||||
static float copiedValue()
|
||||
{
|
||||
return s_copiedValue;
|
||||
}
|
||||
|
||||
bool isAutomated() const;
|
||||
bool isAutomatedOrControlled() const
|
||||
{
|
||||
@@ -132,7 +112,7 @@ public:
|
||||
template<class T>
|
||||
inline T value( int frameOffset = 0 ) const
|
||||
{
|
||||
if( unlikely( m_hasLinkedModels || m_controllerConnection != NULL ) )
|
||||
if( unlikely( hasLinkedModels() || m_controllerConnection != NULL ) )
|
||||
{
|
||||
return castValue<T>( controllerValue( frameOffset ) );
|
||||
}
|
||||
@@ -244,11 +224,11 @@ public:
|
||||
return "automatablemodel";
|
||||
}
|
||||
|
||||
QString displayValue( const float val ) const;
|
||||
virtual QString displayValue( const float val ) const = 0;
|
||||
|
||||
bool hasLinkedModels() const
|
||||
{
|
||||
return m_hasLinkedModels;
|
||||
return !m_linkedModels.empty();
|
||||
}
|
||||
|
||||
// a way to track changed values in the model and avoid using signals/slots - useful for speed-critical code.
|
||||
@@ -266,11 +246,6 @@ public:
|
||||
|
||||
float globalAutomationValueAt( const MidiTime& time );
|
||||
|
||||
bool hasStrictStepSize() const
|
||||
{
|
||||
return m_hasStrictStepSize;
|
||||
}
|
||||
|
||||
void setStrictStepSize( const bool b )
|
||||
{
|
||||
m_hasStrictStepSize = b;
|
||||
@@ -288,12 +263,18 @@ public:
|
||||
|
||||
public slots:
|
||||
virtual void reset();
|
||||
virtual void copyValue();
|
||||
virtual void pasteValue();
|
||||
void unlinkControllerConnection();
|
||||
|
||||
|
||||
protected:
|
||||
AutomatableModel(
|
||||
const float val = 0,
|
||||
const float min = 0,
|
||||
const float max = 0,
|
||||
const float step = 0,
|
||||
Model* parent = NULL,
|
||||
const QString& displayName = QString(),
|
||||
bool defaultConstructed = false );
|
||||
//! returns a value which is in range between min() and
|
||||
//! max() and aligned according to the step size (step size 0.05 -> value
|
||||
//! 0.12345 becomes 0.10 etc.). You should always call it at the end after
|
||||
@@ -324,7 +305,6 @@ private:
|
||||
template<class T> void roundAt( T &value, const T &where ) const;
|
||||
|
||||
|
||||
DataType m_dataType;
|
||||
ScaleType m_scaleType; //! scale type, linear by default
|
||||
float m_value;
|
||||
float m_initValue;
|
||||
@@ -345,15 +325,12 @@ private:
|
||||
bool m_hasStrictStepSize;
|
||||
|
||||
AutoModelVector m_linkedModels;
|
||||
bool m_hasLinkedModels;
|
||||
|
||||
|
||||
//! NULL if not appended to controller, otherwise connection info
|
||||
ControllerConnection* m_controllerConnection;
|
||||
|
||||
|
||||
static float s_copiedValue;
|
||||
|
||||
ValueBuffer m_valueBuffer;
|
||||
long m_lastUpdatedPeriod;
|
||||
static long s_periodCounter;
|
||||
@@ -372,32 +349,35 @@ signals:
|
||||
|
||||
|
||||
|
||||
template <typename T> class EXPORT TypedAutomatableModel : public AutomatableModel
|
||||
{
|
||||
public:
|
||||
using AutomatableModel::AutomatableModel;
|
||||
T value( int frameOffset = 0 ) const
|
||||
{
|
||||
return AutomatableModel::value<T>( frameOffset );
|
||||
}
|
||||
|
||||
#define defaultTypedMethods(type) \
|
||||
type value( int frameOffset = 0 ) const \
|
||||
{ \
|
||||
return AutomatableModel::value<type>( frameOffset ); \
|
||||
} \
|
||||
\
|
||||
type initValue() const \
|
||||
{ \
|
||||
return AutomatableModel::initValue<type>(); \
|
||||
} \
|
||||
\
|
||||
type minValue() const \
|
||||
{ \
|
||||
return AutomatableModel::minValue<type>(); \
|
||||
} \
|
||||
\
|
||||
type maxValue() const \
|
||||
{ \
|
||||
return AutomatableModel::maxValue<type>(); \
|
||||
} \
|
||||
T initValue() const
|
||||
{
|
||||
return AutomatableModel::initValue<T>();
|
||||
}
|
||||
|
||||
T minValue() const
|
||||
{
|
||||
return AutomatableModel::minValue<T>();
|
||||
}
|
||||
|
||||
T maxValue() const
|
||||
{
|
||||
return AutomatableModel::maxValue<T>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// some typed AutomatableModel-definitions
|
||||
|
||||
class EXPORT FloatModel : public AutomatableModel
|
||||
class EXPORT FloatModel : public TypedAutomatableModel<float>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -405,17 +385,16 @@ public:
|
||||
Model * parent = NULL,
|
||||
const QString& displayName = QString(),
|
||||
bool defaultConstructed = false ) :
|
||||
AutomatableModel( Float, val, min, max, step, parent, displayName, defaultConstructed )
|
||||
TypedAutomatableModel( val, min, max, step, parent, displayName, defaultConstructed )
|
||||
{
|
||||
}
|
||||
float getRoundedValue() const;
|
||||
int getDigitCount() const;
|
||||
defaultTypedMethods(float);
|
||||
|
||||
QString displayValue( const float val ) const override;
|
||||
} ;
|
||||
|
||||
|
||||
class EXPORT IntModel : public AutomatableModel
|
||||
class EXPORT IntModel : public TypedAutomatableModel<int>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -423,16 +402,14 @@ public:
|
||||
Model* parent = NULL,
|
||||
const QString& displayName = QString(),
|
||||
bool defaultConstructed = false ) :
|
||||
AutomatableModel( Integer, val, min, max, 1, parent, displayName, defaultConstructed )
|
||||
TypedAutomatableModel( val, min, max, 1, parent, displayName, defaultConstructed )
|
||||
{
|
||||
}
|
||||
|
||||
defaultTypedMethods(int);
|
||||
|
||||
QString displayValue( const float val ) const override;
|
||||
} ;
|
||||
|
||||
|
||||
class EXPORT BoolModel : public AutomatableModel
|
||||
class EXPORT BoolModel : public TypedAutomatableModel<bool>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -440,12 +417,10 @@ public:
|
||||
Model* parent = NULL,
|
||||
const QString& displayName = QString(),
|
||||
bool defaultConstructed = false ) :
|
||||
AutomatableModel( Bool, val, false, true, 1, parent, displayName, defaultConstructed )
|
||||
TypedAutomatableModel( val, false, true, 1, parent, displayName, defaultConstructed )
|
||||
{
|
||||
}
|
||||
|
||||
defaultTypedMethods(bool);
|
||||
|
||||
QString displayValue( const float val ) const override;
|
||||
} ;
|
||||
|
||||
typedef QMap<AutomatableModel*, float> AutomatedValueMap;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* AutomatableModelView.h - class AutomatableModelView
|
||||
* AutomatableModelView.h - provides AutomatableModelView base class and
|
||||
* provides BoolModelView, FloatModelView, IntModelView subclasses.
|
||||
*
|
||||
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -74,7 +75,6 @@ protected:
|
||||
|
||||
QString m_description;
|
||||
QString m_unit;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -93,6 +93,11 @@ public slots:
|
||||
void unlinkAllModels();
|
||||
void removeSongGlobalAutomation();
|
||||
|
||||
private slots:
|
||||
/// Copy the model's value to the clipboard.
|
||||
void copyToClipboard();
|
||||
/// Paste the model's value from the clipboard.
|
||||
void pasteFromClipboard();
|
||||
|
||||
protected:
|
||||
AutomatableModelView* m_amv;
|
||||
@@ -101,31 +106,26 @@ protected:
|
||||
|
||||
|
||||
|
||||
template <typename ModelType> class EXPORT TypedModelView : public AutomatableModelView
|
||||
{
|
||||
public:
|
||||
TypedModelView( Model* model, QWidget* _this) :
|
||||
AutomatableModelView( model, _this )
|
||||
{}
|
||||
|
||||
#define generateTypedModelView(type) \
|
||||
class EXPORT type##ModelView : public AutomatableModelView \
|
||||
{ \
|
||||
public: \
|
||||
type##ModelView( Model* model, QWidget* _this ) : \
|
||||
AutomatableModelView( model, _this ) \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
type##Model* model() \
|
||||
{ \
|
||||
return castModel<type##Model>(); \
|
||||
} \
|
||||
\
|
||||
const type##Model* model() const \
|
||||
{ \
|
||||
return castModel<type##Model>(); \
|
||||
} \
|
||||
}
|
||||
ModelType* model()
|
||||
{
|
||||
return castModel<ModelType>();
|
||||
}
|
||||
const ModelType* model() const
|
||||
{
|
||||
return castModel<ModelType>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
generateTypedModelView(Float);
|
||||
generateTypedModelView(Int);
|
||||
generateTypedModelView(Bool);
|
||||
using FloatModelView = TypedModelView<FloatModel>;
|
||||
using IntModelView = TypedModelView<IntModel>;
|
||||
using BoolModelView = TypedModelView<BoolModel>;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -125,48 +125,9 @@ public:
|
||||
*/
|
||||
static inline sample_t oscillate( float _ph, float _wavelen, Waveforms _wave )
|
||||
{
|
||||
// high wavelen/ low freq
|
||||
if( _wavelen > TLENS[ MAXTBL ] )
|
||||
{
|
||||
const int t = MAXTBL;
|
||||
const int tlen = TLENS[t];
|
||||
const float ph = fraction( _ph );
|
||||
const float lookupf = ph * static_cast<float>( tlen );
|
||||
const int lookup = static_cast<int>( lookupf );
|
||||
const float ip = fraction( lookupf );
|
||||
|
||||
const sample_t s1 = s_waveforms[ _wave ].sampleAt( t, lookup );
|
||||
const sample_t s2 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen );
|
||||
const int lm = lookup == 0 ? tlen - 1 : lookup - 1;
|
||||
const sample_t s0 = s_waveforms[ _wave ].sampleAt( t, lm );
|
||||
const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 2 ) % tlen );
|
||||
const sample_t sr = optimal4pInterpolate( s0, s1, s2, s3, ip );
|
||||
|
||||
return sr;
|
||||
}
|
||||
// low wavelen/ high freq
|
||||
if( _wavelen < 3.0f )
|
||||
{
|
||||
const int t = 0;
|
||||
const int tlen = TLENS[t];
|
||||
const float ph = fraction( _ph );
|
||||
const float lookupf = ph * static_cast<float>( tlen );
|
||||
const int lookup = static_cast<int>( lookupf );
|
||||
const float ip = fraction( lookupf );
|
||||
|
||||
const sample_t s1 = s_waveforms[ _wave ].sampleAt( t, lookup );
|
||||
const sample_t s2 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen );
|
||||
const int lm = lookup == 0 ? tlen - 1 : lookup - 1;
|
||||
const sample_t s0 = s_waveforms[ _wave ].sampleAt( t, lm );
|
||||
const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 2 ) % tlen );
|
||||
const sample_t sr = optimal4pInterpolate( s0, s1, s2, s3, ip );
|
||||
|
||||
return sr;
|
||||
}
|
||||
|
||||
// get the next higher tlen
|
||||
int t = MAXTBL - 1;
|
||||
while( _wavelen < TLENS[t] ) { t--; }
|
||||
int t = 0;
|
||||
while( t < MAXTBL && _wavelen >= TLENS[t+1] ) { t++; }
|
||||
|
||||
int tlen = TLENS[t];
|
||||
const float ph = fraction( _ph );
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#ifndef BUFFER_MANAGER_H
|
||||
#define BUFFER_MANAGER_H
|
||||
|
||||
#include "AtomicInt.h"
|
||||
#include "export.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
#ifndef COMBOBOX_MODEL_H
|
||||
#define COMBOBOX_MODEL_H
|
||||
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QPair>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "AutomatableModel.h"
|
||||
|
||||
class PixmapLoader;
|
||||
#include "embed.h"
|
||||
|
||||
|
||||
class EXPORT ComboBoxModel : public IntModel
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
clear();
|
||||
}
|
||||
|
||||
void addItem( const QString& item, PixmapLoader* loader = NULL );
|
||||
void addItem( QString item, std::unique_ptr<PixmapLoader> loader = nullptr );
|
||||
|
||||
void clear();
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
|
||||
const PixmapLoader* currentData() const
|
||||
{
|
||||
return m_items[value()].second;
|
||||
return m_items[value()].second.get();
|
||||
}
|
||||
|
||||
const QString & itemText( int i ) const
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
|
||||
const PixmapLoader* itemPixmap( int i ) const
|
||||
{
|
||||
return m_items[qBound<int>( minValue(), i, maxValue() )].second;
|
||||
return m_items[qBound<int>( minValue(), i, maxValue() )].second.get();
|
||||
}
|
||||
|
||||
int size() const
|
||||
@@ -82,9 +82,9 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
typedef QPair<QString, PixmapLoader *> Item;
|
||||
typedef std::pair<QString, std::unique_ptr<PixmapLoader> > Item;
|
||||
|
||||
QVector<Item> m_items;
|
||||
std::vector<Item> m_items;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -130,6 +130,7 @@ public:
|
||||
void removeConnection( ControllerConnection * );
|
||||
int connectionCount() const;
|
||||
|
||||
bool hasModel( const Model * m ) const;
|
||||
|
||||
public slots:
|
||||
virtual ControllerDialog * createDialog( QWidget * _parent );
|
||||
@@ -139,8 +140,6 @@ public slots:
|
||||
m_name = _new_name;
|
||||
}
|
||||
|
||||
bool hasModel( const Model * m );
|
||||
|
||||
|
||||
protected:
|
||||
// The internal per-controller get-value function
|
||||
|
||||
@@ -66,6 +66,7 @@ public slots:
|
||||
void selectController();
|
||||
void midiToggled();
|
||||
void userToggled();
|
||||
void userSelected();
|
||||
void autoDetectToggled();
|
||||
void enableAutoDetect( QAction * _a );
|
||||
|
||||
|
||||
@@ -245,15 +245,37 @@ namespace DspEffectLibrary
|
||||
} ;
|
||||
|
||||
|
||||
class FoldbackDistortion : public MonoBase<FoldbackDistortion>
|
||||
template<class T>
|
||||
class DistortionBase : public MonoBase<T>
|
||||
{
|
||||
public:
|
||||
FoldbackDistortion( float threshold, float gain ) :
|
||||
DistortionBase( float threshold, float gain ) :
|
||||
m_threshold( threshold ),
|
||||
m_gain( gain )
|
||||
{
|
||||
}
|
||||
|
||||
void setThreshold( float threshold )
|
||||
{
|
||||
m_threshold = threshold;
|
||||
}
|
||||
|
||||
void setGain( float gain )
|
||||
{
|
||||
m_gain = gain;
|
||||
}
|
||||
|
||||
protected:
|
||||
float m_threshold;
|
||||
float m_gain;
|
||||
};
|
||||
|
||||
|
||||
class FoldbackDistortion : public DistortionBase<FoldbackDistortion>
|
||||
{
|
||||
public:
|
||||
using DistortionBase<FoldbackDistortion>::DistortionBase;
|
||||
|
||||
sample_t nextSample( sample_t in )
|
||||
{
|
||||
if( in >= m_threshold || in < -m_threshold )
|
||||
@@ -262,54 +284,18 @@ namespace DspEffectLibrary
|
||||
}
|
||||
return in * m_gain;
|
||||
}
|
||||
|
||||
void setThreshold( float threshold )
|
||||
{
|
||||
m_threshold = threshold;
|
||||
}
|
||||
|
||||
void setGain( float gain )
|
||||
{
|
||||
m_gain = gain;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
float m_threshold;
|
||||
float m_gain;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
class Distortion : public MonoBase<Distortion>
|
||||
class Distortion : public DistortionBase<Distortion>
|
||||
{
|
||||
public:
|
||||
Distortion( float threshold, float gain ) :
|
||||
m_threshold( threshold ),
|
||||
m_gain( gain )
|
||||
{
|
||||
}
|
||||
using DistortionBase<Distortion>::DistortionBase;
|
||||
|
||||
sample_t nextSample( sample_t in )
|
||||
{
|
||||
return m_gain * ( in * ( fabsf( in )+m_threshold ) / ( in*in +( m_threshold-1 )* fabsf( in ) + 1 ) );
|
||||
}
|
||||
|
||||
void setThreshold( float threshold )
|
||||
{
|
||||
m_threshold = threshold;
|
||||
}
|
||||
|
||||
void setGain( float gain )
|
||||
{
|
||||
m_gain = gain;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
float m_threshold;
|
||||
float m_gain;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -57,11 +57,6 @@ public:
|
||||
|
||||
void clear();
|
||||
|
||||
void setEnabled( bool _on )
|
||||
{
|
||||
m_enabledModel.setValue( _on );
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
typedef QVector<Effect *> EffectList;
|
||||
|
||||
@@ -38,6 +38,16 @@ public:
|
||||
const QString &directory = QString(),
|
||||
const QString &filter = QString() );
|
||||
|
||||
static QString getExistingDirectory(QWidget *parent,
|
||||
const QString &caption,
|
||||
const QString &directory,
|
||||
QFileDialog::Options options = QFileDialog::ShowDirsOnly);
|
||||
static QString getOpenFileName(QWidget *parent = 0,
|
||||
const QString &caption = QString(),
|
||||
const QString &directory = QString(),
|
||||
const QString &filter = QString(),
|
||||
QString *selectedFilter = 0,
|
||||
QFileDialog::Options options = 0);
|
||||
void clearSelection();
|
||||
};
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "JournallingObject.h"
|
||||
#include "ThreadableJob.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
class FxRoute;
|
||||
typedef QVector<FxRoute *> FxRouteVector;
|
||||
@@ -70,7 +71,7 @@ class FxChannel : public ThreadableJob
|
||||
void unmuteForSolo();
|
||||
|
||||
|
||||
QAtomicInt m_dependenciesMet;
|
||||
std::atomic_int m_dependenciesMet;
|
||||
void incrementDeps();
|
||||
void processed();
|
||||
|
||||
|
||||
@@ -70,7 +70,6 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
typedef BoolModel groupBoxModel;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -59,7 +59,8 @@ public:
|
||||
for( const NotePlayHandle * constNotePlayHandle : nphv )
|
||||
{
|
||||
NotePlayHandle * notePlayHandle = const_cast<NotePlayHandle *>( constNotePlayHandle );
|
||||
if( notePlayHandle->state() != ThreadableJob::Done && ! notePlayHandle->isFinished() )
|
||||
if( notePlayHandle->state() != ThreadableJob::ProcessingState::Done &&
|
||||
!notePlayHandle->isFinished())
|
||||
{
|
||||
nphsLeft = true;
|
||||
notePlayHandle->process();
|
||||
|
||||
@@ -45,6 +45,7 @@ typedef enum BufferRates
|
||||
typedef enum BufferData
|
||||
{
|
||||
TOGGLED,
|
||||
ENUM,
|
||||
INTEGER,
|
||||
FLOATING,
|
||||
TIME,
|
||||
|
||||
@@ -179,6 +179,12 @@ public:
|
||||
be described as [-0.1, 3.1]. */
|
||||
bool isInteger( const ladspa_key_t & _plugin, uint32_t _port );
|
||||
|
||||
/* Indicates that a user interface would probably wish to provide a
|
||||
stepped control taking only integer values. This is equal to isInteger,
|
||||
but the number of values is usually small and may be better depicted
|
||||
with a combo box. */
|
||||
bool isEnum( const ladspa_key_t & _plugin, uint32_t _port );
|
||||
|
||||
/* Returns the name of the port. */
|
||||
QString getPortName( const ladspa_key_t & _plugin, uint32_t _port );
|
||||
|
||||
@@ -328,6 +334,11 @@ private:
|
||||
uint16_t getPluginInputs( const LADSPA_Descriptor * _descriptor );
|
||||
uint16_t getPluginOutputs( const LADSPA_Descriptor * _descriptor );
|
||||
|
||||
const LADSPA_PortDescriptor* getPortDescriptor( const ladspa_key_t& _plugin,
|
||||
uint32_t _port );
|
||||
const LADSPA_PortRangeHint* getPortRangeHint( const ladspa_key_t& _plugin,
|
||||
uint32_t _port );
|
||||
|
||||
typedef QMap<ladspa_key_t, ladspaManagerDescription *>
|
||||
ladspaManagerMapType;
|
||||
ladspaManagerMapType m_ladspaManagerMap;
|
||||
|
||||
@@ -25,10 +25,9 @@
|
||||
#ifndef LOCKLESS_ALLOCATOR_H
|
||||
#define LOCKLESS_ALLOCATOR_H
|
||||
|
||||
#include <atomic>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "AtomicInt.h"
|
||||
|
||||
class LocklessAllocator
|
||||
{
|
||||
public:
|
||||
@@ -43,11 +42,11 @@ private:
|
||||
size_t m_capacity;
|
||||
size_t m_elementSize;
|
||||
|
||||
AtomicInt * m_freeState;
|
||||
std::atomic_int * m_freeState;
|
||||
size_t m_freeStateSets;
|
||||
|
||||
AtomicInt m_available;
|
||||
AtomicInt m_startIndex;
|
||||
std::atomic_int m_available;
|
||||
std::atomic_int m_startIndex;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
#ifndef LOCKLESS_LIST_H
|
||||
#define LOCKLESS_LIST_H
|
||||
|
||||
#include <QAtomicPointer>
|
||||
|
||||
#include "LocklessAllocator.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
template<typename T>
|
||||
class LocklessList
|
||||
{
|
||||
@@ -39,9 +39,10 @@ public:
|
||||
Element * next;
|
||||
} ;
|
||||
|
||||
LocklessList( size_t size )
|
||||
LocklessList( size_t size ) :
|
||||
m_first(nullptr),
|
||||
m_allocator(new LocklessAllocatorT<Element>(size))
|
||||
{
|
||||
m_allocator = new LocklessAllocatorT<Element>( size );
|
||||
}
|
||||
|
||||
~LocklessList()
|
||||
@@ -53,39 +54,29 @@ public:
|
||||
{
|
||||
Element * e = m_allocator->alloc();
|
||||
e->value = value;
|
||||
e->next = m_first.load(std::memory_order_relaxed);
|
||||
|
||||
do
|
||||
while (!m_first.compare_exchange_weak(e->next, e,
|
||||
std::memory_order_release,
|
||||
std::memory_order_relaxed))
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
e->next = m_first.loadAcquire();
|
||||
#else
|
||||
e->next = m_first;
|
||||
#endif
|
||||
// Empty loop (compare_exchange_weak updates e->next)
|
||||
}
|
||||
while( !m_first.testAndSetOrdered( e->next, e ) );
|
||||
}
|
||||
|
||||
Element * popList()
|
||||
{
|
||||
return m_first.fetchAndStoreOrdered( NULL );
|
||||
return m_first.exchange(nullptr);
|
||||
}
|
||||
|
||||
Element * first()
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
return m_first.loadAcquire();
|
||||
#else
|
||||
return m_first;
|
||||
#endif
|
||||
return m_first.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
void setFirst( Element * e )
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
m_first.storeRelease( e );
|
||||
#else
|
||||
m_first = e;
|
||||
#endif
|
||||
m_first.store(e, std::memory_order_release);
|
||||
}
|
||||
|
||||
void free( Element * e )
|
||||
@@ -95,7 +86,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
QAtomicPointer<Element> m_first;
|
||||
std::atomic<Element*> m_first;
|
||||
LocklessAllocatorT<Element> * m_allocator;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
#ifndef MIXER_WORKER_THREAD_H
|
||||
#define MIXER_WORKER_THREAD_H
|
||||
|
||||
#include <AtomicInt.h>
|
||||
#include <QtCore/QAtomicPointer>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
class QWaitCondition;
|
||||
class Mixer;
|
||||
class ThreadableJob;
|
||||
@@ -46,12 +46,14 @@ public:
|
||||
Dynamic // jobs can be added while processing queue
|
||||
} ;
|
||||
|
||||
#define JOB_QUEUE_SIZE 1024
|
||||
JobQueue() :
|
||||
m_items(),
|
||||
m_queueSize( 0 ),
|
||||
m_itemsDone( 0 ),
|
||||
m_opMode( Static )
|
||||
{
|
||||
std::fill(m_items, m_items + JOB_QUEUE_SIZE, nullptr);
|
||||
}
|
||||
|
||||
void reset( OperationMode _opMode );
|
||||
@@ -62,10 +64,9 @@ public:
|
||||
void wait();
|
||||
|
||||
private:
|
||||
#define JOB_QUEUE_SIZE 1024
|
||||
QAtomicPointer<ThreadableJob> m_items[JOB_QUEUE_SIZE];
|
||||
AtomicInt m_queueSize;
|
||||
AtomicInt m_itemsDone;
|
||||
std::atomic<ThreadableJob*> m_items[JOB_QUEUE_SIZE];
|
||||
std::atomic_int m_queueSize;
|
||||
std::atomic_int m_itemsDone;
|
||||
OperationMode m_opMode;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
#ifndef NOTE_PLAY_HANDLE_H
|
||||
#define NOTE_PLAY_HANDLE_H
|
||||
|
||||
#include "AtomicInt.h"
|
||||
#include <memory>
|
||||
|
||||
#include "BasicFilters.h"
|
||||
#include "Note.h"
|
||||
#include "PlayHandle.h"
|
||||
@@ -46,7 +47,7 @@ class EXPORT NotePlayHandle : public PlayHandle, public Note
|
||||
MM_OPERATORS
|
||||
public:
|
||||
void * m_pluginData;
|
||||
BasicFilters<> * m_filter;
|
||||
std::unique_ptr<BasicFilters<>> m_filter;
|
||||
|
||||
// specifies origin of NotePlayHandle
|
||||
enum Origins
|
||||
@@ -348,7 +349,7 @@ public:
|
||||
private:
|
||||
static NotePlayHandle ** s_available;
|
||||
static QReadWriteLock s_mutex;
|
||||
static AtomicInt s_availableIndex;
|
||||
static std::atomic_int s_availableIndex;
|
||||
static int s_size;
|
||||
};
|
||||
|
||||
|
||||
73
include/PerfLog.h
Normal file
73
include/PerfLog.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* PerfLog.h - Small performance logger
|
||||
*
|
||||
* Copyright (c) 2017-2018 LMMS Developers
|
||||
*
|
||||
* 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 PERFLOG_H
|
||||
#define PERFLOG_H
|
||||
|
||||
#include <ctime>
|
||||
#include <QtCore/QString>
|
||||
|
||||
/// \brief CPU time point
|
||||
///
|
||||
/// Represents a point in CPU time (not wall-clock time) intended for measuring
|
||||
/// performance.
|
||||
class PerfTime
|
||||
{
|
||||
public:
|
||||
PerfTime();
|
||||
bool valid() const;
|
||||
|
||||
clock_t real() const;
|
||||
clock_t user() const;
|
||||
clock_t system() const;
|
||||
|
||||
static PerfTime now();
|
||||
static clock_t ticksPerSecond();
|
||||
|
||||
friend PerfTime operator-(const PerfTime& lhs, const PerfTime& rhs);
|
||||
private:
|
||||
clock_t m_real;
|
||||
clock_t m_user;
|
||||
clock_t m_system;
|
||||
};
|
||||
|
||||
/// \brief The PerfLog class
|
||||
///
|
||||
/// Measures time between construction and destruction and prints the result to
|
||||
/// stderr, along with \p name. Alternatively, call begin() and end() explicitly.
|
||||
class PerfLogTimer
|
||||
{
|
||||
public:
|
||||
PerfLogTimer(const QString& name);
|
||||
~PerfLogTimer();
|
||||
|
||||
void begin();
|
||||
void end();
|
||||
|
||||
private:
|
||||
QString name;
|
||||
PerfTime begin_time;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef RENDER_MANAGER_H
|
||||
#define RENDER_MANAGER_H
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "ProjectRenderer.h"
|
||||
#include "OutputSettings.h"
|
||||
@@ -64,13 +64,15 @@ private:
|
||||
QString pathForTrack( const Track *track, int num );
|
||||
void restoreMutedState();
|
||||
|
||||
void render( QString outputPath );
|
||||
|
||||
const Mixer::qualitySettings m_qualitySettings;
|
||||
const Mixer::qualitySettings m_oldQualitySettings;
|
||||
const OutputSettings m_outputSettings;
|
||||
ProjectRenderer::ExportFileFormats m_format;
|
||||
QString m_outputPath;
|
||||
|
||||
ProjectRenderer* m_activeRenderer;
|
||||
std::unique_ptr<ProjectRenderer> m_activeRenderer;
|
||||
|
||||
QVector<Track*> m_tracksToRender;
|
||||
QVector<Track*> m_unmuted;
|
||||
|
||||
@@ -103,12 +103,12 @@ public:
|
||||
} ;
|
||||
|
||||
|
||||
SampleBuffer();
|
||||
// constructor which either loads sample _audio_file or decodes
|
||||
// base64-data out of string
|
||||
SampleBuffer( const QString & _audio_file = QString(),
|
||||
bool _is_base64_data = false );
|
||||
SampleBuffer( const QString & _audio_file, bool _is_base64_data = false );
|
||||
SampleBuffer( const sampleFrame * _data, const f_cnt_t _frames );
|
||||
SampleBuffer( const f_cnt_t _frames );
|
||||
explicit SampleBuffer( const f_cnt_t _frames );
|
||||
|
||||
virtual ~SampleBuffer();
|
||||
|
||||
|
||||
@@ -38,8 +38,8 @@ class AudioPort;
|
||||
class SamplePlayHandle : public PlayHandle
|
||||
{
|
||||
public:
|
||||
SamplePlayHandle( const QString& sampleFile );
|
||||
SamplePlayHandle( SampleBuffer* sampleBuffer );
|
||||
SamplePlayHandle( const QString& sampleFile );
|
||||
SamplePlayHandle( SampleTCO* tco );
|
||||
virtual ~SamplePlayHandle();
|
||||
|
||||
|
||||
@@ -25,16 +25,15 @@
|
||||
#ifndef THREADABLE_JOB_H
|
||||
#define THREADABLE_JOB_H
|
||||
|
||||
#include "AtomicInt.h"
|
||||
|
||||
#include "lmms_basics.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
class ThreadableJob
|
||||
{
|
||||
public:
|
||||
|
||||
enum ProcessingState
|
||||
enum class ProcessingState : int
|
||||
{
|
||||
Unstarted,
|
||||
Queued,
|
||||
@@ -43,36 +42,37 @@ public:
|
||||
};
|
||||
|
||||
ThreadableJob() :
|
||||
m_state( ThreadableJob::Unstarted )
|
||||
m_state(ProcessingState::Unstarted)
|
||||
{
|
||||
}
|
||||
|
||||
inline ProcessingState state() const
|
||||
{
|
||||
return static_cast<ProcessingState>( (int) m_state );
|
||||
return m_state.load();
|
||||
}
|
||||
|
||||
inline void reset()
|
||||
{
|
||||
m_state = Unstarted;
|
||||
m_state = ProcessingState::Unstarted;
|
||||
}
|
||||
|
||||
inline void queue()
|
||||
{
|
||||
m_state = Queued;
|
||||
m_state = ProcessingState::Queued;
|
||||
}
|
||||
|
||||
inline void done()
|
||||
{
|
||||
m_state = Done;
|
||||
m_state = ProcessingState::Done;
|
||||
}
|
||||
|
||||
void process()
|
||||
{
|
||||
if( m_state.testAndSetOrdered( Queued, InProgress ) )
|
||||
auto expected = ProcessingState::Queued;
|
||||
if (m_state.compare_exchange_strong(expected, ProcessingState::InProgress))
|
||||
{
|
||||
doProcessing();
|
||||
m_state = Done;
|
||||
m_state = ProcessingState::Done;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,7 @@ public:
|
||||
protected:
|
||||
virtual void doProcessing() = 0;
|
||||
|
||||
AtomicInt m_state;
|
||||
|
||||
std::atomic<ProcessingState> m_state;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -438,6 +438,7 @@ private slots:
|
||||
void cloneTrack();
|
||||
void removeTrack();
|
||||
void updateMenu();
|
||||
void toggleRecording(bool on);
|
||||
void recordingOn();
|
||||
void recordingOff();
|
||||
void clearTrack();
|
||||
|
||||
@@ -69,25 +69,6 @@ private slots:
|
||||
|
||||
|
||||
private:
|
||||
struct VstSyncData
|
||||
{
|
||||
bool isPlaying;
|
||||
float ppqPos;
|
||||
int timeSigNumer;
|
||||
int timeSigDenom;
|
||||
bool isCycle;
|
||||
bool hasSHM;
|
||||
float cycleStart;
|
||||
float cycleEnd;
|
||||
int m_bufferSize;
|
||||
int m_sampleRate;
|
||||
int m_bpm;
|
||||
|
||||
#ifdef VST_SNC_LATENCY
|
||||
float m_latency;
|
||||
#endif
|
||||
} ;
|
||||
|
||||
VstSyncData* m_syncData;
|
||||
|
||||
int m_shmID;
|
||||
|
||||
@@ -26,15 +26,13 @@
|
||||
#ifndef SHARED_OBJECT_H
|
||||
#define SHARED_OBJECT_H
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
class sharedObject
|
||||
{
|
||||
public:
|
||||
sharedObject() :
|
||||
m_referenceCount( 1 ),
|
||||
m_lock()
|
||||
m_referenceCount(1)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -45,19 +43,34 @@ public:
|
||||
template<class T>
|
||||
static T* ref( T* object )
|
||||
{
|
||||
object->m_lock.lock();
|
||||
// TODO: Use QShared
|
||||
++object->m_referenceCount;
|
||||
object->m_lock.unlock();
|
||||
// Incrementing an atomic reference count can be relaxed since no action
|
||||
// is ever taken as a result of increasing the count.
|
||||
// Other loads and stores can be reordered around this without consequence.
|
||||
object->m_referenceCount.fetch_add(1, std::memory_order_relaxed);
|
||||
return object;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void unref( T* object )
|
||||
{
|
||||
object->m_lock.lock();
|
||||
bool deleteObject = --object->m_referenceCount <= 0;
|
||||
object->m_lock.unlock();
|
||||
// When decrementing an atomic reference count, we need to provide
|
||||
// two ordering guarantees:
|
||||
// 1. All reads and writes to the referenced object occur before
|
||||
// the count reaches zero.
|
||||
// 2. Deletion occurs after the count reaches zero.
|
||||
//
|
||||
// To accomplish this, each decrement must be store-released,
|
||||
// and the final thread (which is deleting the referenced data)
|
||||
// must load-acquire those stores.
|
||||
// The simplest way to do this to give the decrement acquire-release
|
||||
// semantics.
|
||||
//
|
||||
// See https://www.boost.org/doc/libs/1_67_0/doc/html/atomic/usage_examples.html
|
||||
// for further discussion, along with a slightly more complicated
|
||||
// (but possibly more performant on weakly-ordered hardware like ARM)
|
||||
// approach.
|
||||
const bool deleteObject =
|
||||
object->m_referenceCount.fetch_sub(1, std::memory_order_acq_rel) == 1;
|
||||
|
||||
if ( deleteObject )
|
||||
{
|
||||
@@ -65,20 +78,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// keep clang happy which complaines about unused member variable
|
||||
void dummy()
|
||||
{
|
||||
m_referenceCount = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_referenceCount;
|
||||
QMutex m_lock;
|
||||
|
||||
std::atomic_int m_referenceCount;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
25
include/stdshims.h
Normal file
25
include/stdshims.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//! Shims for std:: functions that aren't available in the current C++ versions
|
||||
//! we target.
|
||||
|
||||
#ifndef STDSHIMS_H
|
||||
#define STDSHIMS_H
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#if (__cplusplus >= 201402L)
|
||||
#warning "This file should now be removed! The functions it provides are part of the C++14 standard."
|
||||
using std::make_unique;
|
||||
|
||||
#else
|
||||
|
||||
/// Shim for http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique
|
||||
template<typename T, typename... Args>
|
||||
std::unique_ptr<T> make_unique(Args&&... args)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // include guard
|
||||
|
||||
@@ -26,12 +26,13 @@
|
||||
|
||||
#include <QDomElement>
|
||||
|
||||
#include "BasicFilters.h"
|
||||
#include "DualFilterControls.h"
|
||||
#include "DualFilter.h"
|
||||
#include "embed.h"
|
||||
#include "Engine.h"
|
||||
#include "Song.h"
|
||||
#include "BasicFilters.h"
|
||||
#include "embed.h"
|
||||
#include "stdshims.h"
|
||||
|
||||
DualFilterControls::DualFilterControls( DualFilterEffect* effect ) :
|
||||
EffectControls( effect ),
|
||||
@@ -51,51 +52,51 @@ DualFilterControls::DualFilterControls( DualFilterEffect* effect ) :
|
||||
m_res2Model( 0.5, BasicFilters<>::minQ(), 10.0, 0.01, this, tr( "Q/Resonance 2" ) ),
|
||||
m_gain2Model( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Gain 2" ) )
|
||||
{
|
||||
m_filter1Model.addItem( tr( "LowPass" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "HiPass" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "BandPass csg" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filter1Model.addItem( tr( "BandPass czpg" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filter1Model.addItem( tr( "Notch" ), new PixmapLoader( "filter_notch" ) );
|
||||
m_filter1Model.addItem( tr( "Allpass" ), new PixmapLoader( "filter_ap" ) );
|
||||
m_filter1Model.addItem( tr( "Moog" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "2x LowPass" ), new PixmapLoader( "filter_2lp" ) );
|
||||
m_filter1Model.addItem( tr( "RC LowPass 12dB" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "RC BandPass 12dB" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filter1Model.addItem( tr( "RC HighPass 12dB" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "RC LowPass 24dB" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "RC BandPass 24dB" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filter1Model.addItem( tr( "RC HighPass 24dB" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "Vocal Formant Filter" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "2x Moog" ), new PixmapLoader( "filter_2lp" ) );
|
||||
m_filter1Model.addItem( tr( "SV LowPass" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "SV BandPass" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filter1Model.addItem( tr( "SV HighPass" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "SV Notch" ), new PixmapLoader( "filter_notch" ) );
|
||||
m_filter1Model.addItem( tr( "Fast Formant" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "Tripole" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "LowPass" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "HiPass" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "BandPass csg" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filter1Model.addItem( tr( "BandPass czpg" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filter1Model.addItem( tr( "Notch" ), make_unique<PixmapLoader>( "filter_notch" ) );
|
||||
m_filter1Model.addItem( tr( "Allpass" ), make_unique<PixmapLoader>( "filter_ap" ) );
|
||||
m_filter1Model.addItem( tr( "Moog" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "2x LowPass" ), make_unique<PixmapLoader>( "filter_2lp" ) );
|
||||
m_filter1Model.addItem( tr( "RC LowPass 12dB" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "RC BandPass 12dB" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filter1Model.addItem( tr( "RC HighPass 12dB" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "RC LowPass 24dB" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "RC BandPass 24dB" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filter1Model.addItem( tr( "RC HighPass 24dB" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "Vocal Formant Filter" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "2x Moog" ), make_unique<PixmapLoader>( "filter_2lp" ) );
|
||||
m_filter1Model.addItem( tr( "SV LowPass" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filter1Model.addItem( tr( "SV BandPass" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filter1Model.addItem( tr( "SV HighPass" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "SV Notch" ), make_unique<PixmapLoader>( "filter_notch" ) );
|
||||
m_filter1Model.addItem( tr( "Fast Formant" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter1Model.addItem( tr( "Tripole" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
|
||||
m_filter2Model.addItem( tr( "LowPass" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "HiPass" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "BandPass csg" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filter2Model.addItem( tr( "BandPass czpg" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filter2Model.addItem( tr( "Notch" ), new PixmapLoader( "filter_notch" ) );
|
||||
m_filter2Model.addItem( tr( "Allpass" ), new PixmapLoader( "filter_ap" ) );
|
||||
m_filter2Model.addItem( tr( "Moog" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "2x LowPass" ), new PixmapLoader( "filter_2lp" ) );
|
||||
m_filter2Model.addItem( tr( "RC LowPass 12dB" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "RC BandPass 12dB" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filter2Model.addItem( tr( "RC HighPass 12dB" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "RC LowPass 24dB" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "RC BandPass 24dB" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filter2Model.addItem( tr( "RC HighPass 24dB" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "Vocal Formant Filter" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "2x Moog" ), new PixmapLoader( "filter_2lp" ) );
|
||||
m_filter2Model.addItem( tr( "SV LowPass" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "SV BandPass" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filter2Model.addItem( tr( "SV HighPass" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "SV Notch" ), new PixmapLoader( "filter_notch" ) );
|
||||
m_filter2Model.addItem( tr( "Fast Formant" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "Tripole" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "LowPass" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "HiPass" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "BandPass csg" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filter2Model.addItem( tr( "BandPass czpg" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filter2Model.addItem( tr( "Notch" ), make_unique<PixmapLoader>( "filter_notch" ) );
|
||||
m_filter2Model.addItem( tr( "Allpass" ), make_unique<PixmapLoader>( "filter_ap" ) );
|
||||
m_filter2Model.addItem( tr( "Moog" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "2x LowPass" ), make_unique<PixmapLoader>( "filter_2lp" ) );
|
||||
m_filter2Model.addItem( tr( "RC LowPass 12dB" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "RC BandPass 12dB" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filter2Model.addItem( tr( "RC HighPass 12dB" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "RC LowPass 24dB" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "RC BandPass 24dB" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filter2Model.addItem( tr( "RC HighPass 24dB" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "Vocal Formant Filter" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "2x Moog" ), make_unique<PixmapLoader>( "filter_2lp" ) );
|
||||
m_filter2Model.addItem( tr( "SV LowPass" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filter2Model.addItem( tr( "SV BandPass" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filter2Model.addItem( tr( "SV HighPass" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "SV Notch" ), make_unique<PixmapLoader>( "filter_notch" ) );
|
||||
m_filter2Model.addItem( tr( "Fast Formant" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filter2Model.addItem( tr( "Tripole" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
|
||||
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateFilters() ) );
|
||||
}
|
||||
|
||||
@@ -112,10 +112,10 @@ void LadspaControlDialog::updateEffectView( LadspaControls * _ctl )
|
||||
{
|
||||
if( (*it)->port()->proc == proc )
|
||||
{
|
||||
buffer_data_t this_port = (*it)->port()->data_type;
|
||||
if( last_port != NONE &&
|
||||
(*it)->port()->data_type == TOGGLED &&
|
||||
!( (*it)->port()->data_type == TOGGLED &&
|
||||
last_port == TOGGLED ) )
|
||||
( this_port == TOGGLED || this_port == ENUM ) &&
|
||||
( last_port != TOGGLED && last_port != ENUM ) )
|
||||
{
|
||||
++row;
|
||||
col = 0;
|
||||
|
||||
@@ -371,7 +371,11 @@ void LadspaEffect::pluginInstantiation()
|
||||
}
|
||||
|
||||
p->scale = 1.0f;
|
||||
if( manager->isPortToggled( m_key, port ) )
|
||||
if( manager->isEnum( m_key, port ) )
|
||||
{
|
||||
p->data_type = ENUM;
|
||||
}
|
||||
else if( manager->isPortToggled( m_key, port ) )
|
||||
{
|
||||
p->data_type = TOGGLED;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Note:
|
||||
# The last version of Calf that was LADSPA-capable is version 0.0.18.2
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
# Parse version info from autoconf
|
||||
FILE(READ veal/configure.ac VERSION_FILE)
|
||||
STRING(REPLACE "[" ";" VERSION_FILE ${VERSION_FILE} )
|
||||
@@ -12,7 +14,7 @@ FILE(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/veal/src/*.cpp")
|
||||
LIST(SORT SOURCES)
|
||||
|
||||
# Skip files matching pattern
|
||||
SET(FILE_PATTERNS "ctl;gui;gtk;session;connector;jack;rdf;draw;fluid;preset;lv2;benchmark;win")
|
||||
SET(FILE_PATTERNS "ctl;gui;gtk;session;connector;jack;rdf;draw;fluid;preset;lv2;benchmark;win;plugin.cpp")
|
||||
FOREACH(_item ${SOURCES})
|
||||
FOREACH(_pattern ${FILE_PATTERNS})
|
||||
IF(${_item} MATCHES ${_pattern})
|
||||
@@ -29,6 +31,10 @@ INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include"
|
||||
|
||||
INSTALL(TARGETS veal LIBRARY DESTINATION "${PLUGIN_DIR}/ladspa")
|
||||
SET_TARGET_PROPERTIES(veal PROPERTIES PREFIX "")
|
||||
|
||||
# Disable OSC messaging, it's not mingw compatible
|
||||
TARGET_COMPILE_DEFINITIONS(veal PRIVATE DISABLE_OSC=1)
|
||||
|
||||
SET(INLINE_FLAGS "")
|
||||
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
SET(INLINE_FLAGS "-finline-functions-called-once -finline-limit=80")
|
||||
@@ -42,4 +48,3 @@ ENDIF()
|
||||
IF(NOT LMMS_BUILD_APPLE AND NOT LMMS_BUILD_OPENBSD)
|
||||
SET_TARGET_PROPERTIES(veal PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined")
|
||||
ENDIF()
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#define VERSION "${VERSION}"
|
||||
#define PACKAGE_NAME "veal"
|
||||
#define USE_LADSPA 1
|
||||
#define PKGLIBDIR ""
|
||||
|
||||
// Namespace change to avoid conflict with LV2
|
||||
#define calf_plugins veal_plugins
|
||||
|
||||
Submodule plugins/LadspaEffect/calf/veal updated: 816b4d2b7c...2841b05a36
@@ -17,7 +17,7 @@ ENDIF()
|
||||
|
||||
# Additional compile flags
|
||||
SET(COMPILE_FLAGS "${COMPILE_FLAGS} -O3 -Wall")
|
||||
SET(COMPILE_FLAGS "${COMPILE_FLAGS} -fomit-frame-pointer -fstrength-reduce -funroll-loops -ffast-math -c -fno-strict-aliasing")
|
||||
SET(COMPILE_FLAGS "${COMPILE_FLAGS} -fomit-frame-pointer -funroll-loops -ffast-math -c -fno-strict-aliasing")
|
||||
SET(COMPILE_FLAGS "${COMPILE_FLAGS} ${PIC_FLAGS}")
|
||||
|
||||
# Loop over every XML file
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include")
|
||||
FILE(GLOB PLUGIN_SOURCES tap-plugins/*.c)
|
||||
LIST(SORT PLUGIN_SOURCES)
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wno-write-strings -fomit-frame-pointer -fno-strict-aliasing -fstrength-reduce -funroll-loops -ffast-math")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wno-write-strings -fomit-frame-pointer -fno-strict-aliasing -funroll-loops -ffast-math")
|
||||
FOREACH(_item ${PLUGIN_SOURCES})
|
||||
GET_FILENAME_COMPONENT(_plugin "${_item}" NAME_WE)
|
||||
ADD_LIBRARY("${_plugin}" MODULE "${_item}")
|
||||
|
||||
@@ -296,6 +296,44 @@ inline unsigned int rotateLeft(unsigned int x, const int b)
|
||||
return x;
|
||||
}
|
||||
|
||||
struct RandomVectorSeedFunction : public exprtk::ifunction<float>
|
||||
{
|
||||
using exprtk::ifunction<float>::operator();
|
||||
|
||||
RandomVectorSeedFunction() :
|
||||
exprtk::ifunction<float>(2)
|
||||
{ exprtk::disable_has_side_effects(*this); }
|
||||
|
||||
static inline float randv(const float& index,int irseed)
|
||||
{
|
||||
if (index < 0 || std::isnan(index) || std::isinf(index))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const unsigned int xi = (unsigned int)index;
|
||||
const unsigned int si = irseed % data_size;
|
||||
const unsigned int sa = irseed / data_size;
|
||||
unsigned int res=rotateLeft(random_data[(xi + 23 * si + 1) % data_size] ^ random_data[(xi / data_size + sa) % data_size],sa % 31 + 1);
|
||||
res ^= rotateLeft(random_data[(3 * xi + si + 13) % data_size],(xi+2*si) % 32) ^rotateLeft( random_data[(xi / data_size + 2 * sa) % data_size],xi % 31 + 1);
|
||||
return static_cast<int>(res) / (float)(1 << 31);
|
||||
}
|
||||
|
||||
inline float operator()(const float& index,const float& seed)
|
||||
{
|
||||
int irseed;
|
||||
if (seed < 0 || std::isnan(seed) || std::isinf(seed))
|
||||
{
|
||||
irseed=0;
|
||||
}
|
||||
else
|
||||
irseed=(int)seed;
|
||||
return randv(index,irseed);
|
||||
}
|
||||
|
||||
static const int data_size=sizeof(random_data)/sizeof(int);
|
||||
};
|
||||
static RandomVectorSeedFunction randsv_func;
|
||||
|
||||
struct RandomVectorFunction : public exprtk::ifunction<float>
|
||||
{
|
||||
using exprtk::ifunction<float>::operator();
|
||||
@@ -307,19 +345,9 @@ struct RandomVectorFunction : public exprtk::ifunction<float>
|
||||
|
||||
inline float operator()(const float& index)
|
||||
{
|
||||
if (index < 0 || std::isnan(index) || std::isinf(index))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const unsigned int xi = (unsigned int)index;
|
||||
const unsigned int si = m_rseed % data_size;
|
||||
const unsigned int sa = m_rseed / data_size;
|
||||
unsigned int res=rotateLeft(random_data[(xi + si) % data_size] ^ random_data[(xi / data_size + sa) % data_size],sa % 31 + 1);
|
||||
res ^= rotateLeft(random_data[(3 * xi + si) % data_size] ^ random_data[(xi / data_size + 2 * sa) % data_size],xi % 31 + 1);
|
||||
return static_cast<int>(res) / (float)(1 << 31);
|
||||
return RandomVectorSeedFunction::randv(index,m_rseed);
|
||||
}
|
||||
|
||||
const int data_size=sizeof(random_data)/sizeof(int);
|
||||
const unsigned int m_rseed;
|
||||
};
|
||||
|
||||
@@ -340,10 +368,10 @@ static freefunc0<float,SimpleRandom::float_random_with_engine,false> simple_rand
|
||||
class ExprFrontData
|
||||
{
|
||||
public:
|
||||
ExprFrontData():
|
||||
ExprFrontData(int last_func_samples):
|
||||
m_rand_vec(SimpleRandom::generator()),
|
||||
m_integ_func(NULL),
|
||||
m_last_func(500)
|
||||
m_last_func(last_func_samples)
|
||||
{}
|
||||
~ExprFrontData()
|
||||
{
|
||||
@@ -369,6 +397,7 @@ public:
|
||||
RandomVectorFunction m_rand_vec;
|
||||
IntegrateFunction<float> *m_integ_func;
|
||||
LastSampleFunction<float> m_last_func;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -489,17 +518,19 @@ struct harmonic_semitone
|
||||
static freefunc1<float,harmonic_semitone,true> harmonic_semitone_func;
|
||||
|
||||
|
||||
ExprFront::ExprFront(const char * expr)
|
||||
ExprFront::ExprFront(const char * expr, int last_func_samples)
|
||||
{
|
||||
m_valid = false;
|
||||
try
|
||||
{
|
||||
m_data = new ExprFrontData();
|
||||
m_data = new ExprFrontData(last_func_samples);
|
||||
|
||||
m_data->m_expression_string = expr;
|
||||
m_data->m_symbol_table.add_pi();
|
||||
|
||||
m_data->m_symbol_table.add_constant("e", F_E);
|
||||
|
||||
m_data->m_symbol_table.add_constant("seed", SimpleRandom::generator() & max_float_integer_mask);
|
||||
|
||||
m_data->m_symbol_table.add_function("sinew", sin_wave_func);
|
||||
m_data->m_symbol_table.add_function("squarew", square_wave_func);
|
||||
@@ -513,6 +544,7 @@ ExprFront::ExprFront(const char * expr)
|
||||
m_data->m_symbol_table.add_function("semitone", harmonic_semitone_func);
|
||||
m_data->m_symbol_table.add_function("rand", simple_rand);
|
||||
m_data->m_symbol_table.add_function("randv", m_data->m_rand_vec);
|
||||
m_data->m_symbol_table.add_function("randsv", randsv_func);
|
||||
m_data->m_symbol_table.add_function("last", m_data->m_last_func);
|
||||
}
|
||||
catch(...)
|
||||
@@ -742,7 +774,7 @@ void ExprSynth::renderOutput(fpp_t frames, sampleFrame *buf)
|
||||
}
|
||||
o1 = o1_rawExpr->value();
|
||||
o2 = o2_rawExpr->value();
|
||||
last_func1->setLastSample(o1);
|
||||
last_func1->setLastSample(o1);//put result in the circular buffer for the "last" function.
|
||||
last_func2->setLastSample(o2);
|
||||
buf[frame][0] = (-pn1 + 0.5) * o1 + (-pn2 + 0.5) * o2;
|
||||
buf[frame][1] = ( pn1 + 0.5) * o1 + ( pn2 + 0.5) * o2;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include "AutomatableModel.h"
|
||||
#include "Graph.h"
|
||||
#include "Instrument.h"
|
||||
@@ -39,7 +40,7 @@ class ExprFront
|
||||
{
|
||||
public:
|
||||
typedef float (*ff1data_functor)(void*, float);
|
||||
ExprFront(const char* expr);
|
||||
ExprFront(const char* expr, int last_func_samples);
|
||||
~ExprFront();
|
||||
bool compile();
|
||||
inline bool isValid() { return m_valid; }
|
||||
@@ -52,6 +53,9 @@ public:
|
||||
private:
|
||||
ExprFrontData *m_data;
|
||||
bool m_valid;
|
||||
|
||||
static const int max_float_integer_mask=(1<<(std::numeric_limits<float>::digits))-1;
|
||||
|
||||
};
|
||||
|
||||
class WaveSample
|
||||
|
||||
@@ -202,23 +202,24 @@ void Xpressive::playNote(NotePlayHandle* nph, sampleFrame* working_buffer) {
|
||||
|
||||
if (nph->totalFramesPlayed() == 0 || nph->m_pluginData == NULL) {
|
||||
|
||||
ExprFront *exprO1 = new ExprFront(m_outputExpression[0].constData());
|
||||
ExprFront *exprO2 = new ExprFront(m_outputExpression[1].constData());
|
||||
ExprFront *exprO1 = new ExprFront(m_outputExpression[0].constData(),Engine::mixer()->processingSampleRate());//give the "last" function a whole second
|
||||
ExprFront *exprO2 = new ExprFront(m_outputExpression[1].constData(),Engine::mixer()->processingSampleRate());
|
||||
|
||||
auto init_expression_step1 = [this, nph](ExprFront* e) {
|
||||
e->add_constant("key", nph->key());
|
||||
e->add_constant("bnote", nph->instrumentTrack()->baseNote());
|
||||
e->add_constant("srate", Engine::mixer()->processingSampleRate());
|
||||
e->add_constant("v", nph->getVolume() / 255.0);
|
||||
e->add_constant("tempo", Engine::getSong()->getTempo());
|
||||
e->add_variable("A1", m_A1);
|
||||
auto init_expression_step1 = [this, nph](ExprFront* e) { //lambda function to init exprO1 and exprO2
|
||||
//add the constants and the variables to the expression.
|
||||
e->add_constant("key", nph->key());//the key that was pressed.
|
||||
e->add_constant("bnote", nph->instrumentTrack()->baseNote()); // the base note
|
||||
e->add_constant("srate", Engine::mixer()->processingSampleRate());// sample rate of the mixer
|
||||
e->add_constant("v", nph->getVolume() / 255.0); //volume of the note.
|
||||
e->add_constant("tempo", Engine::getSong()->getTempo());//tempo of the song.
|
||||
e->add_variable("A1", m_A1);//A1,A2,A3: general purpose input controls.
|
||||
e->add_variable("A2", m_A2);
|
||||
e->add_variable("A3", m_A3);
|
||||
};
|
||||
init_expression_step1(exprO1);
|
||||
init_expression_step1(exprO2);
|
||||
|
||||
m_W1.setInterpolate(m_interpolateW1.value());
|
||||
m_W1.setInterpolate(m_interpolateW1.value());//set interpolation according to the user selection.
|
||||
m_W2.setInterpolate(m_interpolateW2.value());
|
||||
m_W3.setInterpolate(m_interpolateW3.value());
|
||||
nph->m_pluginData = new ExprSynth(&m_W1, &m_W2, &m_W3, exprO1, exprO2, nph,
|
||||
@@ -520,11 +521,11 @@ void XpressiveView::expressionChanged() {
|
||||
|
||||
if (text.size()>0)
|
||||
{
|
||||
ExprFront expr(text.constData());
|
||||
const unsigned int sample_rate=m_raw_graph->length();
|
||||
ExprFront expr(text.constData(),sample_rate);
|
||||
float t=0;
|
||||
const float f=10,key=5,v=0.5;
|
||||
unsigned int i;
|
||||
const unsigned int sample_rate=m_raw_graph->length();
|
||||
expr.add_variable("t", t);
|
||||
|
||||
if (m_output_expr)
|
||||
@@ -776,7 +777,7 @@ void XpressiveView::sqrWaveClicked() {
|
||||
}
|
||||
|
||||
void XpressiveView::noiseWaveClicked() {
|
||||
m_expressionEditor->appendPlainText("rand");
|
||||
m_expressionEditor->appendPlainText("randsv(t*srate,0)");
|
||||
Engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
@@ -821,13 +822,14 @@ QString XpressiveHelpView::s_helpText=
|
||||
"<b>rel</b> - Gives 0.0 while the key is holded, and 1.0 after the key release. Available only in the output expressions.<br>"
|
||||
"<b>trel</b> - Time after release. While the note is holded, it gives 0.0. Afterwards, it start counting seconds.<br>"
|
||||
"The time it takes to shift from 0.0 to 1.0 after key release is determined by the REL knob<br>"
|
||||
"<b>seed</b> - A random value that remains consistent in the lifetime of a single wave. meant to be used with <b>randsv</b><br>"
|
||||
"<b>A1, A2, A3</b> - General purpose knobs. You can reference them only in O1 and O2. In range [-1,1].<br>"
|
||||
"<h4>Available functions:</h4><br>"
|
||||
"<b>W1, W2, W3</b> - As mentioned before. You can reference them only in O1 and O2.<br>"
|
||||
"<b>cent(x)</b> - Gives pow(2,x/1200), so you can multiply it with the f variable to pitch the frequency.<br>"
|
||||
"100 cents equals one semitone<br>"
|
||||
"<b>semitone(x)</b> - Gives pow(2,x/12), so you can multiply it with the f variable to pitch the frequency.<br>"
|
||||
"<b>last(n)</b> - Gives you the last n'th evaluated sample. The argument n must be in the range [1,500], or else, it will return 0.<br>"
|
||||
"<b>last(n)</b> - Gives you the last n'th evaluated sample. In O1 and O2 it keeps a whole second. Thus the argument n must be in the range [1,srate], or else, it will return 0.<br>"
|
||||
"<b>integrate(x)</b> - Integrates x by delta t (It sums values and divides them by sample rate).<br>"
|
||||
"If you use notes with automated frequency, you should use:<br>"
|
||||
"sinew(integrate(f)) instead of sinew(t*f)<br>"
|
||||
@@ -838,6 +840,9 @@ QString XpressiveHelpView::s_helpText=
|
||||
"and every reference to randv(a) will give you the same value."
|
||||
"If you want a random wave you can use randv(t*srate).<br>"
|
||||
"Each random value is in the range [-1,1).<br>"
|
||||
"<b>randsv(x,seed)</b> - works exactly like randv(x),<br>"
|
||||
"except that it lets you to select the seed manualy,<br>"
|
||||
"if you want to try different random values and make it consistent in each evaluation.<br>"
|
||||
"<b>sinew(x)</b> - A sine wave with period of 1 (In contrast to real sine wave which have a period of 2*pi).<br>"
|
||||
"<b>trianglew(x)</b> - A triangle wave with period of 1.<br>"
|
||||
"<b>squarew(x)</b> - A square wave with period of 1.<br>"
|
||||
|
||||
Submodule plugins/Xpressive/exprtk updated: aad301a6eb...f32d2b4bbb
@@ -38,6 +38,7 @@
|
||||
#include "Oscillator.h"
|
||||
#include "lmms_math.h"
|
||||
#include "BandLimitedWave.h"
|
||||
#include "stdshims.h"
|
||||
|
||||
//
|
||||
// UI Macros
|
||||
@@ -305,35 +306,35 @@ class MonstroInstrument : public Instrument
|
||||
Q_OBJECT
|
||||
|
||||
#define setwavemodel( name ) \
|
||||
name .addItem( tr( "Sine wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "sin" ) ) ); \
|
||||
name .addItem( tr( "Bandlimited Triangle wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "tri" ) ) ); \
|
||||
name .addItem( tr( "Bandlimited Saw wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "saw" ) ) ); \
|
||||
name .addItem( tr( "Bandlimited Ramp wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "ramp" ) ) ); \
|
||||
name .addItem( tr( "Bandlimited Square wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "sqr" ) ) ); \
|
||||
name .addItem( tr( "Bandlimited Moog saw wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "moog" ) ) ); \
|
||||
name .addItem( tr( "Soft square wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "sqrsoft" ) ) ); \
|
||||
name .addItem( tr( "Absolute sine wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "sinabs" ) ) ); \
|
||||
name .addItem( tr( "Exponential wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "exp" ) ) ); \
|
||||
name .addItem( tr( "White noise" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "noise" ) ) ); \
|
||||
name .addItem( tr( "Digital Triangle wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "tri" ) ) ); \
|
||||
name .addItem( tr( "Digital Saw wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "saw" ) ) ); \
|
||||
name .addItem( tr( "Digital Ramp wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "ramp" ) ) ); \
|
||||
name .addItem( tr( "Digital Square wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "sqr" ) ) ); \
|
||||
name .addItem( tr( "Digital Moog saw wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "moog" ) ) );
|
||||
name .addItem( tr( "Sine wave" ), make_unique<PluginPixmapLoader>( "sin" ) ); \
|
||||
name .addItem( tr( "Bandlimited Triangle wave" ), make_unique<PluginPixmapLoader>( "tri" ) ); \
|
||||
name .addItem( tr( "Bandlimited Saw wave" ), make_unique<PluginPixmapLoader>( "saw" ) ); \
|
||||
name .addItem( tr( "Bandlimited Ramp wave" ), make_unique<PluginPixmapLoader>( "ramp" ) ); \
|
||||
name .addItem( tr( "Bandlimited Square wave" ), make_unique<PluginPixmapLoader>( "sqr" ) ); \
|
||||
name .addItem( tr( "Bandlimited Moog saw wave" ), make_unique<PluginPixmapLoader>( "moog" ) ); \
|
||||
name .addItem( tr( "Soft square wave" ), make_unique<PluginPixmapLoader>( "sqrsoft" ) ); \
|
||||
name .addItem( tr( "Absolute sine wave" ), make_unique<PluginPixmapLoader>( "sinabs" ) ); \
|
||||
name .addItem( tr( "Exponential wave" ), make_unique<PluginPixmapLoader>( "exp" ) ); \
|
||||
name .addItem( tr( "White noise" ), make_unique<PluginPixmapLoader>( "noise" ) ); \
|
||||
name .addItem( tr( "Digital Triangle wave" ), make_unique<PluginPixmapLoader>( "tri" ) ); \
|
||||
name .addItem( tr( "Digital Saw wave" ), make_unique<PluginPixmapLoader>( "saw" ) ); \
|
||||
name .addItem( tr( "Digital Ramp wave" ), make_unique<PluginPixmapLoader>( "ramp" ) ); \
|
||||
name .addItem( tr( "Digital Square wave" ), make_unique<PluginPixmapLoader>( "sqr" ) ); \
|
||||
name .addItem( tr( "Digital Moog saw wave" ), make_unique<PluginPixmapLoader>( "moog" ) );
|
||||
|
||||
|
||||
#define setlfowavemodel( name ) \
|
||||
name .addItem( tr( "Sine wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "sin" ) ) ); \
|
||||
name .addItem( tr( "Triangle wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "tri" ) ) ); \
|
||||
name .addItem( tr( "Saw wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "saw" ) ) ); \
|
||||
name .addItem( tr( "Ramp wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "ramp" ) ) ); \
|
||||
name .addItem( tr( "Square wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "sqr" ) ) ); \
|
||||
name .addItem( tr( "Moog saw wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "moog" ) ) ); \
|
||||
name .addItem( tr( "Soft square wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "sqrsoft" ) ) ); \
|
||||
name .addItem( tr( "Abs. sine wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "sinabs" ) ) ); \
|
||||
name .addItem( tr( "Exponential wave" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "exp" ) ) ); \
|
||||
name .addItem( tr( "Random" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "rand" ) ) ); \
|
||||
name .addItem( tr( "Random smooth" ), static_cast<PixmapLoader*>( new PluginPixmapLoader( "rand" ) ) );
|
||||
name .addItem( tr( "Sine wave" ), make_unique<PluginPixmapLoader>( "sin" ) ); \
|
||||
name .addItem( tr( "Triangle wave" ), make_unique<PluginPixmapLoader>( "tri" ) ); \
|
||||
name .addItem( tr( "Saw wave" ), make_unique<PluginPixmapLoader>( "saw" ) ); \
|
||||
name .addItem( tr( "Ramp wave" ), make_unique<PluginPixmapLoader>( "ramp" ) ); \
|
||||
name .addItem( tr( "Square wave" ), make_unique<PluginPixmapLoader>( "sqr" ) ); \
|
||||
name .addItem( tr( "Moog saw wave" ), make_unique<PluginPixmapLoader>( "moog" ) ); \
|
||||
name .addItem( tr( "Soft square wave" ), make_unique<PluginPixmapLoader>( "sqrsoft" ) ); \
|
||||
name .addItem( tr( "Abs. sine wave" ), make_unique<PluginPixmapLoader>( "sinabs" ) ); \
|
||||
name .addItem( tr( "Exponential wave" ), make_unique<PluginPixmapLoader>( "exp" ) ); \
|
||||
name .addItem( tr( "Random" ), make_unique<PluginPixmapLoader>( "rand" ) ); \
|
||||
name .addItem( tr( "Random smooth" ), make_unique<PluginPixmapLoader>( "rand" ) );
|
||||
|
||||
public:
|
||||
MonstroInstrument( InstrumentTrack * _instrument_track );
|
||||
|
||||
@@ -20,7 +20,7 @@ IF(LMMS_HOST_X86 OR LMMS_HOST_X86_64)
|
||||
ENDIF(LMMS_HOST_X86 OR LMMS_HOST_X86_64)
|
||||
|
||||
# build ZynAddSubFX with full optimizations
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wno-write-strings -Wno-deprecated-declarations -fpermissive")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wno-misleading-indentation -Wno-write-strings -Wno-deprecated-declarations -fpermissive")
|
||||
|
||||
IF(LMMS_BUILD_WIN32)
|
||||
# link system-libraries
|
||||
@@ -151,7 +151,7 @@ ADD_DEPENDENCIES(zynaddsubfx ZynAddSubFxCore)
|
||||
IF(WIN32)
|
||||
SET(WINRC "${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfxrc.obj")
|
||||
ADD_CUSTOM_COMMAND(OUTPUT "${WINRC}"
|
||||
COMMAND "${WINDRES}"
|
||||
COMMAND "${CMAKE_RC_COMPILER}"
|
||||
"-I\"${CMAKE_CURRENT_SOURCE_DIR}\""
|
||||
"-o\"${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfxrc.obj\""
|
||||
"-i\"${CMAKE_CURRENT_BINARY_DIR}/zynaddsubfx.rc\""
|
||||
|
||||
Submodule plugins/zynaddsubfx/zynaddsubfx updated: 1a39a451b0...9cd29e2243
@@ -34,7 +34,7 @@ IF(WIN32 AND MSVC)
|
||||
ELSEIF(WIN32)
|
||||
SET(WINRC "${CMAKE_BINARY_DIR}/lmmsrc.obj")
|
||||
ADD_CUSTOM_COMMAND(OUTPUT "${WINRC}"
|
||||
COMMAND "${WINDRES}"
|
||||
COMMAND "${CMAKE_RC_COMPILER}"
|
||||
"-I\"${CMAKE_SOURCE_DIR}\""
|
||||
"-o\"${CMAKE_BINARY_DIR}/lmmsrc.obj\""
|
||||
"-i\"${CMAKE_BINARY_DIR}/lmms.rc\""
|
||||
|
||||
@@ -31,16 +31,14 @@
|
||||
#include "Mixer.h"
|
||||
#include "ProjectJournal.h"
|
||||
|
||||
float AutomatableModel::s_copiedValue = 0;
|
||||
long AutomatableModel::s_periodCounter = 0;
|
||||
|
||||
|
||||
|
||||
AutomatableModel::AutomatableModel( DataType type,
|
||||
AutomatableModel::AutomatableModel(
|
||||
const float val, const float min, const float max, const float step,
|
||||
Model* parent, const QString & displayName, bool defaultConstructed ) :
|
||||
Model( parent, displayName, defaultConstructed ),
|
||||
m_dataType( type ),
|
||||
m_scaleType( Linear ),
|
||||
m_minValue( min ),
|
||||
m_maxValue( max ),
|
||||
@@ -50,7 +48,6 @@ AutomatableModel::AutomatableModel( DataType type,
|
||||
m_valueChanged( false ),
|
||||
m_setValueDepth( 0 ),
|
||||
m_hasStrictStepSize( false ),
|
||||
m_hasLinkedModels( false ),
|
||||
m_controllerConnection( NULL ),
|
||||
m_valueBuffer( static_cast<int>( Engine::mixer()->framesPerPeriod() ) ),
|
||||
m_lastUpdatedPeriod( -1 ),
|
||||
@@ -273,19 +270,6 @@ float AutomatableModel::inverseScaledValue( float value ) const
|
||||
|
||||
|
||||
|
||||
QString AutomatableModel::displayValue( const float val ) const
|
||||
{
|
||||
switch( m_dataType )
|
||||
{
|
||||
case Float: return QString::number( castValue<float>( scaledValue( val ) ) );
|
||||
case Integer: return QString::number( castValue<int>( scaledValue( val ) ) );
|
||||
case Bool: return QString::number( castValue<bool>( scaledValue( val ) ) );
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! @todo: this should be moved into a maths header
|
||||
template<class T>
|
||||
void roundAt( T& value, const T& where, const T& step_size )
|
||||
@@ -411,7 +395,6 @@ void AutomatableModel::linkModel( AutomatableModel* model )
|
||||
if( !m_linkedModels.contains( model ) && model != this )
|
||||
{
|
||||
m_linkedModels.push_back( model );
|
||||
m_hasLinkedModels = true;
|
||||
|
||||
if( !model->hasLinkedModels() )
|
||||
{
|
||||
@@ -430,7 +413,6 @@ void AutomatableModel::unlinkModel( AutomatableModel* model )
|
||||
{
|
||||
m_linkedModels.erase( it );
|
||||
}
|
||||
m_hasLinkedModels = !m_linkedModels.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -462,8 +444,6 @@ void AutomatableModel::unlinkAllModels()
|
||||
{
|
||||
unlinkModels( this, model );
|
||||
}
|
||||
|
||||
m_hasLinkedModels = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -566,7 +546,7 @@ ValueBuffer * AutomatableModel::valueBuffer()
|
||||
}
|
||||
}
|
||||
AutomatableModel* lm = NULL;
|
||||
if( m_hasLinkedModels )
|
||||
if( hasLinkedModels() )
|
||||
{
|
||||
lm = m_linkedModels.first();
|
||||
}
|
||||
@@ -635,21 +615,6 @@ void AutomatableModel::reset()
|
||||
|
||||
|
||||
|
||||
void AutomatableModel::copyValue()
|
||||
{
|
||||
s_copiedValue = value<float>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AutomatableModel::pasteValue()
|
||||
{
|
||||
setValue( copiedValue() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
float AutomatableModel::globalAutomationValueAt( const MidiTime& time )
|
||||
{
|
||||
// get patterns that connect to this model
|
||||
@@ -728,3 +693,19 @@ int FloatModel::getDigitCount() const
|
||||
return digits;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QString FloatModel::displayValue( const float val ) const
|
||||
{
|
||||
return QString::number( castValue<float>( scaledValue( val ) ) );
|
||||
}
|
||||
|
||||
QString IntModel::displayValue( const float val ) const
|
||||
{
|
||||
return QString::number( castValue<int>( scaledValue( val ) ) );
|
||||
}
|
||||
|
||||
QString BoolModel::displayValue( const float val ) const
|
||||
{
|
||||
return QString::number( castValue<bool>( scaledValue( val ) ) );
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ set(LMMS_SRCS
|
||||
core/NotePlayHandle.cpp
|
||||
core/Oscillator.cpp
|
||||
core/PeakController.cpp
|
||||
core/PerfLog.cpp
|
||||
core/Piano.cpp
|
||||
core/PlayHandle.cpp
|
||||
core/Plugin.cpp
|
||||
|
||||
@@ -25,11 +25,12 @@
|
||||
#include "ComboBoxModel.h"
|
||||
#include "embed.h"
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::move;
|
||||
|
||||
|
||||
void ComboBoxModel::addItem( const QString& item, PixmapLoader* loader )
|
||||
void ComboBoxModel::addItem( QString item, unique_ptr<PixmapLoader> loader )
|
||||
{
|
||||
m_items.push_back( qMakePair( item, loader ) );
|
||||
m_items.emplace_back( move(item), move(loader) );
|
||||
setRange( 0, m_items.size() - 1 );
|
||||
}
|
||||
|
||||
@@ -39,10 +40,6 @@ void ComboBoxModel::addItem( const QString& item, PixmapLoader* loader )
|
||||
void ComboBoxModel::clear()
|
||||
{
|
||||
setRange( 0, 0 );
|
||||
for( const Item& i : m_items )
|
||||
{
|
||||
delete i.second;
|
||||
}
|
||||
|
||||
m_items.clear();
|
||||
|
||||
@@ -54,7 +51,7 @@ void ComboBoxModel::clear()
|
||||
|
||||
int ComboBoxModel::findText( const QString& txt ) const
|
||||
{
|
||||
for( QVector<Item>::ConstIterator it = m_items.begin(); it != m_items.end(); ++it )
|
||||
for( auto it = m_items.begin(); it != m_items.end(); ++it )
|
||||
{
|
||||
if( ( *it ).first == txt )
|
||||
{
|
||||
|
||||
@@ -63,11 +63,9 @@ Controller::Controller( ControllerTypes _type, Model * _parent,
|
||||
|
||||
// Check if name is already in use
|
||||
bool name_used = false;
|
||||
QVector<Controller *>::const_iterator it;
|
||||
for ( it = s_controllers.constBegin();
|
||||
it != s_controllers.constEnd(); ++it )
|
||||
for (Controller * controller : s_controllers)
|
||||
{
|
||||
if ( (*it)->name() == new_name )
|
||||
if ( controller->name() == new_name )
|
||||
{
|
||||
name_used = true;
|
||||
break;
|
||||
@@ -157,13 +155,13 @@ float Controller::runningTime()
|
||||
|
||||
void Controller::triggerFrameCounter()
|
||||
{
|
||||
for( int i = 0; i < s_controllers.size(); ++i )
|
||||
for (Controller * controller : s_controllers)
|
||||
{
|
||||
// This signal is for updating values for both stubborn knobs and for
|
||||
// painting. If we ever get all the widgets to use or at least check
|
||||
// currentValue() then we can throttle the signal and only use it for
|
||||
// GUI.
|
||||
emit s_controllers.at(i)->valueChanged();
|
||||
emit controller->valueChanged();
|
||||
}
|
||||
|
||||
s_periods ++;
|
||||
@@ -174,10 +172,10 @@ void Controller::triggerFrameCounter()
|
||||
|
||||
void Controller::resetFrameCounter()
|
||||
{
|
||||
for( int i = 0; i < s_controllers.size(); ++i )
|
||||
for (Controller * controller : s_controllers)
|
||||
{
|
||||
s_controllers.at( i )->m_bufferLastUpdated = 0;
|
||||
}
|
||||
controller->m_bufferLastUpdated = 0;
|
||||
}
|
||||
s_periods = 0;
|
||||
}
|
||||
|
||||
@@ -190,15 +188,11 @@ Controller * Controller::create( ControllerTypes _ct, Model * _parent )
|
||||
|
||||
switch( _ct )
|
||||
{
|
||||
case Controller::DummyController:
|
||||
if( dummy )
|
||||
c = dummy;
|
||||
else
|
||||
{
|
||||
c = new Controller( DummyController, NULL,
|
||||
case Controller::DummyController:
|
||||
if (!dummy)
|
||||
dummy = new Controller( DummyController, NULL,
|
||||
QString() );
|
||||
dummy = c;
|
||||
}
|
||||
c = dummy;
|
||||
break;
|
||||
|
||||
case Controller::LfoController:
|
||||
@@ -247,12 +241,10 @@ Controller * Controller::create( const QDomElement & _this, Model * _parent )
|
||||
|
||||
|
||||
|
||||
bool Controller::hasModel( const Model * m )
|
||||
bool Controller::hasModel( const Model * m ) const
|
||||
{
|
||||
QObjectList chldren = children();
|
||||
for( int i = 0; i < chldren.size(); ++i )
|
||||
for (QObject * c : children())
|
||||
{
|
||||
QObject * c = chldren.at(i);
|
||||
AutomatableModel * am = qobject_cast<AutomatableModel*>(c);
|
||||
if( am != NULL )
|
||||
{
|
||||
@@ -262,16 +254,13 @@ bool Controller::hasModel( const Model * m )
|
||||
}
|
||||
|
||||
ControllerConnection * cc = am->controllerConnection();
|
||||
if( cc != NULL )
|
||||
if( cc != NULL && cc->getController()->hasModel( m ) )
|
||||
{
|
||||
if( cc->getController()->hasModel( m ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -968,6 +968,67 @@ void DataFile::upgrade_1_2_0_rc2_42()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to call a functor for all effect ports' DomElements,
|
||||
* providing the functor with lists to add and remove DomElements. Helpful for
|
||||
* patching port values from savefiles.
|
||||
*/
|
||||
template<class Ftor>
|
||||
void iterate_ladspa_ports(QDomElement& effect, Ftor& ftor)
|
||||
{
|
||||
// Head back up the DOM to upgrade ports
|
||||
QDomNodeList ladspacontrols = effect.elementsByTagName( "ladspacontrols" );
|
||||
for( int m = 0; !ladspacontrols.item( m ).isNull(); ++m )
|
||||
{
|
||||
QList<QDomElement> addList, removeList;
|
||||
QDomElement ladspacontrol = ladspacontrols.item( m ).toElement();
|
||||
for( QDomElement port = ladspacontrol.firstChild().toElement();
|
||||
!port.isNull(); port = port.nextSibling().toElement() )
|
||||
{
|
||||
QStringList parts = port.tagName().split("port");
|
||||
// Not a "port"
|
||||
if ( parts.size() < 2 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int num = parts[1].toInt();
|
||||
|
||||
// From Qt's docs of QDomNode:
|
||||
// * copying a QDomNode is OK, they still have the same
|
||||
// pointer to the "internal" QDomNodePrivate.
|
||||
// * Also, they are using linked lists, which means
|
||||
// deleting or appending QDomNode does not invalidate
|
||||
// any other pointers.
|
||||
// => Inside ftor, you can (and should) push back the
|
||||
// QDomElements by value, not references
|
||||
// => The loops below for adding and removing don't
|
||||
// invalidate any other QDomElements
|
||||
ftor(port, num, addList, removeList);
|
||||
}
|
||||
|
||||
// Add ports marked for adding
|
||||
for ( QDomElement e : addList )
|
||||
{
|
||||
ladspacontrol.appendChild( e );
|
||||
}
|
||||
// Remove ports marked for removal
|
||||
for ( QDomElement e : removeList )
|
||||
{
|
||||
ladspacontrol.removeChild( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// helper function if you need to print a QDomNode
|
||||
QDebug operator<<(QDebug dbg, const QDomNode& node)
|
||||
{
|
||||
QString s;
|
||||
QTextStream str(&s, QIODevice::WriteOnly);
|
||||
node.save(str, 2);
|
||||
dbg << qPrintable(s);
|
||||
return dbg;
|
||||
}
|
||||
|
||||
void DataFile::upgrade_1_3_0()
|
||||
{
|
||||
QDomNodeList list = elementsByTagName( "instrument" );
|
||||
@@ -1009,6 +1070,8 @@ void DataFile::upgrade_1_3_0()
|
||||
QDomNodeList attributes = key.elementsByTagName( "attribute" );
|
||||
for( int k = 0; !attributes.item( k ).isNull(); ++k )
|
||||
{
|
||||
// Effect name changes
|
||||
|
||||
QDomElement attribute = attributes.item( k ).toElement();
|
||||
if( attribute.attribute( "name" ) == "file" &&
|
||||
( attribute.attribute( "value" ) == "calf" ||
|
||||
@@ -1016,6 +1079,283 @@ void DataFile::upgrade_1_3_0()
|
||||
{
|
||||
attribute.setAttribute( "value", "veal" );
|
||||
}
|
||||
else if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Sidechaincompressor" )
|
||||
{
|
||||
attribute.setAttribute( "value", "SidechainCompressor" );
|
||||
}
|
||||
else if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Sidechaingate" )
|
||||
{
|
||||
attribute.setAttribute( "value", "SidechainGate" );
|
||||
}
|
||||
else if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Multibandcompressor" )
|
||||
{
|
||||
attribute.setAttribute( "value", "MultibandCompressor" );
|
||||
}
|
||||
else if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Multibandgate" )
|
||||
{
|
||||
attribute.setAttribute( "value", "MultibandGate" );
|
||||
}
|
||||
else if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Multibandlimiter" )
|
||||
{
|
||||
attribute.setAttribute( "value", "MultibandLimiter" );
|
||||
}
|
||||
|
||||
// Handle port changes
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
( attribute.attribute( "value" ) == "MultibandLimiter" ||
|
||||
attribute.attribute( "value" ) == "MultibandCompressor" ||
|
||||
attribute.attribute( "value" ) == "MultibandGate" ) )
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>&, QList<QDomElement>& removeList)
|
||||
{
|
||||
// Mark ports for removal
|
||||
if ( num >= 18 && num <= 23 )
|
||||
{
|
||||
removeList << port;
|
||||
}
|
||||
// Bump higher ports up 6 positions
|
||||
else if ( num >= 24 )
|
||||
{
|
||||
// port01...port010, etc
|
||||
QString name( "port0" );
|
||||
name.append( QString::number( num -6 ) );
|
||||
port.setTagName( name );
|
||||
}
|
||||
};
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
( attribute.attribute( "value" ) == "Pulsator" ) )
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>& addList, QList<QDomElement>& removeList)
|
||||
{
|
||||
switch(num)
|
||||
{
|
||||
case 16:
|
||||
{
|
||||
// old freq is now at port 25
|
||||
QDomElement portCopy = createElement("port025");
|
||||
portCopy.setAttribute("data", port.attribute("data"));
|
||||
addList << portCopy;
|
||||
// remove old freq port
|
||||
removeList << port;
|
||||
// set the "timing" port to choose port23+2=port25 (timing in Hz)
|
||||
QDomElement timing = createElement("port022");
|
||||
timing.setAttribute("data", 2);
|
||||
addList << timing;
|
||||
break;
|
||||
}
|
||||
// port 18 (modulation) => 17
|
||||
case 17:
|
||||
port.setTagName("port016");
|
||||
break;
|
||||
case 18:
|
||||
{
|
||||
// leave port 18 (offsetr), but add port 17 (offsetl)
|
||||
QDomElement offsetl = createElement("port017");
|
||||
offsetl.setAttribute("data", 0.0f);
|
||||
addList << offsetl;
|
||||
// additional: bash port 21 to 1
|
||||
QDomElement pulsewidth = createElement("port021");
|
||||
pulsewidth.setAttribute("data", 1.0f);
|
||||
addList << pulsewidth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
( attribute.attribute( "value" ) == "VintageDelay" ) )
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>& addList, QList<QDomElement>& )
|
||||
{
|
||||
switch(num)
|
||||
{
|
||||
case 4:
|
||||
{
|
||||
// BPM is now port028
|
||||
port.setTagName("port028");
|
||||
// bash timing to BPM
|
||||
QDomElement timing = createElement("port027");
|
||||
timing.setAttribute("data", 0);
|
||||
addList << timing;
|
||||
|
||||
// port 5 and 6 (in, out gain) need to be bashed to 1:
|
||||
QDomElement input = createElement("port05");
|
||||
input.setAttribute("data", 1.0f);
|
||||
addList << input;
|
||||
QDomElement output = createElement("port06");
|
||||
output.setAttribute("data", 1.0f);
|
||||
addList << output;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// all other ports increase by 10
|
||||
QString name( "port0" );
|
||||
name.append( QString::number( num + 10 ) );
|
||||
port.setTagName( name );
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
( ( attribute.attribute( "value" ) == "Equalizer5Band" )
|
||||
|| ( attribute.attribute( "value" ) == "Equalizer8Band" )
|
||||
|| ( attribute.attribute( "value" ) == "Equalizer12Band" ) ) )
|
||||
{
|
||||
// NBand equalizers got 4 q nobs inserted. We need to shift everything else...
|
||||
// HOWEVER: 5 band eq has only 2 q nobs inserted (no LS/HS filters)
|
||||
bool band5 = ( attribute.attribute( "value" ) == "Equalizer5Band" );
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>& addList, QList<QDomElement>& )
|
||||
{
|
||||
if(num == 4)
|
||||
{
|
||||
// don't modify port 4, but some other ones:
|
||||
int zoom_port;
|
||||
if(attribute.attribute( "value" ) == "Equalizer5Band")
|
||||
zoom_port = 36;
|
||||
else if(attribute.attribute( "value" ) == "Equalizer8Band")
|
||||
zoom_port = 48;
|
||||
else // 12 band
|
||||
zoom_port = 64;
|
||||
// bash zoom to 0.25
|
||||
QString name( "port0" );
|
||||
name.append( QString::number( zoom_port ) );
|
||||
QDomElement timing = createElement(name);
|
||||
timing.setAttribute("data", 0.25f);
|
||||
addList << timing;
|
||||
}
|
||||
// the following code could be refactored, but I did careful code-reading
|
||||
// to prevent copy-paste-errors
|
||||
if(num == 18)
|
||||
{
|
||||
// 18 => 19
|
||||
port.setTagName("port019");
|
||||
// insert port 18 (q)
|
||||
QDomElement q = createElement("port018");
|
||||
q.setAttribute("data", 0.707f);
|
||||
addList << q;
|
||||
}
|
||||
else if(num >= 19 && num <= 20)
|
||||
{
|
||||
// num += 1
|
||||
QString name( "port0" );
|
||||
name.append( QString::number( num + 1 ) );
|
||||
port.setTagName( name );
|
||||
}
|
||||
else if(num == 21)
|
||||
{
|
||||
// 21 => 23
|
||||
port.setTagName("port023");
|
||||
// insert port 22 (q)
|
||||
QDomElement q = createElement("port022");
|
||||
q.setAttribute("data", 0.707f);
|
||||
addList << q;
|
||||
}
|
||||
else if(num >= 22 && (num <= 23 || band5))
|
||||
{
|
||||
// num += 2
|
||||
QString name( "port0" );
|
||||
name.append( QString::number( num + 2 ) );
|
||||
port.setTagName( name );
|
||||
}
|
||||
else if(num == 24 && !band5)
|
||||
{
|
||||
// 24 => 27
|
||||
port.setTagName("port027");
|
||||
// insert port 26 (q)
|
||||
QDomElement q = createElement("port026");
|
||||
q.setAttribute("data", 0.707f);
|
||||
addList << q;
|
||||
}
|
||||
else if(num >= 25 && num <= 26 && !band5)
|
||||
{
|
||||
// num += 3
|
||||
QString name( "port0" );
|
||||
name.append( QString::number( num + 3 ) );
|
||||
port.setTagName( name );
|
||||
}
|
||||
else if(num == 27 && !band5)
|
||||
{
|
||||
// 27 => 31
|
||||
port.setTagName("port031");
|
||||
// insert port 30 (q)
|
||||
QDomElement q = createElement("port030");
|
||||
q.setAttribute("data", 0.707f);
|
||||
addList << q;
|
||||
}
|
||||
else if(num >= 28 && !band5)
|
||||
{
|
||||
// num += 4
|
||||
QString name( "port0" );
|
||||
name.append( QString::number( num + 4 ) );
|
||||
port.setTagName( name );
|
||||
}
|
||||
};
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Saturator" )
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>&, QList<QDomElement>& )
|
||||
{
|
||||
// These ports have been shifted a bit weird...
|
||||
if( num == 7 )
|
||||
{
|
||||
port.setTagName("port015");
|
||||
}
|
||||
else if(num == 12)
|
||||
{
|
||||
port.setTagName("port016");
|
||||
}
|
||||
else if(num == 13)
|
||||
{
|
||||
port.setTagName("port017");
|
||||
}
|
||||
else if ( num >= 15 )
|
||||
{
|
||||
QString name( "port0" );
|
||||
name.append( QString::number( num + 3 ) );
|
||||
port.setTagName( name );
|
||||
}
|
||||
};
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "StereoTools" )
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>&, QList<QDomElement>& )
|
||||
{
|
||||
// This effect can not be back-ported due to bugs in the old version,
|
||||
// or due to different behaviour. We thus port all parameters we can,
|
||||
// and bash all new parameters (in this case, s.level and m.level) to
|
||||
// their new defaults (both 1.0f in this case)
|
||||
|
||||
if( num == 23 || num == 25 )
|
||||
{
|
||||
port.setAttribute("data", 1.0f);
|
||||
}
|
||||
};
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +125,8 @@ void EffectChain::appendEffect( Effect * _effect )
|
||||
m_effects.append( _effect );
|
||||
Engine::mixer()->doneChangeInModel();
|
||||
|
||||
m_enabledModel.setValue( true );
|
||||
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
@@ -144,6 +146,12 @@ void EffectChain::removeEffect( Effect * _effect )
|
||||
m_effects.erase( found );
|
||||
|
||||
Engine::mixer()->doneChangeInModel();
|
||||
|
||||
if( m_effects.isEmpty() )
|
||||
{
|
||||
m_enabledModel.setValue( false );
|
||||
}
|
||||
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
@@ -154,19 +162,8 @@ void EffectChain::moveDown( Effect * _effect )
|
||||
{
|
||||
if( _effect != m_effects.last() )
|
||||
{
|
||||
int i = 0;
|
||||
for( EffectList::Iterator it = m_effects.begin();
|
||||
it != m_effects.end(); it++, i++ )
|
||||
{
|
||||
if( *it == _effect )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Effect * temp = m_effects[i + 1];
|
||||
m_effects[i + 1] = _effect;
|
||||
m_effects[i] = temp;
|
||||
int i = m_effects.indexOf(_effect);
|
||||
std::swap(m_effects[i + 1], m_effects[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,19 +174,8 @@ void EffectChain::moveUp( Effect * _effect )
|
||||
{
|
||||
if( _effect != m_effects.first() )
|
||||
{
|
||||
int i = 0;
|
||||
for( EffectList::Iterator it = m_effects.begin();
|
||||
it != m_effects.end(); it++, i++ )
|
||||
{
|
||||
if( *it == _effect )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Effect * temp = m_effects[i - 1];
|
||||
m_effects[i - 1] = _effect;
|
||||
m_effects[i] = temp;
|
||||
int i = m_effects.indexOf(_effect);
|
||||
std::swap(m_effects[i - 1], m_effects[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +236,6 @@ void EffectChain::clear()
|
||||
|
||||
Engine::mixer()->requestChangeInModel();
|
||||
|
||||
m_enabledModel.setValue( false );
|
||||
while( m_effects.count() )
|
||||
{
|
||||
Effect * e = m_effects[m_effects.count() - 1];
|
||||
@@ -259,4 +244,6 @@ void EffectChain::clear()
|
||||
}
|
||||
|
||||
Engine::mixer()->doneChangeInModel();
|
||||
|
||||
m_enabledModel.setValue( false );
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ FxChannel::FxChannel( int idx, Model * _parent ) :
|
||||
m_lock(),
|
||||
m_channelIndex( idx ),
|
||||
m_queued( false ),
|
||||
m_dependenciesMet( 0 )
|
||||
m_dependenciesMet(0)
|
||||
{
|
||||
BufferManager::clear( m_buffer, Engine::mixer()->framesPerPeriod() );
|
||||
}
|
||||
@@ -98,7 +98,7 @@ inline void FxChannel::processed()
|
||||
|
||||
void FxChannel::incrementDeps()
|
||||
{
|
||||
int i = m_dependenciesMet.fetchAndAddOrdered( 1 ) + 1;
|
||||
int i = m_dependenciesMet++ + 1;
|
||||
if( i >= m_receives.size() && ! m_queued )
|
||||
{
|
||||
m_queued = true;
|
||||
@@ -594,14 +594,14 @@ void FxMixer::masterMix( sampleFrame * _buf )
|
||||
MixerWorkerThread::addJob( ch );
|
||||
}
|
||||
}
|
||||
while( m_fxChannels[0]->state() != ThreadableJob::Done )
|
||||
while (m_fxChannels[0]->state() != ThreadableJob::ProcessingState::Done)
|
||||
{
|
||||
bool found = false;
|
||||
for( FxChannel * ch : m_fxChannels )
|
||||
{
|
||||
int s = ch->state();
|
||||
if( s == ThreadableJob::Queued
|
||||
|| s == ThreadableJob::InProgress )
|
||||
const auto s = ch->state();
|
||||
if (s == ThreadableJob::ProcessingState::Queued
|
||||
|| s == ThreadableJob::ProcessingState::InProgress)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "ImportFilter.h"
|
||||
@@ -32,6 +33,8 @@
|
||||
#include "ProjectJournal.h"
|
||||
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
ImportFilter::ImportFilter( const QString & _file_name,
|
||||
const Descriptor * _descriptor ) :
|
||||
Plugin( _descriptor, NULL ),
|
||||
@@ -54,7 +57,8 @@ void ImportFilter::import( const QString & _file_to_import,
|
||||
{
|
||||
bool successful = false;
|
||||
|
||||
char * s = qstrdup( _file_to_import.toUtf8().constData() );
|
||||
QByteArray s = _file_to_import.toUtf8();
|
||||
s.detach();
|
||||
|
||||
// do not record changes while importing files
|
||||
const bool j = Engine::projectJournal()->isJournalling();
|
||||
@@ -62,21 +66,17 @@ void ImportFilter::import( const QString & _file_to_import,
|
||||
|
||||
for (const Plugin::Descriptor* desc : pluginFactory->descriptors(Plugin::ImportFilter))
|
||||
{
|
||||
Plugin * p = Plugin::instantiate( desc->name, NULL, s );
|
||||
if( dynamic_cast<ImportFilter *>( p ) != NULL &&
|
||||
dynamic_cast<ImportFilter *>( p )->tryImport( tc ) == true )
|
||||
unique_ptr<Plugin> p(Plugin::instantiate( desc->name, NULL, s.data() ));
|
||||
if( dynamic_cast<ImportFilter *>( p.get() ) != NULL &&
|
||||
dynamic_cast<ImportFilter *>( p.get() )->tryImport( tc ) )
|
||||
{
|
||||
delete p;
|
||||
successful = true;
|
||||
break;
|
||||
}
|
||||
delete p;
|
||||
}
|
||||
|
||||
Engine::projectJournal()->setJournalling( j );
|
||||
|
||||
delete[] s;
|
||||
|
||||
if( successful == false )
|
||||
{
|
||||
QMessageBox::information( NULL,
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "InstrumentTrack.h"
|
||||
#include "Mixer.h"
|
||||
#include "PresetPreviewPlayHandle.h"
|
||||
|
||||
#include "stdshims.h"
|
||||
|
||||
|
||||
InstrumentFunctionNoteStacking::ChordTable::Init InstrumentFunctionNoteStacking::ChordTable::s_initTable[] =
|
||||
@@ -45,7 +45,7 @@ InstrumentFunctionNoteStacking::ChordTable::Init InstrumentFunctionNoteStacking:
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "aug" ), { 0, 4, 8, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "augsus4" ), { 0, 5, 8, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "tri" ), { 0, 3, 6, 9, -1 } },
|
||||
|
||||
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "6" ), { 0, 4, 7, 9, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "6sus4" ), { 0, 5, 7, 9, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "6add9" ), { 0, 4, 7, 9, 14, -1 } },
|
||||
@@ -125,7 +125,7 @@ InstrumentFunctionNoteStacking::ChordTable::Init InstrumentFunctionNoteStacking:
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Neopolitan minor" ), { 0, 1, 3, 5, 7, 8, 11, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Hungarian minor" ), { 0, 2, 3, 6, 7, 8, 11, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Dorian" ), { 0, 2, 3, 5, 7, 9, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Phrygolydian" ), { 0, 1, 3, 5, 7, 8, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Phrygian" ), { 0, 1, 3, 5, 7, 8, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Lydian" ), { 0, 2, 4, 6, 7, 9, 11, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Mixolydian" ), { 0, 2, 4, 5, 7, 9, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Aeolian" ), { 0, 2, 3, 5, 7, 8, 10, -1 } },
|
||||
@@ -133,7 +133,7 @@ InstrumentFunctionNoteStacking::ChordTable::Init InstrumentFunctionNoteStacking:
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Minor" ), { 0, 2, 3, 5, 7, 8, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Chromatic" ), { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Half-Whole Diminished" ), { 0, 1, 3, 4, 6, 7, 9, 10, -1 } },
|
||||
|
||||
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "5" ), { 0, 7, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Phrygian dominant" ), { 0, 1, 4, 5, 7, 8, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Persian" ), { 0, 1, 4, 5, 6, 8, 11, -1 } }
|
||||
@@ -262,7 +262,7 @@ void InstrumentFunctionNoteStacking::processNote( NotePlayHandle * _n )
|
||||
|
||||
// create sub-note-play-handle, only note is
|
||||
// different
|
||||
Engine::mixer()->addPlayHandle(
|
||||
Engine::mixer()->addPlayHandle(
|
||||
NotePlayHandleManager::acquire( _n->instrumentTrack(), _n->offset(), _n->frames(), note_copy,
|
||||
_n, -1, NotePlayHandle::OriginNoteStacking )
|
||||
);
|
||||
@@ -316,16 +316,16 @@ InstrumentFunctionArpeggio::InstrumentFunctionArpeggio( Model * _parent ) :
|
||||
m_arpModel.addItem( chord_table[i].getName() );
|
||||
}
|
||||
|
||||
m_arpDirectionModel.addItem( tr( "Up" ), new PixmapLoader( "arp_up" ) );
|
||||
m_arpDirectionModel.addItem( tr( "Down" ), new PixmapLoader( "arp_down" ) );
|
||||
m_arpDirectionModel.addItem( tr( "Up and down" ), new PixmapLoader( "arp_up_and_down" ) );
|
||||
m_arpDirectionModel.addItem( tr( "Down and up" ), new PixmapLoader( "arp_up_and_down" ) );
|
||||
m_arpDirectionModel.addItem( tr( "Random" ), new PixmapLoader( "arp_random" ) );
|
||||
m_arpDirectionModel.addItem( tr( "Up" ), make_unique<PixmapLoader>( "arp_up" ) );
|
||||
m_arpDirectionModel.addItem( tr( "Down" ), make_unique<PixmapLoader>( "arp_down" ) );
|
||||
m_arpDirectionModel.addItem( tr( "Up and down" ), make_unique<PixmapLoader>( "arp_up_and_down" ) );
|
||||
m_arpDirectionModel.addItem( tr( "Down and up" ), make_unique<PixmapLoader>( "arp_up_and_down" ) );
|
||||
m_arpDirectionModel.addItem( tr( "Random" ), make_unique<PixmapLoader>( "arp_random" ) );
|
||||
m_arpDirectionModel.setInitValue( ArpDirUp );
|
||||
|
||||
m_arpModeModel.addItem( tr( "Free" ), new PixmapLoader( "arp_free" ) );
|
||||
m_arpModeModel.addItem( tr( "Sort" ), new PixmapLoader( "arp_sort" ) );
|
||||
m_arpModeModel.addItem( tr( "Sync" ), new PixmapLoader( "arp_sync" ) );
|
||||
m_arpModeModel.addItem( tr( "Free" ), make_unique<PixmapLoader>( "arp_free" ) );
|
||||
m_arpModeModel.addItem( tr( "Sort" ), make_unique<PixmapLoader>( "arp_sort" ) );
|
||||
m_arpModeModel.addItem( tr( "Sync" ), make_unique<PixmapLoader>( "arp_sync" ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -569,13 +569,10 @@ void InstrumentFunctionArpeggio::loadSettings( const QDomElement & _this )
|
||||
// Keep compatibility with version 0.2.1 file format
|
||||
if( _this.hasAttribute( "arpsyncmode" ) )
|
||||
{
|
||||
m_arpTimeKnob->setSyncMode(
|
||||
m_arpTimeKnob->setSyncMode(
|
||||
( tempoSyncKnob::tempoSyncMode ) _this.attribute(
|
||||
"arpsyncmode" ).toInt() );
|
||||
}*/
|
||||
|
||||
m_arpModeModel.loadSettings( _this, "arpmode" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "Instrument.h"
|
||||
#include "InstrumentTrack.h"
|
||||
#include "Mixer.h"
|
||||
#include "stdshims.h"
|
||||
|
||||
|
||||
const float CUT_FREQ_MULTIPLIER = 6000.0f;
|
||||
@@ -79,28 +80,28 @@ InstrumentSoundShaping::InstrumentSoundShaping(
|
||||
tr( targetNames[i][2].toUtf8().constData() ) );
|
||||
}
|
||||
|
||||
m_filterModel.addItem( tr( "LowPass" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "HiPass" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "BandPass csg" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "BandPass czpg" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "Notch" ), new PixmapLoader( "filter_notch" ) );
|
||||
m_filterModel.addItem( tr( "Allpass" ), new PixmapLoader( "filter_ap" ) );
|
||||
m_filterModel.addItem( tr( "Moog" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "2x LowPass" ), new PixmapLoader( "filter_2lp" ) );
|
||||
m_filterModel.addItem( tr( "RC LowPass 12dB" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "RC BandPass 12dB" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "RC HighPass 12dB" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "RC LowPass 24dB" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "RC BandPass 24dB" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "RC HighPass 24dB" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "Vocal Formant Filter" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "2x Moog" ), new PixmapLoader( "filter_2lp" ) );
|
||||
m_filterModel.addItem( tr( "SV LowPass" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "SV BandPass" ), new PixmapLoader( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "SV HighPass" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "SV Notch" ), new PixmapLoader( "filter_notch" ) );
|
||||
m_filterModel.addItem( tr( "Fast Formant" ), new PixmapLoader( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "Tripole" ), new PixmapLoader( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "LowPass" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "HiPass" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "BandPass csg" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "BandPass czpg" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "Notch" ), make_unique<PixmapLoader>( "filter_notch" ) );
|
||||
m_filterModel.addItem( tr( "Allpass" ), make_unique<PixmapLoader>( "filter_ap" ) );
|
||||
m_filterModel.addItem( tr( "Moog" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "2x LowPass" ), make_unique<PixmapLoader>( "filter_2lp" ) );
|
||||
m_filterModel.addItem( tr( "RC LowPass 12dB" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "RC BandPass 12dB" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "RC HighPass 12dB" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "RC LowPass 24dB" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "RC BandPass 24dB" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "RC HighPass 24dB" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "Vocal Formant Filter" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "2x Moog" ), make_unique<PixmapLoader>( "filter_2lp" ) );
|
||||
m_filterModel.addItem( tr( "SV LowPass" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
m_filterModel.addItem( tr( "SV BandPass" ), make_unique<PixmapLoader>( "filter_bp" ) );
|
||||
m_filterModel.addItem( tr( "SV HighPass" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "SV Notch" ), make_unique<PixmapLoader>( "filter_notch" ) );
|
||||
m_filterModel.addItem( tr( "Fast Formant" ), make_unique<PixmapLoader>( "filter_hp" ) );
|
||||
m_filterModel.addItem( tr( "Tripole" ), make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -160,9 +161,9 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer,
|
||||
int old_filter_cut = 0;
|
||||
int old_filter_res = 0;
|
||||
|
||||
if( n->m_filter == NULL )
|
||||
if( n->m_filter == nullptr )
|
||||
{
|
||||
n->m_filter = new BasicFilters<>( Engine::mixer()->processingSampleRate() );
|
||||
n->m_filter = make_unique<BasicFilters<>>( Engine::mixer()->processingSampleRate() );
|
||||
}
|
||||
n->m_filter->setFilterType( m_filterModel.value() );
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port,
|
||||
switch( m_port->data_type )
|
||||
{
|
||||
case TOGGLED:
|
||||
m_toggledModel.setInitValue(
|
||||
static_cast<bool>( m_port->def ) );
|
||||
connect( &m_toggledModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( ledChanged() ) );
|
||||
if( m_port->def == 1.0f )
|
||||
@@ -59,6 +61,7 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port,
|
||||
break;
|
||||
|
||||
case INTEGER:
|
||||
case ENUM:
|
||||
m_knobModel.setRange( static_cast<int>( m_port->max ),
|
||||
static_cast<int>( m_port->min ),
|
||||
1 + static_cast<int>( m_port->max -
|
||||
@@ -117,6 +120,7 @@ LADSPA_Data LadspaControl::value()
|
||||
case TOGGLED:
|
||||
return static_cast<LADSPA_Data>( m_toggledModel.value() );
|
||||
case INTEGER:
|
||||
case ENUM:
|
||||
case FLOATING:
|
||||
return static_cast<LADSPA_Data>( m_knobModel.value() );
|
||||
case TIME:
|
||||
@@ -136,6 +140,7 @@ ValueBuffer * LadspaControl::valueBuffer()
|
||||
{
|
||||
case TOGGLED:
|
||||
case INTEGER:
|
||||
case ENUM:
|
||||
return NULL;
|
||||
case FLOATING:
|
||||
return m_knobModel.valueBuffer();
|
||||
@@ -159,6 +164,7 @@ void LadspaControl::setValue( LADSPA_Data _value )
|
||||
m_toggledModel.setValue( static_cast<bool>( _value ) );
|
||||
break;
|
||||
case INTEGER:
|
||||
case ENUM:
|
||||
m_knobModel.setValue( static_cast<int>( _value ) );
|
||||
break;
|
||||
case FLOATING:
|
||||
@@ -193,6 +199,7 @@ void LadspaControl::saveSettings( QDomDocument& doc,
|
||||
m_toggledModel.saveSettings( doc, e, "data" );
|
||||
break;
|
||||
case INTEGER:
|
||||
case ENUM:
|
||||
case FLOATING:
|
||||
m_knobModel.saveSettings( doc, e, "data" );
|
||||
break;
|
||||
@@ -216,35 +223,64 @@ void LadspaControl::loadSettings( const QDomElement& parent, const QString& name
|
||||
QString linkModelName = "link";
|
||||
QDomElement e = parent.namedItem( name ).toElement();
|
||||
|
||||
// COMPAT < 1.0.0: detect old data format where there's either no dedicated sub
|
||||
// element or there's a direct sub element with automation link information
|
||||
if( e.isNull() || e.hasAttribute( "id" ) )
|
||||
if(e.isNull())
|
||||
{
|
||||
dataModelName = name;
|
||||
linkModelName = name + "link";
|
||||
e = parent;
|
||||
// the port exists in the current effect, but not in the
|
||||
// savefile => it's a new port, so load the default value
|
||||
if( m_link )
|
||||
m_linkEnabledModel.setValue(m_linkEnabledModel.initValue());
|
||||
switch( m_port->data_type )
|
||||
{
|
||||
case TOGGLED:
|
||||
m_toggledModel.setValue(m_toggledModel.initValue());
|
||||
break;
|
||||
case INTEGER:
|
||||
case ENUM:
|
||||
case FLOATING:
|
||||
m_knobModel.setValue(m_knobModel.initValue());
|
||||
break;
|
||||
case TIME:
|
||||
m_tempoSyncKnobModel.setValue(m_tempoSyncKnobModel.initValue());
|
||||
break;
|
||||
default:
|
||||
printf("LadspaControl::loadSettings BAD BAD BAD\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_link )
|
||||
else
|
||||
{
|
||||
m_linkEnabledModel.loadSettings( e, linkModelName );
|
||||
}
|
||||
|
||||
switch( m_port->data_type )
|
||||
{
|
||||
case TOGGLED:
|
||||
m_toggledModel.loadSettings( e, dataModelName );
|
||||
break;
|
||||
case INTEGER:
|
||||
case FLOATING:
|
||||
m_knobModel.loadSettings( e, dataModelName );
|
||||
break;
|
||||
case TIME:
|
||||
m_tempoSyncKnobModel.loadSettings( e, dataModelName );
|
||||
break;
|
||||
default:
|
||||
printf("LadspaControl::loadSettings BAD BAD BAD\n");
|
||||
break;
|
||||
// COMPAT < 1.0.0: detect old data format where there's either no dedicated sub
|
||||
// element or there's a direct sub element with automation link information
|
||||
if( e.isNull() || e.hasAttribute( "id" ) )
|
||||
{
|
||||
dataModelName = name;
|
||||
linkModelName = name + "link";
|
||||
e = parent;
|
||||
}
|
||||
|
||||
if( m_link )
|
||||
{
|
||||
m_linkEnabledModel.loadSettings( e, linkModelName );
|
||||
}
|
||||
|
||||
switch( m_port->data_type )
|
||||
{
|
||||
case TOGGLED:
|
||||
m_toggledModel.loadSettings( e, dataModelName );
|
||||
break;
|
||||
case INTEGER:
|
||||
case ENUM:
|
||||
case FLOATING:
|
||||
m_knobModel.loadSettings( e, dataModelName );
|
||||
break;
|
||||
case TIME:
|
||||
m_tempoSyncKnobModel.loadSettings( e, dataModelName );
|
||||
break;
|
||||
default:
|
||||
printf("LadspaControl::loadSettings BAD BAD BAD\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,6 +295,7 @@ void LadspaControl::linkControls( LadspaControl * _control )
|
||||
BoolModel::linkModels( &m_toggledModel, _control->toggledModel() );
|
||||
break;
|
||||
case INTEGER:
|
||||
case ENUM:
|
||||
case FLOATING:
|
||||
FloatModel::linkModels( &m_knobModel, _control->knobModel() );
|
||||
break;
|
||||
@@ -309,6 +346,7 @@ void LadspaControl::unlinkControls( LadspaControl * _control )
|
||||
BoolModel::unlinkModels( &m_toggledModel, _control->toggledModel() );
|
||||
break;
|
||||
case INTEGER:
|
||||
case ENUM:
|
||||
case FLOATING:
|
||||
FloatModel::unlinkModels( &m_knobModel, _control->knobModel() );
|
||||
break;
|
||||
|
||||
@@ -235,6 +235,26 @@ uint16_t LadspaManager::getPluginOutputs(
|
||||
return outputs;
|
||||
}
|
||||
|
||||
const LADSPA_PortDescriptor* LadspaManager::getPortDescriptor(const ladspa_key_t &_plugin, uint32_t _port)
|
||||
{
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
if( descriptor && _port < getPortCount( _plugin ) )
|
||||
{
|
||||
return( & descriptor->PortDescriptors[_port] );
|
||||
}
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
const LADSPA_PortRangeHint *LadspaManager::getPortRangeHint(const ladspa_key_t &_plugin, uint32_t _port)
|
||||
{
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
if( descriptor && _port < getPortCount( _plugin ) )
|
||||
{
|
||||
return( & descriptor->PortRangeHints[_port] );
|
||||
}
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -248,19 +268,8 @@ l_sortable_plugin_t LadspaManager::getSortedPlugins()
|
||||
|
||||
QString LadspaManager::getLabel( const ladspa_key_t & _plugin )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
return( QString( descriptor->Label ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( QString( "" ) );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ? descriptor->Label : "" );
|
||||
}
|
||||
|
||||
|
||||
@@ -269,19 +278,9 @@ QString LadspaManager::getLabel( const ladspa_key_t & _plugin )
|
||||
bool LadspaManager::hasRealTimeDependency(
|
||||
const ladspa_key_t & _plugin )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
return( LADSPA_IS_REALTIME( descriptor->Properties ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ? LADSPA_IS_REALTIME( descriptor->Properties )
|
||||
: false );
|
||||
}
|
||||
|
||||
|
||||
@@ -289,19 +288,9 @@ bool LadspaManager::hasRealTimeDependency(
|
||||
|
||||
bool LadspaManager::isInplaceBroken( const ladspa_key_t & _plugin )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
return( LADSPA_IS_INPLACE_BROKEN( descriptor->Properties ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ? LADSPA_IS_INPLACE_BROKEN( descriptor->Properties )
|
||||
: false );
|
||||
}
|
||||
|
||||
|
||||
@@ -310,19 +299,9 @@ bool LadspaManager::isInplaceBroken( const ladspa_key_t & _plugin )
|
||||
bool LadspaManager::isRealTimeCapable(
|
||||
const ladspa_key_t & _plugin )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
return( LADSPA_IS_HARD_RT_CAPABLE( descriptor->Properties ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ? LADSPA_IS_HARD_RT_CAPABLE( descriptor->Properties )
|
||||
: false );
|
||||
}
|
||||
|
||||
|
||||
@@ -330,19 +309,8 @@ bool LadspaManager::isRealTimeCapable(
|
||||
|
||||
QString LadspaManager::getName( const ladspa_key_t & _plugin )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
return( QString( descriptor->Name ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( QString( "" ) );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ? descriptor->Name : "" );
|
||||
}
|
||||
|
||||
|
||||
@@ -350,19 +318,8 @@ QString LadspaManager::getName( const ladspa_key_t & _plugin )
|
||||
|
||||
QString LadspaManager::getMaker( const ladspa_key_t & _plugin )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
return( QString( descriptor->Maker ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( QString( "" ) );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ? descriptor->Maker : "" );
|
||||
}
|
||||
|
||||
|
||||
@@ -370,19 +327,8 @@ QString LadspaManager::getMaker( const ladspa_key_t & _plugin )
|
||||
|
||||
QString LadspaManager::getCopyright( const ladspa_key_t & _plugin )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
return( QString( descriptor->Copyright ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( QString( "" ) );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ? descriptor->Copyright : "" );
|
||||
}
|
||||
|
||||
|
||||
@@ -390,19 +336,8 @@ QString LadspaManager::getCopyright( const ladspa_key_t & _plugin )
|
||||
|
||||
uint32_t LadspaManager::getPortCount( const ladspa_key_t & _plugin )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
return( descriptor->PortCount );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ? descriptor->PortCount : 0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -411,22 +346,8 @@ uint32_t LadspaManager::getPortCount( const ladspa_key_t & _plugin )
|
||||
bool LadspaManager::isPortInput( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
|
||||
return( LADSPA_IS_PORT_INPUT
|
||||
( descriptor->PortDescriptors[_port] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
const auto * descriptor = getPortDescriptor( _plugin, _port );
|
||||
return( descriptor && LADSPA_IS_PORT_INPUT( * descriptor ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -435,22 +356,8 @@ bool LadspaManager::isPortInput( const ladspa_key_t & _plugin,
|
||||
bool LadspaManager::isPortOutput( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
|
||||
return( LADSPA_IS_PORT_OUTPUT
|
||||
( descriptor->PortDescriptors[_port] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
const auto * descriptor = getPortDescriptor( _plugin, _port );
|
||||
return( descriptor && LADSPA_IS_PORT_OUTPUT( * descriptor ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -459,22 +366,8 @@ bool LadspaManager::isPortOutput( const ladspa_key_t & _plugin,
|
||||
bool LadspaManager::isPortAudio( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
|
||||
return( LADSPA_IS_PORT_AUDIO
|
||||
( descriptor->PortDescriptors[_port] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
const auto * descriptor = getPortDescriptor( _plugin, _port );
|
||||
return( descriptor && LADSPA_IS_PORT_AUDIO( * descriptor ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -483,22 +376,8 @@ bool LadspaManager::isPortAudio( const ladspa_key_t & _plugin,
|
||||
bool LadspaManager::isPortControl( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
|
||||
return( LADSPA_IS_PORT_CONTROL
|
||||
( descriptor->PortDescriptors[_port] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
const auto * descriptor = getPortDescriptor( _plugin, _port );
|
||||
return( descriptor && LADSPA_IS_PORT_CONTROL( * descriptor ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -508,22 +387,8 @@ bool LadspaManager::areHintsSampleRateDependent(
|
||||
const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
LADSPA_PortRangeHintDescriptor hintDescriptor =
|
||||
descriptor->PortRangeHints[_port].HintDescriptor;
|
||||
return( LADSPA_IS_HINT_SAMPLE_RATE ( hintDescriptor ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
const auto* portRangeHint = getPortRangeHint( _plugin, _port );
|
||||
return portRangeHint && LADSPA_IS_HINT_SAMPLE_RATE( portRangeHint->HintDescriptor );
|
||||
}
|
||||
|
||||
|
||||
@@ -532,59 +397,26 @@ bool LadspaManager::areHintsSampleRateDependent(
|
||||
float LadspaManager::getLowerBound( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
const auto* portRangeHint = getPortRangeHint( _plugin, _port );
|
||||
if( portRangeHint && LADSPA_IS_HINT_BOUNDED_BELOW( portRangeHint->HintDescriptor ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
LADSPA_PortRangeHintDescriptor hintDescriptor =
|
||||
descriptor->PortRangeHints[_port].HintDescriptor;
|
||||
if( LADSPA_IS_HINT_BOUNDED_BELOW( hintDescriptor ) )
|
||||
{
|
||||
return( descriptor->PortRangeHints[_port].LowerBound );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( NOHINT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return( NOHINT );
|
||||
return( portRangeHint->LowerBound );
|
||||
}
|
||||
return( NOHINT );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float LadspaManager::getUpperBound( const ladspa_key_t & _plugin, uint32_t _port )
|
||||
float LadspaManager::getUpperBound( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
const auto* portRangeHint = getPortRangeHint( _plugin, _port );
|
||||
if( portRangeHint && LADSPA_IS_HINT_BOUNDED_ABOVE( portRangeHint->HintDescriptor ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
LADSPA_PortRangeHintDescriptor hintDescriptor =
|
||||
descriptor->PortRangeHints[_port].HintDescriptor;
|
||||
if( LADSPA_IS_HINT_BOUNDED_ABOVE( hintDescriptor ) )
|
||||
{
|
||||
return( descriptor->PortRangeHints[_port].UpperBound );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( NOHINT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return( NOHINT );
|
||||
return( portRangeHint->UpperBound );
|
||||
}
|
||||
return( NOHINT );
|
||||
}
|
||||
|
||||
|
||||
@@ -593,22 +425,8 @@ float LadspaManager::getUpperBound( const ladspa_key_t & _plugin, uint32
|
||||
bool LadspaManager::isPortToggled( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
LADSPA_PortRangeHintDescriptor hintDescriptor =
|
||||
descriptor->PortRangeHints[_port].HintDescriptor;
|
||||
return( LADSPA_IS_HINT_TOGGLED( hintDescriptor ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
const auto* portRangeHint = getPortRangeHint( _plugin, _port );
|
||||
return( portRangeHint && LADSPA_IS_HINT_TOGGLED( portRangeHint->HintDescriptor ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -617,69 +435,54 @@ bool LadspaManager::isPortToggled( const ladspa_key_t & _plugin,
|
||||
float LadspaManager::getDefaultSetting( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
const auto* portRangeHint = getPortRangeHint( _plugin, _port );
|
||||
if( portRangeHint )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
LADSPA_PortRangeHintDescriptor hintDescriptor =
|
||||
descriptor->PortRangeHints[_port].HintDescriptor;
|
||||
LADSPA_PortRangeHintDescriptor hintDescriptor = portRangeHint->HintDescriptor;
|
||||
switch( hintDescriptor & LADSPA_HINT_DEFAULT_MASK )
|
||||
{
|
||||
case LADSPA_HINT_DEFAULT_NONE:
|
||||
return( NOHINT );
|
||||
case LADSPA_HINT_DEFAULT_MINIMUM:
|
||||
return( descriptor->PortRangeHints[_port].
|
||||
LowerBound );
|
||||
return( portRangeHint->LowerBound );
|
||||
case LADSPA_HINT_DEFAULT_LOW:
|
||||
if( LADSPA_IS_HINT_LOGARITHMIC
|
||||
( hintDescriptor ) )
|
||||
{
|
||||
return( exp( log( descriptor->PortRangeHints[_port].LowerBound )
|
||||
* 0.75
|
||||
+ log( descriptor->PortRangeHints[_port].UpperBound )
|
||||
* 0.25 ) );
|
||||
return( exp( log( portRangeHint->LowerBound ) * 0.75 +
|
||||
log( portRangeHint->UpperBound ) * 0.25 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( descriptor->PortRangeHints[_port].LowerBound
|
||||
* 0.75
|
||||
+ descriptor->PortRangeHints[_port].UpperBound
|
||||
* 0.25 );
|
||||
return( portRangeHint->LowerBound * 0.75 +
|
||||
portRangeHint->UpperBound * 0.25 );
|
||||
}
|
||||
case LADSPA_HINT_DEFAULT_MIDDLE:
|
||||
if( LADSPA_IS_HINT_LOGARITHMIC
|
||||
( hintDescriptor ) )
|
||||
{
|
||||
return( sqrt( descriptor->PortRangeHints[_port].LowerBound
|
||||
* descriptor->PortRangeHints[_port].UpperBound ) );
|
||||
return( sqrt( portRangeHint->LowerBound
|
||||
* portRangeHint->UpperBound ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( 0.5 * ( descriptor->PortRangeHints[_port].LowerBound
|
||||
+ descriptor->PortRangeHints[_port].UpperBound ) );
|
||||
return( 0.5 * ( portRangeHint->LowerBound
|
||||
+ portRangeHint->UpperBound ) );
|
||||
}
|
||||
case LADSPA_HINT_DEFAULT_HIGH:
|
||||
if( LADSPA_IS_HINT_LOGARITHMIC
|
||||
( hintDescriptor ) )
|
||||
{
|
||||
return( exp( log( descriptor->PortRangeHints[_port].LowerBound )
|
||||
* 0.25
|
||||
+ log( descriptor->PortRangeHints[_port].UpperBound )
|
||||
* 0.75 ) );
|
||||
return( exp( log( portRangeHint->LowerBound ) * 0.25 +
|
||||
log( portRangeHint->UpperBound ) * 0.75 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( descriptor->PortRangeHints[_port].LowerBound
|
||||
* 0.25
|
||||
+ descriptor->PortRangeHints[_port].UpperBound
|
||||
* 0.75 );
|
||||
return( portRangeHint->LowerBound * 0.25 +
|
||||
portRangeHint->UpperBound * 0.75 );
|
||||
}
|
||||
case LADSPA_HINT_DEFAULT_MAXIMUM:
|
||||
return( descriptor->PortRangeHints[_port].UpperBound );
|
||||
return( portRangeHint->UpperBound );
|
||||
case LADSPA_HINT_DEFAULT_0:
|
||||
return( 0.0 );
|
||||
case LADSPA_HINT_DEFAULT_1:
|
||||
@@ -704,22 +507,8 @@ float LadspaManager::getDefaultSetting( const ladspa_key_t & _plugin,
|
||||
bool LadspaManager::isLogarithmic( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
LADSPA_PortRangeHintDescriptor hintDescriptor =
|
||||
descriptor->PortRangeHints[_port].HintDescriptor;
|
||||
return( LADSPA_IS_HINT_LOGARITHMIC( hintDescriptor ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
const auto* portRangeHint = getPortRangeHint( _plugin, _port );
|
||||
return( portRangeHint && LADSPA_IS_HINT_LOGARITHMIC( portRangeHint->HintDescriptor ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -728,7 +517,16 @@ bool LadspaManager::isLogarithmic( const ladspa_key_t & _plugin,
|
||||
bool LadspaManager::isInteger( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
const auto* portRangeHint = getPortRangeHint( _plugin, _port );
|
||||
return( portRangeHint && LADSPA_IS_HINT_INTEGER( portRangeHint->HintDescriptor ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool LadspaManager::isEnum( const ladspa_key_t & _plugin, uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
@@ -738,7 +536,9 @@ bool LadspaManager::isInteger( const ladspa_key_t & _plugin,
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
LADSPA_PortRangeHintDescriptor hintDescriptor =
|
||||
descriptor->PortRangeHints[_port].HintDescriptor;
|
||||
return( LADSPA_IS_HINT_INTEGER( hintDescriptor ) );
|
||||
// This is an LMMS extension to ladspa
|
||||
return( LADSPA_IS_HINT_INTEGER( hintDescriptor ) &&
|
||||
LADSPA_IS_HINT_TOGGLED( hintDescriptor ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -752,21 +552,8 @@ bool LadspaManager::isInteger( const ladspa_key_t & _plugin,
|
||||
QString LadspaManager::getPortName( const ladspa_key_t & _plugin,
|
||||
uint32_t _port )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) &&
|
||||
_port < getPortCount( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
|
||||
return( QString( descriptor->PortNames[_port] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( QString( "" ) );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ? descriptor->PortNames[_port] : QString( "" ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -775,19 +562,8 @@ QString LadspaManager::getPortName( const ladspa_key_t & _plugin,
|
||||
const void * LadspaManager::getImplementationData(
|
||||
const ladspa_key_t & _plugin )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
return( descriptor->ImplementationData );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( NULL );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ? descriptor->ImplementationData : NULL );
|
||||
}
|
||||
|
||||
|
||||
@@ -818,20 +594,10 @@ LADSPA_Handle LadspaManager::instantiate(
|
||||
const ladspa_key_t & _plugin,
|
||||
uint32_t _sample_rate )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
return( ( descriptor->instantiate )
|
||||
( descriptor, _sample_rate ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( NULL );
|
||||
}
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
return( descriptor ?
|
||||
( descriptor->instantiate )( descriptor, _sample_rate ) :
|
||||
NULL );
|
||||
}
|
||||
|
||||
|
||||
@@ -842,20 +608,13 @@ bool LadspaManager::connectPort( const ladspa_key_t & _plugin,
|
||||
uint32_t _port,
|
||||
LADSPA_Data * _data_location )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin )
|
||||
&& _port < getPortCount( _plugin ) )
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
if( descriptor && descriptor->connect_port != NULL &&
|
||||
_port < getPortCount( _plugin ) )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
if( descriptor->connect_port != NULL )
|
||||
{
|
||||
( descriptor->connect_port )
|
||||
( _instance, _port, _data_location );
|
||||
return( true );
|
||||
}
|
||||
( descriptor->connect_port )
|
||||
( _instance, _port, _data_location );
|
||||
return( true );
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
@@ -866,18 +625,11 @@ bool LadspaManager::connectPort( const ladspa_key_t & _plugin,
|
||||
bool LadspaManager::activate( const ladspa_key_t & _plugin,
|
||||
LADSPA_Handle _instance )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
if( descriptor && descriptor->activate != NULL )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
if( descriptor->activate != NULL )
|
||||
{
|
||||
( descriptor->activate ) ( _instance );
|
||||
return( true );
|
||||
}
|
||||
( descriptor->activate ) ( _instance );
|
||||
return( true );
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
@@ -889,18 +641,11 @@ bool LadspaManager::run( const ladspa_key_t & _plugin,
|
||||
LADSPA_Handle _instance,
|
||||
uint32_t _sample_count )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
if( descriptor && descriptor->run!= NULL )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
if( descriptor->run != NULL )
|
||||
{
|
||||
( descriptor->run ) ( _instance, _sample_count );
|
||||
return( true );
|
||||
}
|
||||
( descriptor->run ) ( _instance, _sample_count );
|
||||
return( true );
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
@@ -912,19 +657,12 @@ bool LadspaManager::runAdding( const ladspa_key_t & _plugin,
|
||||
LADSPA_Handle _instance,
|
||||
uint32_t _sample_count )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
if( descriptor && descriptor->run_adding!= NULL
|
||||
&& descriptor->set_run_adding_gain != NULL )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
if( descriptor->run_adding != NULL &&
|
||||
descriptor->set_run_adding_gain != NULL )
|
||||
{
|
||||
( descriptor->run_adding ) ( _instance, _sample_count );
|
||||
return( true );
|
||||
}
|
||||
( descriptor->run_adding ) ( _instance, _sample_count );
|
||||
return( true );
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
@@ -936,20 +674,12 @@ bool LadspaManager::setRunAddingGain( const ladspa_key_t & _plugin,
|
||||
LADSPA_Handle _instance,
|
||||
LADSPA_Data _gain )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
if( descriptor && descriptor->run_adding!= NULL
|
||||
&& descriptor->set_run_adding_gain != NULL )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
if( descriptor->run_adding != NULL &&
|
||||
descriptor->set_run_adding_gain != NULL )
|
||||
{
|
||||
( descriptor->set_run_adding_gain )
|
||||
( _instance, _gain );
|
||||
return( true );
|
||||
}
|
||||
( descriptor->set_run_adding_gain ) ( _instance, _gain );
|
||||
return( true );
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
@@ -960,18 +690,11 @@ bool LadspaManager::setRunAddingGain( const ladspa_key_t & _plugin,
|
||||
bool LadspaManager::deactivate( const ladspa_key_t & _plugin,
|
||||
LADSPA_Handle _instance )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
if( descriptor && descriptor->deactivate!= NULL )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
if( descriptor->deactivate != NULL )
|
||||
{
|
||||
( descriptor->deactivate ) ( _instance );
|
||||
return( true );
|
||||
}
|
||||
( descriptor->deactivate ) ( _instance );
|
||||
return( true );
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
@@ -982,18 +705,11 @@ bool LadspaManager::deactivate( const ladspa_key_t & _plugin,
|
||||
bool LadspaManager::cleanup( const ladspa_key_t & _plugin,
|
||||
LADSPA_Handle _instance )
|
||||
{
|
||||
if( m_ladspaManagerMap.contains( _plugin ) )
|
||||
const LADSPA_Descriptor * descriptor = getDescriptor( _plugin );
|
||||
if( descriptor && descriptor->cleanup!= NULL )
|
||||
{
|
||||
LADSPA_Descriptor_Function descriptorFunction =
|
||||
m_ladspaManagerMap[_plugin]->descriptorFunction;
|
||||
const LADSPA_Descriptor * descriptor =
|
||||
descriptorFunction(
|
||||
m_ladspaManagerMap[_plugin]->index );
|
||||
if( descriptor->cleanup != NULL )
|
||||
{
|
||||
( descriptor->cleanup ) ( _instance );
|
||||
return( true );
|
||||
}
|
||||
( descriptor->cleanup ) ( _instance );
|
||||
return( true );
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "LocklessAllocator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
@@ -55,9 +56,11 @@ LocklessAllocator::LocklessAllocator( size_t nmemb, size_t size )
|
||||
m_pool = new char[m_capacity * m_elementSize];
|
||||
|
||||
m_freeStateSets = m_capacity / SIZEOF_SET;
|
||||
m_freeState = new AtomicInt[m_freeStateSets];
|
||||
m_freeState = new std::atomic_int[m_freeStateSets];
|
||||
std::fill(m_freeState, m_freeState + m_freeStateSets, 0);
|
||||
|
||||
m_available = m_capacity;
|
||||
m_startIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,27 +104,27 @@ static int ffs( int i )
|
||||
|
||||
void * LocklessAllocator::alloc()
|
||||
{
|
||||
int available;
|
||||
// Some of these CAS loops could probably use relaxed atomics, as discussed
|
||||
// in http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange.
|
||||
// Let's use sequentially-consistent ops to be safe for now.
|
||||
int available = m_available.load();
|
||||
do
|
||||
{
|
||||
available = m_available;
|
||||
if( !available )
|
||||
{
|
||||
fprintf( stderr, "LocklessAllocator: No free space\n" );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
while( !m_available.testAndSetOrdered( available, available - 1 ) );
|
||||
while (!m_available.compare_exchange_weak(available, available - 1));
|
||||
|
||||
size_t startIndex = m_startIndex.fetchAndAddOrdered( 1 )
|
||||
% m_freeStateSets;
|
||||
for( size_t set = startIndex;; set = ( set + 1 ) % m_freeStateSets )
|
||||
const size_t startIndex = m_startIndex++ % m_freeStateSets;
|
||||
for (size_t set = startIndex;; set = ( set + 1 ) % m_freeStateSets)
|
||||
{
|
||||
for( int freeState = m_freeState[set]; freeState != -1;
|
||||
freeState = m_freeState[set] )
|
||||
for (int freeState = m_freeState[set]; freeState != -1;)
|
||||
{
|
||||
int bit = ffs( ~freeState ) - 1;
|
||||
if( m_freeState[set].testAndSetOrdered( freeState,
|
||||
if (m_freeState[set].compare_exchange_weak(freeState,
|
||||
freeState | 1 << bit ) )
|
||||
{
|
||||
return m_pool + ( SIZEOF_SET * set + bit )
|
||||
@@ -151,11 +154,11 @@ invalid:
|
||||
size_t set = offset / SIZEOF_SET;
|
||||
int bit = offset % SIZEOF_SET;
|
||||
int mask = 1 << bit;
|
||||
int prevState = m_freeState[set].fetchAndAndOrdered( ~mask );
|
||||
int prevState = m_freeState[set].fetch_and(~mask);
|
||||
if ( !( prevState & mask ) )
|
||||
{
|
||||
fprintf( stderr, "LocklessAllocator: Block not in use\n" );
|
||||
return;
|
||||
}
|
||||
m_available.fetchAndAddOrdered( 1 );
|
||||
++m_available;
|
||||
}
|
||||
|
||||
@@ -24,9 +24,11 @@
|
||||
|
||||
#include "MixerWorkerThread.h"
|
||||
|
||||
#include "denormals.h"
|
||||
#include <xmmintrin.h>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include "denormals.h"
|
||||
#include "ThreadableJob.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
@@ -52,7 +54,7 @@ void MixerWorkerThread::JobQueue::addJob( ThreadableJob * _job )
|
||||
// update job state
|
||||
_job->queue();
|
||||
// actually queue the job via atomic operations
|
||||
m_items[m_queueSize.fetchAndAddOrdered(1)] = _job;
|
||||
m_items[m_queueSize++] = _job;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,17 +63,17 @@ void MixerWorkerThread::JobQueue::addJob( ThreadableJob * _job )
|
||||
void MixerWorkerThread::JobQueue::run()
|
||||
{
|
||||
bool processedJob = true;
|
||||
while( processedJob && (int) m_itemsDone < (int) m_queueSize )
|
||||
while (processedJob && m_itemsDone < m_queueSize)
|
||||
{
|
||||
processedJob = false;
|
||||
for( int i = 0; i < m_queueSize; ++i )
|
||||
{
|
||||
ThreadableJob * job = m_items[i].fetchAndStoreOrdered( NULL );
|
||||
ThreadableJob * job = m_items[i].exchange(nullptr);
|
||||
if( job )
|
||||
{
|
||||
job->process();
|
||||
processedJob = true;
|
||||
m_itemsDone.fetchAndAddOrdered( 1 );
|
||||
++m_itemsDone;
|
||||
}
|
||||
}
|
||||
// always exit loop if we're not in dynamic mode
|
||||
@@ -84,7 +86,7 @@ void MixerWorkerThread::JobQueue::run()
|
||||
|
||||
void MixerWorkerThread::JobQueue::wait()
|
||||
{
|
||||
while( (int) m_itemsDone < (int) m_queueSize )
|
||||
while (m_itemsDone < m_queueSize)
|
||||
{
|
||||
#if defined(LMMS_HOST_X86) || defined(LMMS_HOST_X86_64)
|
||||
_mm_pause();
|
||||
|
||||
@@ -53,7 +53,6 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
|
||||
PlayHandle( TypeNotePlayHandle, _offset ),
|
||||
Note( n.length(), n.pos(), n.key(), n.getVolume(), n.getPanning(), n.detuning() ),
|
||||
m_pluginData( NULL ),
|
||||
m_filter( NULL ),
|
||||
m_instrumentTrack( instrumentTrack ),
|
||||
m_frames( 0 ),
|
||||
m_totalFramesPlayed( 0 ),
|
||||
@@ -155,8 +154,6 @@ NotePlayHandle::~NotePlayHandle()
|
||||
|
||||
m_subNotes.clear();
|
||||
|
||||
delete m_filter;
|
||||
|
||||
if( buffer() ) releaseBuffer();
|
||||
|
||||
unlock();
|
||||
@@ -554,7 +551,7 @@ void NotePlayHandle::resize( const bpm_t _new_tempo )
|
||||
|
||||
NotePlayHandle ** NotePlayHandleManager::s_available;
|
||||
QReadWriteLock NotePlayHandleManager::s_mutex;
|
||||
AtomicInt NotePlayHandleManager::s_availableIndex;
|
||||
std::atomic_int NotePlayHandleManager::s_availableIndex;
|
||||
int NotePlayHandleManager::s_size;
|
||||
|
||||
|
||||
@@ -589,7 +586,7 @@ NotePlayHandle * NotePlayHandleManager::acquire( InstrumentTrack* instrumentTrac
|
||||
s_mutex.unlock();
|
||||
}
|
||||
s_mutex.lockForRead();
|
||||
NotePlayHandle * nph = s_available[ s_availableIndex.fetchAndAddOrdered( -1 ) ];
|
||||
NotePlayHandle * nph = s_available[s_availableIndex--];
|
||||
s_mutex.unlock();
|
||||
|
||||
new( (void*)nph ) NotePlayHandle( instrumentTrack, offset, frames, noteToPlay, parent, midiEventChannel, origin );
|
||||
@@ -601,7 +598,7 @@ void NotePlayHandleManager::release( NotePlayHandle * nph )
|
||||
{
|
||||
nph->NotePlayHandle::~NotePlayHandle();
|
||||
s_mutex.lockForRead();
|
||||
s_available[ s_availableIndex.fetchAndAddOrdered( 1 ) + 1 ] = nph;
|
||||
s_available[++s_availableIndex] = nph;
|
||||
s_mutex.unlock();
|
||||
}
|
||||
|
||||
@@ -617,7 +614,7 @@ void NotePlayHandleManager::extend( int c )
|
||||
|
||||
for( int i=0; i < c; ++i )
|
||||
{
|
||||
s_available[ s_availableIndex.fetchAndAddOrdered( 1 ) + 1 ] = n;
|
||||
s_available[++s_availableIndex] = n;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
131
src/core/PerfLog.cpp
Normal file
131
src/core/PerfLog.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* PerfLog.cpp - Small performance logger
|
||||
*
|
||||
* Copyright (c) 2017-2018 LMMS Developers
|
||||
*
|
||||
* 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 "PerfLog.h"
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#if defined(LMMS_HAVE_SYS_TIMES_H) && defined(LMMS_HAVE_UNISTD_H)
|
||||
# define USE_POSIX_TIME
|
||||
#endif
|
||||
|
||||
#ifdef USE_POSIX_TIME
|
||||
# include <unistd.h>
|
||||
# include <sys/times.h>
|
||||
#endif
|
||||
|
||||
PerfTime::PerfTime()
|
||||
: m_real(-1)
|
||||
{
|
||||
}
|
||||
|
||||
clock_t PerfTime::real() const
|
||||
{
|
||||
return m_real;
|
||||
}
|
||||
|
||||
clock_t PerfTime::user() const
|
||||
{
|
||||
return m_user;
|
||||
}
|
||||
|
||||
clock_t PerfTime::system() const
|
||||
{
|
||||
return m_system;
|
||||
}
|
||||
|
||||
bool PerfTime::valid() const
|
||||
{
|
||||
return m_real != -1;
|
||||
}
|
||||
|
||||
PerfTime PerfTime::now()
|
||||
{
|
||||
PerfTime time;
|
||||
#ifdef USE_POSIX_TIME
|
||||
tms t;
|
||||
time.m_real = times(&t);
|
||||
time.m_user = t.tms_utime;
|
||||
time.m_system = t.tms_stime;
|
||||
if (time.m_real == -1) { qWarning("PerfTime: now failed"); }
|
||||
#endif
|
||||
return time;
|
||||
}
|
||||
|
||||
clock_t PerfTime::ticksPerSecond()
|
||||
{
|
||||
static long clktck = 0;
|
||||
#ifdef USE_POSIX_TIME
|
||||
if (!clktck) {
|
||||
if ((clktck = sysconf(_SC_CLK_TCK)) < 0) {
|
||||
qWarning("PerfLog::end sysconf()");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return clktck;
|
||||
}
|
||||
|
||||
PerfTime operator-(const PerfTime& lhs, const PerfTime& rhs)
|
||||
{
|
||||
PerfTime diff;
|
||||
diff.m_real = lhs.m_real - rhs.m_real;
|
||||
diff.m_user = lhs.m_user - rhs.m_user;
|
||||
diff.m_system = lhs.m_system - rhs.m_system;
|
||||
return diff;
|
||||
}
|
||||
|
||||
PerfLogTimer::PerfLogTimer(const QString& what)
|
||||
: name(what)
|
||||
{
|
||||
begin();
|
||||
}
|
||||
|
||||
PerfLogTimer::~PerfLogTimer()
|
||||
{
|
||||
end();
|
||||
}
|
||||
|
||||
void PerfLogTimer::begin()
|
||||
{
|
||||
begin_time = PerfTime::now();
|
||||
}
|
||||
|
||||
void PerfLogTimer::end()
|
||||
{
|
||||
if (! begin_time.valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
long clktck = PerfTime::ticksPerSecond();
|
||||
|
||||
PerfTime d = PerfTime::now() - begin_time;
|
||||
qWarning("PERFLOG | %20s | %.2fuser, %.2fsystem %.2felapsed",
|
||||
qPrintable(name),
|
||||
d.user() / (double)clktck,
|
||||
d.system() / (double)clktck,
|
||||
d.real() / (double)clktck);
|
||||
|
||||
// Invalidate so destructor won't call print another log entry
|
||||
begin_time = PerfTime();
|
||||
}
|
||||
@@ -22,7 +22,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QAtomicPointer>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "PresetPreviewPlayHandle.h"
|
||||
@@ -34,7 +33,7 @@
|
||||
#include "ProjectJournal.h"
|
||||
#include "TrackContainer.h"
|
||||
|
||||
|
||||
#include <atomic>
|
||||
|
||||
// invisible track-container which is needed as parent for preview-channels
|
||||
class PreviewTrackContainer : public TrackContainer
|
||||
@@ -67,25 +66,17 @@ public:
|
||||
|
||||
NotePlayHandle* previewNote()
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
return m_previewNote.loadAcquire();
|
||||
#else
|
||||
return m_previewNote;
|
||||
#endif
|
||||
return m_previewNote.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
void setPreviewNote( NotePlayHandle * _note )
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
m_previewNote.storeRelease( _note );
|
||||
#else
|
||||
m_previewNote = _note;
|
||||
#endif
|
||||
m_previewNote.store(_note, std::memory_order_release);
|
||||
}
|
||||
|
||||
bool testAndSetPreviewNote( NotePlayHandle * expectedVal, NotePlayHandle * newVal )
|
||||
{
|
||||
return m_previewNote.testAndSetOrdered( expectedVal, newVal );
|
||||
return m_previewNote.compare_exchange_strong(expectedVal, newVal);
|
||||
}
|
||||
|
||||
void lockData()
|
||||
@@ -111,7 +102,7 @@ public:
|
||||
|
||||
private:
|
||||
InstrumentTrack* m_previewInstrumentTrack;
|
||||
QAtomicPointer<NotePlayHandle> m_previewNote;
|
||||
std::atomic<NotePlayHandle*> m_previewNote;
|
||||
QMutex m_dataMutex;
|
||||
|
||||
friend class PresetPreviewPlayHandle;
|
||||
@@ -125,7 +116,7 @@ PreviewTrackContainer * PresetPreviewPlayHandle::s_previewTC;
|
||||
|
||||
PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, bool _load_by_plugin, DataFile *dataFile ) :
|
||||
PlayHandle( TypePresetPreviewHandle ),
|
||||
m_previewNote( NULL )
|
||||
m_previewNote(nullptr)
|
||||
{
|
||||
setUsesBuffer( false );
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "ProjectRenderer.h"
|
||||
#include "Song.h"
|
||||
#include "PerfLog.h"
|
||||
|
||||
#include "AudioFileWave.h"
|
||||
#include "AudioFileOgg.h"
|
||||
@@ -177,6 +178,8 @@ void ProjectRenderer::run()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
PerfLogTimer perfLog("Project Render");
|
||||
|
||||
Engine::getSong()->startExport();
|
||||
Engine::getSong()->updateLength();
|
||||
// Skip first empty buffer.
|
||||
@@ -209,6 +212,8 @@ void ProjectRenderer::run()
|
||||
|
||||
Engine::getSong()->stopExport();
|
||||
|
||||
perfLog.end();
|
||||
|
||||
// If the user aborted export-process, the file has to be deleted.
|
||||
const QString f = m_fileDev->outputFile();
|
||||
if( m_abort )
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "Song.h"
|
||||
#include "BBTrackContainer.h"
|
||||
#include "BBTrack.h"
|
||||
#include "stdshims.h"
|
||||
|
||||
|
||||
RenderManager::RenderManager(
|
||||
@@ -40,17 +41,13 @@ RenderManager::RenderManager(
|
||||
m_oldQualitySettings( Engine::mixer()->currentQualitySettings() ),
|
||||
m_outputSettings(outputSettings),
|
||||
m_format(fmt),
|
||||
m_outputPath(outputPath),
|
||||
m_activeRenderer(NULL)
|
||||
m_outputPath(outputPath)
|
||||
{
|
||||
Engine::mixer()->storeAudioDevice();
|
||||
}
|
||||
|
||||
RenderManager::~RenderManager()
|
||||
{
|
||||
delete m_activeRenderer;
|
||||
m_activeRenderer = NULL;
|
||||
|
||||
Engine::mixer()->restoreAudioDevice(); // Also deletes audio dev.
|
||||
Engine::mixer()->changeQuality( m_oldQualitySettings );
|
||||
}
|
||||
@@ -58,7 +55,7 @@ RenderManager::~RenderManager()
|
||||
void RenderManager::abortProcessing()
|
||||
{
|
||||
if ( m_activeRenderer ) {
|
||||
disconnect( m_activeRenderer, SIGNAL( finished() ),
|
||||
disconnect( m_activeRenderer.get(), SIGNAL( finished() ),
|
||||
this, SLOT( renderNextTrack() ) );
|
||||
m_activeRenderer->abortProcessing();
|
||||
}
|
||||
@@ -68,8 +65,7 @@ void RenderManager::abortProcessing()
|
||||
// Called to render each new track when rendering tracks individually.
|
||||
void RenderManager::renderNextTrack()
|
||||
{
|
||||
delete m_activeRenderer;
|
||||
m_activeRenderer = NULL;
|
||||
m_activeRenderer.reset();
|
||||
|
||||
if( m_tracksToRender.isEmpty() )
|
||||
{
|
||||
@@ -92,30 +88,7 @@ void RenderManager::renderNextTrack()
|
||||
// for multi-render, prefix each output file with a different number
|
||||
int trackNum = m_tracksToRender.size() + 1;
|
||||
|
||||
// create a renderer for this track
|
||||
m_activeRenderer = new ProjectRenderer(
|
||||
m_qualitySettings,
|
||||
m_outputSettings,
|
||||
m_format,
|
||||
pathForTrack(renderTrack, trackNum));
|
||||
|
||||
if ( m_activeRenderer->isReady() )
|
||||
{
|
||||
// pass progress signals through
|
||||
connect( m_activeRenderer, SIGNAL( progressChanged( int ) ),
|
||||
this, SIGNAL( progressChanged( int ) ) );
|
||||
|
||||
// when it is finished, render the next track
|
||||
connect( m_activeRenderer, SIGNAL( finished() ),
|
||||
this, SLOT( renderNextTrack() ) );
|
||||
|
||||
m_activeRenderer->startProcessing();
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug( "Renderer failed to acquire a file device!" );
|
||||
renderNextTrack();
|
||||
}
|
||||
render( pathForTrack(renderTrack, trackNum) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,20 +131,26 @@ void RenderManager::renderTracks()
|
||||
// Render the song into a single track
|
||||
void RenderManager::renderProject()
|
||||
{
|
||||
m_activeRenderer = new ProjectRenderer(
|
||||
render( m_outputPath );
|
||||
}
|
||||
|
||||
void RenderManager::render(QString outputPath)
|
||||
{
|
||||
m_activeRenderer = make_unique<ProjectRenderer>(
|
||||
m_qualitySettings,
|
||||
m_outputSettings,
|
||||
m_format,
|
||||
m_outputPath);
|
||||
outputPath);
|
||||
|
||||
if( m_activeRenderer->isReady() )
|
||||
{
|
||||
// pass progress signals through
|
||||
connect( m_activeRenderer, SIGNAL( progressChanged( int ) ),
|
||||
connect( m_activeRenderer.get(), SIGNAL( progressChanged( int ) ),
|
||||
this, SIGNAL( progressChanged( int ) ) );
|
||||
|
||||
// as we have not queued any tracks, renderNextTrack will just clean up
|
||||
connect( m_activeRenderer, SIGNAL( finished() ),
|
||||
// when it is finished, render the next track.
|
||||
// if we have not queued any tracks, renderNextTrack will just clean up
|
||||
connect( m_activeRenderer.get(), SIGNAL( finished() ),
|
||||
this, SLOT( renderNextTrack() ) );
|
||||
|
||||
m_activeRenderer->startProcessing();
|
||||
@@ -179,7 +158,7 @@ void RenderManager::renderProject()
|
||||
else
|
||||
{
|
||||
qDebug( "Renderer failed to acquire a file device!" );
|
||||
emit finished();
|
||||
renderNextTrack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,34 +59,8 @@
|
||||
#include "FileDialog.h"
|
||||
|
||||
|
||||
SampleBuffer::SampleBuffer( const QString & _audio_file,
|
||||
bool _is_base64_data ) :
|
||||
m_audioFile( ( _is_base64_data == true ) ? "" : _audio_file ),
|
||||
m_origData( NULL ),
|
||||
m_origFrames( 0 ),
|
||||
m_data( NULL ),
|
||||
m_frames( 0 ),
|
||||
m_startFrame( 0 ),
|
||||
m_endFrame( 0 ),
|
||||
m_loopStartFrame( 0 ),
|
||||
m_loopEndFrame( 0 ),
|
||||
m_amplification( 1.0f ),
|
||||
m_reversed( false ),
|
||||
m_frequency( BaseFreq ),
|
||||
m_sampleRate( Engine::mixer()->baseSampleRate() )
|
||||
{
|
||||
if( _is_base64_data == true )
|
||||
{
|
||||
loadFromBase64( _audio_file );
|
||||
}
|
||||
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) );
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SampleBuffer::SampleBuffer( const sampleFrame * _data, const f_cnt_t _frames ) :
|
||||
SampleBuffer::SampleBuffer() :
|
||||
m_audioFile( "" ),
|
||||
m_origData( NULL ),
|
||||
m_origFrames( 0 ),
|
||||
@@ -101,42 +75,56 @@ SampleBuffer::SampleBuffer( const sampleFrame * _data, const f_cnt_t _frames ) :
|
||||
m_frequency( BaseFreq ),
|
||||
m_sampleRate( Engine::mixer()->baseSampleRate() )
|
||||
{
|
||||
|
||||
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) );
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
SampleBuffer::SampleBuffer( const QString & _audio_file,
|
||||
bool _is_base64_data )
|
||||
: SampleBuffer()
|
||||
{
|
||||
if( _is_base64_data )
|
||||
{
|
||||
loadFromBase64( _audio_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_audioFile = _audio_file;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SampleBuffer::SampleBuffer( const sampleFrame * _data, const f_cnt_t _frames )
|
||||
: SampleBuffer()
|
||||
{
|
||||
if( _frames > 0 )
|
||||
{
|
||||
m_origData = MM_ALLOC( sampleFrame, _frames );
|
||||
memcpy( m_origData, _data, _frames * BYTES_PER_FRAME );
|
||||
m_origFrames = _frames;
|
||||
update();
|
||||
}
|
||||
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) );
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SampleBuffer::SampleBuffer( const f_cnt_t _frames ) :
|
||||
m_audioFile( "" ),
|
||||
m_origData( NULL ),
|
||||
m_origFrames( 0 ),
|
||||
m_data( NULL ),
|
||||
m_frames( 0 ),
|
||||
m_startFrame( 0 ),
|
||||
m_endFrame( 0 ),
|
||||
m_loopStartFrame( 0 ),
|
||||
m_loopEndFrame( 0 ),
|
||||
m_amplification( 1.0f ),
|
||||
m_reversed( false ),
|
||||
m_frequency( BaseFreq ),
|
||||
m_sampleRate( Engine::mixer()->baseSampleRate() )
|
||||
SampleBuffer::SampleBuffer( const f_cnt_t _frames )
|
||||
: SampleBuffer()
|
||||
{
|
||||
if( _frames > 0 )
|
||||
{
|
||||
m_origData = MM_ALLOC( sampleFrame, _frames );
|
||||
memset( m_origData, 0, _frames * BYTES_PER_FRAME );
|
||||
m_origFrames = _frames;
|
||||
update();
|
||||
}
|
||||
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) );
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,23 +32,6 @@
|
||||
|
||||
|
||||
|
||||
SamplePlayHandle::SamplePlayHandle( const QString& sampleFile ) :
|
||||
PlayHandle( TypeSamplePlayHandle ),
|
||||
m_sampleBuffer( new SampleBuffer( sampleFile ) ),
|
||||
m_doneMayReturnTrue( true ),
|
||||
m_frame( 0 ),
|
||||
m_ownAudioPort( true ),
|
||||
m_defaultVolumeModel( DefaultVolume, MinVolume, MaxVolume, 1 ),
|
||||
m_volumeModel( &m_defaultVolumeModel ),
|
||||
m_track( NULL ),
|
||||
m_bbTrack( NULL )
|
||||
{
|
||||
setAudioPort( new AudioPort( "SamplePlayHandle", false ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SamplePlayHandle::SamplePlayHandle( SampleBuffer* sampleBuffer ) :
|
||||
PlayHandle( TypeSamplePlayHandle ),
|
||||
m_sampleBuffer( sharedObject::ref( sampleBuffer ) ),
|
||||
@@ -66,17 +49,20 @@ SamplePlayHandle::SamplePlayHandle( SampleBuffer* sampleBuffer ) :
|
||||
|
||||
|
||||
|
||||
SamplePlayHandle::SamplePlayHandle( SampleTCO* tco ) :
|
||||
PlayHandle( TypeSamplePlayHandle ),
|
||||
m_sampleBuffer( sharedObject::ref( tco->sampleBuffer() ) ),
|
||||
m_doneMayReturnTrue( true ),
|
||||
m_frame( 0 ),
|
||||
m_ownAudioPort( false ),
|
||||
m_defaultVolumeModel( DefaultVolume, MinVolume, MaxVolume, 1 ),
|
||||
m_volumeModel( &m_defaultVolumeModel ),
|
||||
m_track( tco->getTrack() ),
|
||||
m_bbTrack( NULL )
|
||||
SamplePlayHandle::SamplePlayHandle( const QString& sampleFile ) :
|
||||
SamplePlayHandle( new SampleBuffer( sampleFile ) )
|
||||
{
|
||||
sharedObject::unref( m_sampleBuffer );
|
||||
setAudioPort( new AudioPort( "SamplePlayHandle", false ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SamplePlayHandle::SamplePlayHandle( SampleTCO* tco ) :
|
||||
SamplePlayHandle( tco->sampleBuffer() )
|
||||
{
|
||||
m_track = tco->getTrack();
|
||||
setAudioPort( ( (SampleTrack *)tco->getTrack() )->audioPort() );
|
||||
}
|
||||
|
||||
|
||||
@@ -1932,34 +1932,31 @@ void TrackOperationsWidget::updateMenu()
|
||||
}
|
||||
|
||||
|
||||
void TrackOperationsWidget::recordingOn()
|
||||
void TrackOperationsWidget::toggleRecording( bool on )
|
||||
{
|
||||
AutomationTrackView * atv = dynamic_cast<AutomationTrackView *>( m_trackView );
|
||||
if( atv )
|
||||
{
|
||||
const Track::tcoVector & tcov = atv->getTrack()->getTCOs();
|
||||
for( Track::tcoVector::const_iterator it = tcov.begin(); it != tcov.end(); ++it )
|
||||
for( TrackContentObject * tco : atv->getTrack()->getTCOs() )
|
||||
{
|
||||
AutomationPattern * ap = dynamic_cast<AutomationPattern *>( *it );
|
||||
if( ap ) { ap->setRecording( true ); }
|
||||
AutomationPattern * ap = dynamic_cast<AutomationPattern *>( tco );
|
||||
if( ap ) { ap->setRecording( on ); }
|
||||
}
|
||||
atv->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TrackOperationsWidget::recordingOn()
|
||||
{
|
||||
toggleRecording( true );
|
||||
}
|
||||
|
||||
|
||||
void TrackOperationsWidget::recordingOff()
|
||||
{
|
||||
AutomationTrackView * atv = dynamic_cast<AutomationTrackView *>( m_trackView );
|
||||
if( atv )
|
||||
{
|
||||
const Track::tcoVector & tcov = atv->getTrack()->getTCOs();
|
||||
for( Track::tcoVector::const_iterator it = tcov.begin(); it != tcov.end(); ++it )
|
||||
{
|
||||
AutomationPattern * ap = dynamic_cast<AutomationPattern *>( *it );
|
||||
if( ap ) { ap->setRecording( false ); }
|
||||
}
|
||||
atv->update();
|
||||
}
|
||||
toggleRecording( false );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#ifdef LMMS_HAVE_OGGVORBIS
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vorbis/vorbisenc.h>
|
||||
|
||||
#include "Mixer.h"
|
||||
@@ -71,9 +72,9 @@ bool AudioFileOgg::startEncoding()
|
||||
{
|
||||
vorbis_comment vc;
|
||||
const char * comments = "Cool=This song has been made using LMMS";
|
||||
int comment_length = strlen( comments );
|
||||
char * user_comments = new char[comment_length + 1];
|
||||
strcpy( user_comments, comments );
|
||||
std::string user_comments_str(comments);
|
||||
int comment_length = user_comments_str.size();
|
||||
char * user_comments = &user_comments_str[0];
|
||||
|
||||
vc.user_comments = &user_comments;
|
||||
vc.comment_lengths = &comment_length;
|
||||
@@ -113,7 +114,6 @@ bool AudioFileOgg::startEncoding()
|
||||
printf( "Mode initialization failed: invalid parameters for "
|
||||
"bitrate\n" );
|
||||
vorbis_info_clear( &m_vi );
|
||||
delete[] user_comments;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -169,12 +169,10 @@ bool AudioFileOgg::startEncoding()
|
||||
{
|
||||
// clean up
|
||||
finishEncoding();
|
||||
delete[] user_comments;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] user_comments;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user