Merge branch 'master' into groove
This commit is contained in:
@@ -22,9 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ABOUT_DIALOG_H
|
||||
#define ABOUT_DIALOG_H
|
||||
#ifndef LMMS_GUI_ABOUT_DIALOG_H
|
||||
#define LMMS_GUI_ABOUT_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
@@ -42,5 +41,4 @@ public:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LMMS_GUI_ABOUT_DIALOG_H
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ACTION_GROUP_H
|
||||
#define ACTION_GROUP_H
|
||||
#ifndef LMMS_GUI_ACTION_GROUP_H
|
||||
#define LMMS_GUI_ACTION_GROUP_H
|
||||
|
||||
#include <QActionGroup>
|
||||
|
||||
@@ -59,4 +58,4 @@ private:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_ACTION_GROUP_H
|
||||
|
||||
388
include/ArrayVector.h
Normal file
388
include/ArrayVector.h
Normal file
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* ArrayVector.h
|
||||
*
|
||||
* Copyright (c) 2023 Dominic Clark
|
||||
*
|
||||
* 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 LMMS_ARRAY_VECTOR_H
|
||||
#define LMMS_ARRAY_VECTOR_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
namespace lmms {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, typename = void>
|
||||
constexpr bool is_input_iterator_v = false;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_input_iterator_v<T, std::void_t<typename std::iterator_traits<T>::iterator_category>> =
|
||||
std::is_convertible_v<typename std::iterator_traits<T>::iterator_category, std::input_iterator_tag>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* A container that stores up to a maximum of `N` elements of type `T` directly
|
||||
* within itself, rather than separately on the heap. Useful when a dynamically
|
||||
* resizeable container is needed for use in real-time code. Can be thought of
|
||||
* as a hybrid between `std::array` and `std::vector`. The interface follows
|
||||
* that of `std::vector` - see standard C++ documentation.
|
||||
*/
|
||||
template<typename T, std::size_t N>
|
||||
class ArrayVector
|
||||
{
|
||||
public:
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = T;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
ArrayVector() = default;
|
||||
|
||||
ArrayVector(const ArrayVector& other) noexcept(std::is_nothrow_copy_constructible_v<T>) :
|
||||
m_size{other.m_size}
|
||||
{
|
||||
std::uninitialized_copy(other.begin(), other.end(), begin());
|
||||
}
|
||||
|
||||
ArrayVector(ArrayVector&& other) noexcept(std::is_nothrow_move_constructible_v<T>) :
|
||||
m_size{other.m_size}
|
||||
{
|
||||
std::uninitialized_move(other.begin(), other.end(), begin());
|
||||
other.clear();
|
||||
}
|
||||
|
||||
ArrayVector(size_type count, const T& value) noexcept(std::is_nothrow_copy_constructible_v<T>) :
|
||||
m_size{count}
|
||||
{
|
||||
assert(count <= N);
|
||||
std::uninitialized_fill_n(begin(), count, value);
|
||||
}
|
||||
|
||||
explicit ArrayVector(size_type count) noexcept(std::is_nothrow_default_constructible_v<T>) :
|
||||
m_size{count}
|
||||
{
|
||||
assert(count <= N);
|
||||
std::uninitialized_value_construct_n(begin(), count);
|
||||
}
|
||||
|
||||
template<typename It, std::enable_if_t<detail::is_input_iterator_v<It>, int> = 0>
|
||||
ArrayVector(It first, It last)
|
||||
{
|
||||
// Can't check the size first as the iterator may not be multipass
|
||||
const auto end = std::uninitialized_copy(first, last, begin());
|
||||
m_size = end - begin();
|
||||
assert(m_size <= N);
|
||||
}
|
||||
|
||||
ArrayVector(std::initializer_list<T> il) noexcept(std::is_nothrow_copy_constructible_v<T>) :
|
||||
m_size{il.size()}
|
||||
{
|
||||
assert(il.size() <= N);
|
||||
std::uninitialized_copy(il.begin(), il.end(), begin());
|
||||
}
|
||||
|
||||
~ArrayVector() { std::destroy(begin(), end()); }
|
||||
|
||||
ArrayVector& operator=(const ArrayVector& other)
|
||||
noexcept(std::is_nothrow_copy_assignable_v<T> && std::is_nothrow_copy_constructible_v<T>)
|
||||
{
|
||||
if (this != &other) {
|
||||
const auto toAssign = std::min(other.size(), size());
|
||||
const auto assignedFromEnd = other.begin() + toAssign;
|
||||
const auto assignedToEnd = std::copy(other.begin(), other.begin() + toAssign, begin());
|
||||
std::destroy(assignedToEnd, end());
|
||||
std::uninitialized_copy(assignedFromEnd, other.end(), end());
|
||||
m_size = other.size();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArrayVector& operator=(ArrayVector&& other)
|
||||
noexcept(std::is_nothrow_move_assignable_v<T> && std::is_nothrow_move_constructible_v<T>)
|
||||
{
|
||||
if (this != &other) {
|
||||
const auto toAssign = std::min(other.size(), size());
|
||||
const auto assignedFromEnd = other.begin() + toAssign;
|
||||
const auto assignedToEnd = std::move(other.begin(), other.begin() + toAssign, begin());
|
||||
std::destroy(assignedToEnd, end());
|
||||
std::uninitialized_move(assignedFromEnd, other.end(), end());
|
||||
m_size = other.size();
|
||||
other.clear();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArrayVector& operator=(std::initializer_list<T> il)
|
||||
noexcept(std::is_nothrow_copy_assignable_v<T> && std::is_nothrow_copy_constructible_v<T>)
|
||||
{
|
||||
assert(il.size() <= N);
|
||||
const auto toAssign = std::min(il.size(), size());
|
||||
const auto assignedFromEnd = il.begin() + toAssign;
|
||||
const auto assignedToEnd = std::copy(il.begin(), assignedFromEnd, begin());
|
||||
std::destroy(assignedToEnd, end());
|
||||
std::uninitialized_copy(assignedFromEnd, il.end(), end());
|
||||
m_size = il.size();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void assign(size_type count, const T& value)
|
||||
noexcept(std::is_nothrow_copy_assignable_v<T> && std::is_nothrow_copy_constructible_v<T>)
|
||||
{
|
||||
assert(count <= N);
|
||||
const auto temp = value;
|
||||
const auto toAssign = std::min(count, size());
|
||||
const auto toConstruct = count - toAssign;
|
||||
const auto assignedToEnd = std::fill_n(begin(), toAssign, temp);
|
||||
std::destroy(assignedToEnd, end());
|
||||
std::uninitialized_fill_n(assignedToEnd, toConstruct, temp);
|
||||
m_size = count;
|
||||
}
|
||||
|
||||
template<typename It, std::enable_if_t<detail::is_input_iterator_v<It>, int> = 0>
|
||||
void assign(It first, It last)
|
||||
{
|
||||
// Can't check the size first as the iterator may not be multipass
|
||||
auto pos = begin();
|
||||
for (; first != last && pos != end(); ++pos, ++first) {
|
||||
*pos = *first;
|
||||
}
|
||||
std::destroy(pos, end());
|
||||
pos = std::uninitialized_copy(first, last, pos);
|
||||
m_size = pos - begin();
|
||||
assert(m_size <= N);
|
||||
}
|
||||
|
||||
reference at(size_type index)
|
||||
{
|
||||
if (index >= m_size) { throw std::out_of_range{"index out of range"}; }
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
const_reference at(size_type index) const
|
||||
{
|
||||
if (index >= m_size) { throw std::out_of_range{"index out of range"}; }
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
reference operator[](size_type index) noexcept
|
||||
{
|
||||
assert(index < m_size);
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
const_reference operator[](size_type index) const noexcept
|
||||
{
|
||||
assert(index < m_size);
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
reference front() noexcept { return operator[](0); }
|
||||
const_reference front() const noexcept { return operator[](0); }
|
||||
|
||||
reference back() noexcept { return operator[](m_size - 1); }
|
||||
const_reference back() const noexcept { return operator[](m_size - 1); }
|
||||
|
||||
pointer data() noexcept { return *std::launder(reinterpret_cast<T(*)[N]>(m_data)); }
|
||||
const_pointer data() const noexcept { return *std::launder(reinterpret_cast<const T(*)[N]>(m_data)); }
|
||||
|
||||
iterator begin() noexcept { return data(); }
|
||||
const_iterator begin() const noexcept { return data(); }
|
||||
const_iterator cbegin() const noexcept { return data(); }
|
||||
|
||||
iterator end() noexcept { return data() + m_size; }
|
||||
const_iterator end() const noexcept { return data() + m_size; }
|
||||
const_iterator cend() const noexcept { return data() + m_size; }
|
||||
|
||||
reverse_iterator rbegin() noexcept { return std::reverse_iterator{end()}; }
|
||||
const_reverse_iterator rbegin() const noexcept { return std::reverse_iterator{end()}; }
|
||||
const_reverse_iterator crbegin() const noexcept { return std::reverse_iterator{cend()}; }
|
||||
|
||||
reverse_iterator rend() noexcept { return std::reverse_iterator{begin()}; }
|
||||
const_reverse_iterator rend() const noexcept { return std::reverse_iterator{begin()}; }
|
||||
const_reverse_iterator crend() const noexcept { return std::reverse_iterator{cbegin()}; }
|
||||
|
||||
bool empty() const noexcept { return m_size == 0; }
|
||||
bool full() const noexcept { return m_size == N; }
|
||||
size_type size() const noexcept { return m_size; }
|
||||
size_type max_size() const noexcept { return N; }
|
||||
size_type capacity() const noexcept { return N; }
|
||||
|
||||
void clear() noexcept
|
||||
{
|
||||
std::destroy(begin(), end());
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
iterator insert(const_iterator pos, const T& value) { return emplace(pos, value); }
|
||||
iterator insert(const_iterator pos, T&& value) { return emplace(pos, std::move(value)); }
|
||||
|
||||
iterator insert(const_iterator pos, size_type count, const T& value)
|
||||
{
|
||||
assert(m_size + count <= N);
|
||||
assert(cbegin() <= pos && pos <= cend());
|
||||
const auto mutPos = begin() + (pos - cbegin());
|
||||
const auto newEnd = std::uninitialized_fill_n(end(), count, value);
|
||||
std::rotate(mutPos, end(), newEnd);
|
||||
m_size += count;
|
||||
return mutPos;
|
||||
}
|
||||
|
||||
template<typename It, std::enable_if_t<detail::is_input_iterator_v<It>, int> = 0>
|
||||
iterator insert(const_iterator pos, It first, It last)
|
||||
{
|
||||
// Can't check the size first as the iterator may not be multipass
|
||||
assert(cbegin() <= pos && pos <= cend());
|
||||
const auto mutPos = begin() + (pos - cbegin());
|
||||
const auto newEnd = std::uninitialized_copy(first, last, end());
|
||||
std::rotate(mutPos, end(), newEnd);
|
||||
m_size = newEnd - begin();
|
||||
assert(m_size <= N);
|
||||
return mutPos;
|
||||
}
|
||||
|
||||
iterator insert(const_iterator pos, std::initializer_list<T> il) { return insert(pos, il.begin(), il.end()); }
|
||||
|
||||
template<typename... Args>
|
||||
iterator emplace(const_iterator pos, Args&&... args)
|
||||
{
|
||||
assert(cbegin() <= pos && pos <= cend());
|
||||
const auto mutPos = begin() + (pos - cbegin());
|
||||
emplace_back(std::forward<Args>(args)...);
|
||||
std::rotate(mutPos, end() - 1, end());
|
||||
return mutPos;
|
||||
}
|
||||
|
||||
iterator erase(const_iterator pos) { return erase(pos, pos + 1); }
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
assert(cbegin() <= first && first <= last && last <= cend());
|
||||
const auto mutFirst = begin() + (first - cbegin());
|
||||
const auto mutLast = begin() + (last - cbegin());
|
||||
const auto newEnd = std::move(mutLast, end(), mutFirst);
|
||||
std::destroy(newEnd, end());
|
||||
m_size = newEnd - begin();
|
||||
return mutFirst;
|
||||
}
|
||||
|
||||
void push_back(const T& value) { emplace_back(value); }
|
||||
void push_back(T&& value) { emplace_back(std::move(value)); }
|
||||
|
||||
template<typename... Args>
|
||||
reference emplace_back(Args&&... args)
|
||||
{
|
||||
assert(!full());
|
||||
// TODO C++20: Use std::construct_at
|
||||
const auto result = new(static_cast<void*>(end())) T(std::forward<Args>(args)...);
|
||||
++m_size;
|
||||
return *result;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
assert(!empty());
|
||||
--m_size;
|
||||
std::destroy_at(end());
|
||||
}
|
||||
|
||||
void resize(size_type size)
|
||||
{
|
||||
if (size > N) { throw std::length_error{"size exceeds maximum size"}; }
|
||||
if (size < m_size) {
|
||||
std::destroy(begin() + size, end());
|
||||
} else {
|
||||
std::uninitialized_value_construct(end(), begin() + size);
|
||||
}
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void resize(size_type size, const value_type& value)
|
||||
{
|
||||
if (size > N) { throw std::length_error{"size exceeds maximum size"}; }
|
||||
if (size < m_size) {
|
||||
std::destroy(begin() + size, end());
|
||||
} else {
|
||||
std::uninitialized_fill(end(), begin() + size, value);
|
||||
}
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void swap(ArrayVector& other)
|
||||
noexcept(std::is_nothrow_swappable_v<T> && std::is_nothrow_move_constructible_v<T>)
|
||||
{
|
||||
using std::swap;
|
||||
swap(*this, other);
|
||||
}
|
||||
|
||||
friend void swap(ArrayVector& a, ArrayVector& b)
|
||||
noexcept(std::is_nothrow_swappable_v<T> && std::is_nothrow_move_constructible_v<T>)
|
||||
{
|
||||
const auto toSwap = std::min(a.size(), b.size());
|
||||
const auto aSwapEnd = a.begin() + toSwap;
|
||||
const auto bSwapEnd = b.begin() + toSwap;
|
||||
std::swap_ranges(a.begin(), aSwapEnd, b.begin());
|
||||
std::uninitialized_move(aSwapEnd, a.end(), bSwapEnd);
|
||||
std::uninitialized_move(bSwapEnd, b.end(), aSwapEnd);
|
||||
std::destroy(aSwapEnd, a.end());
|
||||
std::destroy(bSwapEnd, b.end());
|
||||
std::swap(a.m_size, b.m_size);
|
||||
}
|
||||
|
||||
// TODO C++20: Replace with operator<=>
|
||||
friend bool operator<(const ArrayVector& l, const ArrayVector& r)
|
||||
{
|
||||
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
friend bool operator<=(const ArrayVector& l, const ArrayVector& r) { return !(r < l); }
|
||||
friend bool operator>(const ArrayVector& l, const ArrayVector& r) { return r < l; }
|
||||
friend bool operator>=(const ArrayVector& l, const ArrayVector& r) { return !(l < r); }
|
||||
|
||||
friend bool operator==(const ArrayVector& l, const ArrayVector& r)
|
||||
{
|
||||
return std::equal(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
// TODO C++20: Remove
|
||||
friend bool operator!=(const ArrayVector& l, const ArrayVector& r) { return !(l == r); }
|
||||
|
||||
private:
|
||||
alignas(T) std::byte m_data[std::max(N * sizeof(T), std::size_t{1})]; // Intentionally a raw array
|
||||
size_type m_size = 0;
|
||||
};
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_ARRAY_VECTOR_H
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_ALSA_H
|
||||
#define AUDIO_ALSA_H
|
||||
#ifndef LMMS_AUDIO_ALSA_H
|
||||
#define LMMS_AUDIO_ALSA_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
@@ -108,4 +108,4 @@ private:
|
||||
|
||||
#endif // LMMS_HAVE_ALSA
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_ALSA_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_ALSA_SETUP_WIDGET_H
|
||||
#define AUDIO_ALSA_SETUP_WIDGET_H
|
||||
#ifndef LMMS_GUI_AUDIO_ALSA_SETUP_WIDGET_H
|
||||
#define LMMS_GUI_AUDIO_ALSA_SETUP_WIDGET_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
@@ -66,4 +66,4 @@ private:
|
||||
|
||||
#endif // LMMS_HAVE_ALSA
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_AUDIO_ALSA_SETUP_WIDGET_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_DEVICE_H
|
||||
#define AUDIO_DEVICE_H
|
||||
#ifndef LMMS_AUDIO_DEVICE_H
|
||||
#define LMMS_AUDIO_DEVICE_H
|
||||
|
||||
#include <QMutex>
|
||||
#include <samplerate.h>
|
||||
@@ -96,11 +96,7 @@ public:
|
||||
protected:
|
||||
// subclasses can re-implement this for being used in conjunction with
|
||||
// processNextBuffer()
|
||||
virtual void writeBuffer( const surroundSampleFrame * /* _buf*/,
|
||||
const fpp_t /*_frames*/,
|
||||
const float /*_master_gain*/ )
|
||||
{
|
||||
}
|
||||
virtual void writeBuffer(const surroundSampleFrame* /* _buf*/, const fpp_t /*_frames*/) {}
|
||||
|
||||
// called by according driver for fetching new sound-data
|
||||
fpp_t getNextBuffer( surroundSampleFrame * _ab );
|
||||
@@ -109,7 +105,6 @@ protected:
|
||||
// returns num of bytes in outbuf
|
||||
int convertToS16( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain,
|
||||
int_sample_t * _output_buffer,
|
||||
const bool _convert_endian = false );
|
||||
|
||||
@@ -160,4 +155,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_DEVICE_H
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* AudioDeviceSetupWidget.h - Base class for audio device setup widgets
|
||||
*
|
||||
* Copyright (c) 2004-2015 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2023- Michael Gregorius
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
@@ -22,15 +23,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_DEVICE_SETUP_WIDGET_H
|
||||
#define AUDIO_DEVICE_SETUP_WIDGET_H
|
||||
#ifndef LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H
|
||||
#define LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H
|
||||
|
||||
#include "TabWidget.h"
|
||||
#include <QGroupBox>
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class AudioDeviceSetupWidget : public TabWidget
|
||||
class AudioDeviceSetupWidget : public QGroupBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -45,4 +46,4 @@ public:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_DUMMY_H
|
||||
#define AUDIO_DUMMY_H
|
||||
#ifndef LMMS_AUDIO_DUMMY_H
|
||||
#define LMMS_AUDIO_DUMMY_H
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
@@ -116,4 +116,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_DUMMY_H
|
||||
|
||||
@@ -22,20 +22,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_ENGINE_H
|
||||
#define AUDIO_ENGINE_H
|
||||
#ifndef LMMS_AUDIO_ENGINE_H
|
||||
#define LMMS_AUDIO_ENGINE_H
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
|
||||
#include <QRecursiveMutex>
|
||||
#ifdef __MINGW32__
|
||||
#include <mingw.mutex.h>
|
||||
#else
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
#include <QThread>
|
||||
#include <QVector>
|
||||
#include <QWaitCondition>
|
||||
#include <samplerate.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "LocklessList.h"
|
||||
@@ -109,27 +108,27 @@ public:
|
||||
|
||||
struct qualitySettings
|
||||
{
|
||||
enum Mode
|
||||
enum class Mode
|
||||
{
|
||||
Mode_Draft,
|
||||
Mode_HighQuality,
|
||||
Mode_FinalMix
|
||||
Draft,
|
||||
HighQuality,
|
||||
FinalMix
|
||||
} ;
|
||||
|
||||
enum Interpolation
|
||||
enum class Interpolation
|
||||
{
|
||||
Interpolation_Linear,
|
||||
Interpolation_SincFastest,
|
||||
Interpolation_SincMedium,
|
||||
Interpolation_SincBest
|
||||
Linear,
|
||||
SincFastest,
|
||||
SincMedium,
|
||||
SincBest
|
||||
} ;
|
||||
|
||||
enum Oversampling
|
||||
enum class Oversampling
|
||||
{
|
||||
Oversampling_None,
|
||||
Oversampling_2x,
|
||||
Oversampling_4x,
|
||||
Oversampling_8x
|
||||
None,
|
||||
X2,
|
||||
X4,
|
||||
X8
|
||||
} ;
|
||||
|
||||
Interpolation interpolation;
|
||||
@@ -139,18 +138,18 @@ public:
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case Mode_Draft:
|
||||
interpolation = Interpolation_Linear;
|
||||
oversampling = Oversampling_None;
|
||||
case Mode::Draft:
|
||||
interpolation = Interpolation::Linear;
|
||||
oversampling = Oversampling::None;
|
||||
break;
|
||||
case Mode_HighQuality:
|
||||
case Mode::HighQuality:
|
||||
interpolation =
|
||||
Interpolation_SincFastest;
|
||||
oversampling = Oversampling_2x;
|
||||
Interpolation::SincFastest;
|
||||
oversampling = Oversampling::X2;
|
||||
break;
|
||||
case Mode_FinalMix:
|
||||
interpolation = Interpolation_SincBest;
|
||||
oversampling = Oversampling_8x;
|
||||
case Mode::FinalMix:
|
||||
interpolation = Interpolation::SincBest;
|
||||
oversampling = Oversampling::X8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -165,10 +164,10 @@ public:
|
||||
{
|
||||
switch( oversampling )
|
||||
{
|
||||
case Oversampling_None: return 1;
|
||||
case Oversampling_2x: return 2;
|
||||
case Oversampling_4x: return 4;
|
||||
case Oversampling_8x: return 8;
|
||||
case Oversampling::None: return 1;
|
||||
case Oversampling::X2: return 2;
|
||||
case Oversampling::X4: return 4;
|
||||
case Oversampling::X8: return 8;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -177,13 +176,13 @@ public:
|
||||
{
|
||||
switch( interpolation )
|
||||
{
|
||||
case Interpolation_Linear:
|
||||
case Interpolation::Linear:
|
||||
return SRC_ZERO_ORDER_HOLD;
|
||||
case Interpolation_SincFastest:
|
||||
case Interpolation::SincFastest:
|
||||
return SRC_SINC_FASTEST;
|
||||
case Interpolation_SincMedium:
|
||||
case Interpolation::SincMedium:
|
||||
return SRC_SINC_MEDIUM_QUALITY;
|
||||
case Interpolation_SincBest:
|
||||
case Interpolation::SincBest:
|
||||
return SRC_SINC_BEST_QUALITY;
|
||||
}
|
||||
return SRC_LINEAR;
|
||||
@@ -197,6 +196,7 @@ public:
|
||||
|
||||
// audio-device-stuff
|
||||
|
||||
bool renderOnly() const { return m_renderOnly; }
|
||||
// Returns the current audio device's name. This is not necessarily
|
||||
// the user's preferred audio device, in case you were thinking that.
|
||||
inline const QString & audioDevName() const
|
||||
@@ -255,7 +255,7 @@ public:
|
||||
return m_playHandles;
|
||||
}
|
||||
|
||||
void removePlayHandlesOfTypes(Track * track, const quint8 types);
|
||||
void removePlayHandlesOfTypes(Track * track, PlayHandle::Types types);
|
||||
|
||||
|
||||
// methods providing information for other classes
|
||||
@@ -275,6 +275,11 @@ public:
|
||||
return m_profiler.cpuLoad();
|
||||
}
|
||||
|
||||
int detailLoad(const AudioEngineProfiler::DetailType type) const
|
||||
{
|
||||
return m_profiler.detailLoad(type);
|
||||
}
|
||||
|
||||
const qualitySettings & currentQualitySettings() const
|
||||
{
|
||||
return m_qualitySettings;
|
||||
@@ -401,6 +406,10 @@ private:
|
||||
AudioDevice * tryAudioDevices();
|
||||
MidiClient * tryMidiClients();
|
||||
|
||||
void renderStageNoteSetup();
|
||||
void renderStageInstruments();
|
||||
void renderStageEffects();
|
||||
void renderStageMix();
|
||||
|
||||
const surroundSampleFrame * renderNextBuffer();
|
||||
|
||||
@@ -410,13 +419,9 @@ private:
|
||||
|
||||
void clearInternal();
|
||||
|
||||
//! Called by the audio thread to give control to other threads,
|
||||
//! such that they can do changes in the model (like e.g. removing effects)
|
||||
void runChangesInModel();
|
||||
|
||||
bool m_renderOnly;
|
||||
|
||||
QVector<AudioPort *> m_audioPorts;
|
||||
std::vector<AudioPort *> m_audioPorts;
|
||||
|
||||
fpp_t m_framesPerPeriod;
|
||||
|
||||
@@ -430,7 +435,7 @@ private:
|
||||
surroundSampleFrame * m_outputBufferWrite;
|
||||
|
||||
// worker thread stuff
|
||||
QVector<AudioEngineWorkerThread *> m_workers;
|
||||
std::vector<AudioEngineWorkerThread *> m_workers;
|
||||
int m_numWorkers;
|
||||
|
||||
// playhandle stuff
|
||||
@@ -443,8 +448,6 @@ private:
|
||||
struct qualitySettings m_qualitySettings;
|
||||
float m_masterGain;
|
||||
|
||||
bool m_isProcessing;
|
||||
|
||||
// audio device stuff
|
||||
void doSetAudioDevice( AudioDevice *_dev );
|
||||
AudioDevice * m_audioDev;
|
||||
@@ -466,19 +469,7 @@ private:
|
||||
|
||||
bool m_clearSignal;
|
||||
|
||||
bool m_changesSignal;
|
||||
unsigned int m_changes;
|
||||
QMutex m_changesMutex;
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
|
||||
QRecursiveMutex m_doChangesMutex;
|
||||
#else
|
||||
QMutex m_doChangesMutex;
|
||||
#endif
|
||||
QMutex m_waitChangesMutex;
|
||||
QWaitCondition m_changesAudioEngineCondition;
|
||||
QWaitCondition m_changesRequestCondition;
|
||||
|
||||
bool m_waitingForWrite;
|
||||
std::mutex m_changeMutex;
|
||||
|
||||
friend class Engine;
|
||||
friend class AudioEngineWorkerThread;
|
||||
@@ -487,4 +478,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_ENGINE_H
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_ENGINE_PROFILER_H
|
||||
#define AUDIO_ENGINE_PROFILER_H
|
||||
#ifndef LMMS_AUDIO_ENGINE_PROFILER_H
|
||||
#define LMMS_AUDIO_ENGINE_PROFILER_H
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <QFile>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
@@ -53,13 +55,57 @@ public:
|
||||
|
||||
void setOutputFile( const QString& outputFile );
|
||||
|
||||
enum class DetailType {
|
||||
NoteSetup,
|
||||
Instruments,
|
||||
Effects,
|
||||
Mixing,
|
||||
Count
|
||||
};
|
||||
|
||||
constexpr static auto DetailCount = static_cast<std::size_t>(DetailType::Count);
|
||||
|
||||
int detailLoad(const DetailType type) const
|
||||
{
|
||||
return m_detailLoad[static_cast<std::size_t>(type)].load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
class Probe
|
||||
{
|
||||
public:
|
||||
Probe(AudioEngineProfiler& profiler, AudioEngineProfiler::DetailType type)
|
||||
: m_profiler(profiler)
|
||||
, m_type(type)
|
||||
{
|
||||
profiler.startDetail(type);
|
||||
}
|
||||
~Probe() { m_profiler.finishDetail(m_type); }
|
||||
Probe& operator=(const Probe&) = delete;
|
||||
Probe(const Probe&) = delete;
|
||||
Probe(Probe&&) = delete;
|
||||
|
||||
private:
|
||||
AudioEngineProfiler &m_profiler;
|
||||
const AudioEngineProfiler::DetailType m_type;
|
||||
};
|
||||
|
||||
private:
|
||||
void startDetail(const DetailType type) { m_detailTimer[static_cast<std::size_t>(type)].reset(); }
|
||||
void finishDetail(const DetailType type)
|
||||
{
|
||||
m_detailTime[static_cast<std::size_t>(type)] = m_detailTimer[static_cast<std::size_t>(type)].elapsed();
|
||||
}
|
||||
|
||||
MicroTimer m_periodTimer;
|
||||
int m_cpuLoad;
|
||||
std::atomic<float> m_cpuLoad;
|
||||
QFile m_outputFile;
|
||||
|
||||
// Use arrays to avoid dynamic allocations in realtime code
|
||||
std::array<MicroTimer, DetailCount> m_detailTimer;
|
||||
std::array<int, DetailCount> m_detailTime{0};
|
||||
std::array<std::atomic<float>, DetailCount> m_detailLoad{0};
|
||||
};
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_ENGINE_PROFILER_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_ENGINE_WORKER_THREAD_H
|
||||
#define AUDIO_ENGINE_WORKER_THREAD_H
|
||||
#ifndef LMMS_AUDIO_ENGINE_WORKER_THREAD_H
|
||||
#define LMMS_AUDIO_ENGINE_WORKER_THREAD_H
|
||||
|
||||
#include <QThread>
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
class JobQueue
|
||||
{
|
||||
public:
|
||||
enum OperationMode
|
||||
enum class OperationMode
|
||||
{
|
||||
Static, // no jobs added while processing queue
|
||||
Dynamic // jobs can be added while processing queue
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
m_items(),
|
||||
m_writeIndex( 0 ),
|
||||
m_itemsDone( 0 ),
|
||||
m_opMode( Static )
|
||||
m_opMode( OperationMode::Static )
|
||||
{
|
||||
std::fill(m_items, m_items + JOB_QUEUE_SIZE, nullptr);
|
||||
}
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
virtual void quit();
|
||||
|
||||
static void resetJobQueue( JobQueue::OperationMode _opMode =
|
||||
JobQueue::Static )
|
||||
JobQueue::OperationMode::Static )
|
||||
{
|
||||
globalJobQueue.reset( _opMode );
|
||||
}
|
||||
@@ -97,12 +97,12 @@ public:
|
||||
// to ThreadableJob objects
|
||||
template<typename T>
|
||||
static void fillJobQueue( const T & _vec,
|
||||
JobQueue::OperationMode _opMode = JobQueue::Static )
|
||||
JobQueue::OperationMode _opMode = JobQueue::OperationMode::Static )
|
||||
{
|
||||
resetJobQueue( _opMode );
|
||||
for( typename T::ConstIterator it = _vec.begin(); it != _vec.end(); ++it )
|
||||
for (const auto& job : _vec)
|
||||
{
|
||||
addJob( *it );
|
||||
addJob(job);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,4 +121,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_ENGINE_WORKER_THREAD_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_FILE_DEVICE_H
|
||||
#define AUDIO_FILE_DEVICE_H
|
||||
#ifndef LMMS_AUDIO_FILE_DEVICE_H
|
||||
#define LMMS_AUDIO_FILE_DEVICE_H
|
||||
|
||||
#include <QFile>
|
||||
|
||||
@@ -73,4 +73,4 @@ using AudioFileDeviceInstantiaton
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_FILE_DEVICE_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_FILE_FLAC_H
|
||||
#define AUDIO_FILE_FLAC_H
|
||||
#ifndef LMMS_AUDIO_FILE_FLAC_H
|
||||
#define LMMS_AUDIO_FILE_FLAC_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioFileFlac: public AudioFileDevice
|
||||
class AudioFileFlac : public AudioFileDevice
|
||||
{
|
||||
public:
|
||||
AudioFileFlac(OutputSettings const& outputSettings,
|
||||
@@ -65,9 +65,7 @@ private:
|
||||
SF_INFO m_sfinfo;
|
||||
SNDFILE* m_sf;
|
||||
|
||||
void writeBuffer(surroundSampleFrame const* _ab,
|
||||
fpp_t const frames,
|
||||
float master_gain) override;
|
||||
void writeBuffer(surroundSampleFrame const* _ab, fpp_t const frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
@@ -77,4 +75,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif //AUDIO_FILE_FLAC_H
|
||||
#endif // LMMS_AUDIO_FILE_FLAC_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_FILE_MP3_H
|
||||
#define AUDIO_FILE_MP3_H
|
||||
#ifndef LMMS_AUDIO_FILE_MP3_H
|
||||
#define LMMS_AUDIO_FILE_MP3_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
@@ -58,9 +58,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void writeBuffer( const surroundSampleFrame * /* _buf*/,
|
||||
const fpp_t /*_frames*/,
|
||||
const float /*_master_gain*/ ) override;
|
||||
void writeBuffer(const surroundSampleFrame* /* _buf*/, const fpp_t /*_frames*/) override;
|
||||
|
||||
private:
|
||||
void flushRemainingBuffers();
|
||||
@@ -75,4 +73,4 @@ private:
|
||||
|
||||
#endif // LMMS_HAVE_MP3LAME
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_FILE_MP3_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_FILE_OGG_H
|
||||
#define AUDIO_FILE_OGG_H
|
||||
#ifndef LMMS_AUDIO_FILE_OGG_H
|
||||
#define LMMS_AUDIO_FILE_OGG_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
@@ -58,9 +58,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain ) override;
|
||||
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
@@ -113,4 +111,4 @@ private:
|
||||
|
||||
#endif // LMMS_HAVE_OGGVORBIS
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_FILE_OGG_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_FILE_WAVE_H
|
||||
#define AUDIO_FILE_WAVE_H
|
||||
#ifndef LMMS_AUDIO_FILE_WAVE_H
|
||||
#define LMMS_AUDIO_FILE_WAVE_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
#include "AudioFileDevice.h"
|
||||
@@ -56,9 +56,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
float _master_gain ) override;
|
||||
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
@@ -71,4 +69,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_FILE_WAVE_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_JACK_H
|
||||
#define AUDIO_JACK_H
|
||||
#ifndef LMMS_AUDIO_JACK_H
|
||||
#define LMMS_AUDIO_JACK_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <QVector>
|
||||
#include <vector>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
@@ -57,42 +57,37 @@ class AudioJack : public QObject, public AudioDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioJack( bool & _success_ful, AudioEngine* audioEngine );
|
||||
AudioJack(bool& successful, AudioEngine* audioEngine);
|
||||
~AudioJack() override;
|
||||
|
||||
// this is to allow the jack midi connection to use the same jack client connection
|
||||
// the jack callback is handled here, we call the midi client so that it can read
|
||||
// it's midi data during the callback
|
||||
AudioJack * addMidiClient(MidiJack *midiClient);
|
||||
AudioJack* addMidiClient(MidiJack* midiClient);
|
||||
void removeMidiClient() { m_midiClient = nullptr; }
|
||||
jack_client_t * jackClient() {return m_client;};
|
||||
jack_client_t* jackClient() { return m_client; };
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget",
|
||||
"JACK (JACK Audio Connection Kit)" );
|
||||
return QT_TRANSLATE_NOOP("AudioDeviceSetupWidget", "JACK (JACK Audio Connection Kit)");
|
||||
}
|
||||
|
||||
|
||||
class setupWidget : public gui::AudioDeviceSetupWidget
|
||||
class setupWidget : public gui::AudioDeviceSetupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
setupWidget(QWidget* parent);
|
||||
~setupWidget() override;
|
||||
|
||||
void saveSettings() override;
|
||||
|
||||
private:
|
||||
QLineEdit * m_clientName;
|
||||
gui::LcdSpinBox * m_channels;
|
||||
|
||||
} ;
|
||||
|
||||
QLineEdit* m_clientName;
|
||||
gui::LcdSpinBox* m_channels;
|
||||
};
|
||||
|
||||
private slots:
|
||||
void restartAfterZombified();
|
||||
|
||||
|
||||
private:
|
||||
bool initJackClient();
|
||||
|
||||
@@ -100,48 +95,44 @@ private:
|
||||
void stopProcessing() override;
|
||||
void applyQualitySettings() override;
|
||||
|
||||
void registerPort( AudioPort * _port ) override;
|
||||
void unregisterPort( AudioPort * _port ) override;
|
||||
void renamePort( AudioPort * _port ) override;
|
||||
void registerPort(AudioPort* port) override;
|
||||
void unregisterPort(AudioPort* port) override;
|
||||
void renamePort(AudioPort* port) override;
|
||||
|
||||
int processCallback( jack_nframes_t _nframes, void * _udata );
|
||||
int processCallback(jack_nframes_t nframes);
|
||||
|
||||
static int staticProcessCallback( jack_nframes_t _nframes,
|
||||
void * _udata );
|
||||
static void shutdownCallback( void * _udata );
|
||||
static int staticProcessCallback(jack_nframes_t nframes, void* udata);
|
||||
static void shutdownCallback(void* _udata);
|
||||
|
||||
|
||||
jack_client_t * m_client;
|
||||
jack_client_t* m_client;
|
||||
|
||||
bool m_active;
|
||||
std::atomic<bool> m_stopped;
|
||||
|
||||
std::atomic<MidiJack *> m_midiClient;
|
||||
QVector<jack_port_t *> m_outputPorts;
|
||||
jack_default_audio_sample_t * * m_tempOutBufs;
|
||||
surroundSampleFrame * m_outBuf;
|
||||
std::atomic<MidiJack*> m_midiClient;
|
||||
std::vector<jack_port_t*> m_outputPorts;
|
||||
jack_default_audio_sample_t** m_tempOutBufs;
|
||||
surroundSampleFrame* m_outBuf;
|
||||
|
||||
f_cnt_t m_framesDoneInCurBuf;
|
||||
f_cnt_t m_framesToDoInCurBuf;
|
||||
|
||||
|
||||
#ifdef AUDIO_PORT_SUPPORT
|
||||
struct StereoPort
|
||||
{
|
||||
jack_port_t * ports[2];
|
||||
} ;
|
||||
jack_port_t* ports[2];
|
||||
};
|
||||
|
||||
using JackPortMap = QMap<AudioPort *, StereoPort>;
|
||||
using JackPortMap = QMap<AudioPort*, StereoPort>;
|
||||
JackPortMap m_portMap;
|
||||
#endif
|
||||
|
||||
signals:
|
||||
void zombified();
|
||||
|
||||
} ;
|
||||
};
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_HAVE_JACK
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_JACK_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_OSS_H
|
||||
#define AUDIO_OSS_H
|
||||
#ifndef LMMS_AUDIO_OSS_H
|
||||
#define LMMS_AUDIO_OSS_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
@@ -92,4 +92,4 @@ private:
|
||||
|
||||
#endif // LMMS_HAVE_OSS
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_OSS_H
|
||||
|
||||
@@ -22,14 +22,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_PORT_H
|
||||
#define AUDIO_PORT_H
|
||||
#ifndef LMMS_AUDIO_PORT_H
|
||||
#define LMMS_AUDIO_PORT_H
|
||||
|
||||
#include <memory>
|
||||
#include <QString>
|
||||
#include <QMutex>
|
||||
|
||||
#include "MemoryManager.h"
|
||||
#include "PlayHandle.h"
|
||||
|
||||
namespace lmms
|
||||
@@ -41,7 +40,6 @@ class BoolModel;
|
||||
|
||||
class AudioPort : public ThreadableJob
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
AudioPort( const QString & _name, bool _has_effect_chain = true,
|
||||
FloatModel * volumeModel = nullptr, FloatModel * panningModel = nullptr,
|
||||
@@ -138,4 +136,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_PORT_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_PORTAUDIO_H
|
||||
#define AUDIO_PORTAUDIO_H
|
||||
#ifndef LMMS_AUDIO_PORTAUDIO_H
|
||||
#define LMMS_AUDIO_PORTAUDIO_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
@@ -163,4 +163,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_PORTAUDIO_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_PULSEAUDIO_H
|
||||
#define AUDIO_PULSEAUDIO_H
|
||||
#ifndef LMMS_AUDIO_PULSEAUDIO_H
|
||||
#define LMMS_AUDIO_PULSEAUDIO_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
@@ -104,4 +104,4 @@ private:
|
||||
|
||||
#endif // LMMS_HAVE_PULSEAUDIO
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_PULSEAUDIO_H
|
||||
|
||||
64
include/AudioResampler.h
Normal file
64
include/AudioResampler.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* AudioResampler.h - wrapper around libsamplerate
|
||||
*
|
||||
* Copyright (c) 2023 saker <sakertooth@gmail.com>
|
||||
*
|
||||
* 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 LMMS_AUDIO_RESAMPLER_H
|
||||
#define LMMS_AUDIO_RESAMPLER_H
|
||||
|
||||
#include <samplerate.h>
|
||||
|
||||
#include "lmms_export.h"
|
||||
|
||||
namespace lmms {
|
||||
|
||||
class LMMS_EXPORT AudioResampler
|
||||
{
|
||||
public:
|
||||
struct ProcessResult
|
||||
{
|
||||
int error;
|
||||
long inputFramesUsed;
|
||||
long outputFramesGenerated;
|
||||
};
|
||||
|
||||
AudioResampler(int interpolationMode, int channels);
|
||||
AudioResampler(const AudioResampler&) = delete;
|
||||
AudioResampler(AudioResampler&&) = delete;
|
||||
~AudioResampler();
|
||||
|
||||
AudioResampler& operator=(const AudioResampler&) = delete;
|
||||
AudioResampler& operator=(AudioResampler&&) = delete;
|
||||
|
||||
auto resample(const float* in, long inputFrames, float* out, long outputFrames, double ratio) -> ProcessResult;
|
||||
auto interpolationMode() const -> int { return m_interpolationMode; }
|
||||
auto channels() const -> int { return m_channels; }
|
||||
|
||||
private:
|
||||
int m_interpolationMode = -1;
|
||||
int m_channels = 0;
|
||||
int m_error = 0;
|
||||
SRC_STATE* m_state = nullptr;
|
||||
};
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_AUDIO_RESAMPLER_H
|
||||
@@ -23,11 +23,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_SAMPLE_RECORDER_H
|
||||
#define AUDIO_SAMPLE_RECORDER_H
|
||||
#ifndef LMMS_AUDIO_SAMPLE_RECORDER_H
|
||||
#define LMMS_AUDIO_SAMPLE_RECORDER_H
|
||||
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
#include <memory>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
|
||||
@@ -44,13 +45,10 @@ public:
|
||||
~AudioSampleRecorder() override;
|
||||
|
||||
f_cnt_t framesRecorded() const;
|
||||
void createSampleBuffer( SampleBuffer** sampleBuffer );
|
||||
|
||||
std::shared_ptr<const SampleBuffer> createSampleBuffer();
|
||||
|
||||
private:
|
||||
void writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain ) override;
|
||||
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
using BufferList = QList<QPair<sampleFrame*, fpp_t>>;
|
||||
BufferList m_buffers;
|
||||
@@ -59,4 +57,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_SAMPLE_RECORDER_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_SDL_H
|
||||
#define AUDIO_SDL_H
|
||||
#ifndef LMMS_AUDIO_SDL_H
|
||||
#define LMMS_AUDIO_SDL_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
@@ -115,4 +115,4 @@ private:
|
||||
|
||||
#endif // LMMS_HAVE_SDL
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_SDL_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_SNDIO_H
|
||||
#define _AUDIO_SNDIO_H
|
||||
#ifndef LMMS_AUDIO_SNDIO_H
|
||||
#define LMMS_AUDIO_SNDIO_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
@@ -87,6 +87,6 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_HAVE_SNDIO
|
||||
#endif // LMMS_HAVE_SNDIO
|
||||
|
||||
#endif // _AUDIO_SNDIO_H
|
||||
#endif // LMMS_AUDIO_SNDIO_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_SOUNDIO_H
|
||||
#define AUDIO_SOUNDIO_H
|
||||
#ifndef LMMS_AUDIO_SOUNDIO_H
|
||||
#define LMMS_AUDIO_SOUNDIO_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
@@ -145,4 +145,4 @@ private:
|
||||
|
||||
#endif // LMMS_HAVE_SOUNDIO
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_SOUNDIO_H
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef AUTOMATABLE_BUTTON_H
|
||||
#define AUTOMATABLE_BUTTON_H
|
||||
#ifndef LMMS_GUI_AUTOMATABLE_BUTTON_H
|
||||
#define LMMS_GUI_AUTOMATABLE_BUTTON_H
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
@@ -109,4 +108,4 @@ private:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_AUTOMATABLE_BUTTON_H
|
||||
|
||||
@@ -22,17 +22,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATABLE_MODEL_H
|
||||
#define AUTOMATABLE_MODEL_H
|
||||
#ifndef LMMS_AUTOMATABLE_MODEL_H
|
||||
#define LMMS_AUTOMATABLE_MODEL_H
|
||||
|
||||
#include <cmath>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include "JournallingObject.h"
|
||||
#include "Model.h"
|
||||
#include "TimePos.h"
|
||||
#include "ValueBuffer.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "ModelVisitor.h"
|
||||
|
||||
|
||||
@@ -76,11 +77,10 @@ class ControllerConnection;
|
||||
class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
MM_OPERATORS
|
||||
public:
|
||||
using AutoModelVector = QVector<AutomatableModel*>;
|
||||
using AutoModelVector = std::vector<AutomatableModel*>;
|
||||
|
||||
enum ScaleType
|
||||
enum class ScaleType
|
||||
{
|
||||
Linear,
|
||||
Logarithmic,
|
||||
@@ -144,7 +144,7 @@ public:
|
||||
template<bool>
|
||||
static bool castValue( const float v )
|
||||
{
|
||||
return ( qRound( v ) != 0 );
|
||||
return (std::round(v) != 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -231,11 +231,11 @@ public:
|
||||
}
|
||||
void setScaleLogarithmic( bool setToTrue = true )
|
||||
{
|
||||
setScaleType( setToTrue ? Logarithmic : Linear );
|
||||
setScaleType( setToTrue ? ScaleType::Logarithmic : ScaleType::Linear );
|
||||
}
|
||||
bool isScaleLogarithmic() const
|
||||
{
|
||||
return m_scaleType == Logarithmic;
|
||||
return m_scaleType == ScaleType::Logarithmic;
|
||||
}
|
||||
|
||||
void setStep( const float step );
|
||||
@@ -507,5 +507,4 @@ using AutomatedValueMap = QMap<AutomatableModel*, float>;
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LMMS_AUTOMATABLE_MODEL_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATABLE_MODEL_VIEW_H
|
||||
#define AUTOMATABLE_MODEL_VIEW_H
|
||||
#ifndef LMMS_GUI_AUTOMATABLE_MODEL_VIEW_H
|
||||
#define LMMS_GUI_AUTOMATABLE_MODEL_VIEW_H
|
||||
|
||||
#include "ModelView.h"
|
||||
#include "AutomatableModel.h"
|
||||
@@ -137,5 +137,4 @@ using BoolModelView = TypedModelView<BoolModel>;
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LMMS_GUI_AUTOMATABLE_MODEL_VIEW_H
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef AUTOMATABLE_SLIDER_H
|
||||
#define AUTOMATABLE_SLIDER_H
|
||||
#ifndef LMMS_GUI_AUTOMATABLE_SLIDER_H
|
||||
#define LMMS_GUI_AUTOMATABLE_SLIDER_H
|
||||
|
||||
#include <QSlider>
|
||||
|
||||
@@ -77,4 +76,4 @@ using sliderModel = IntModel;
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_AUTOMATABLE_SLIDER_H
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATION_CLIP_H
|
||||
#define AUTOMATION_CLIP_H
|
||||
#ifndef LMMS_AUTOMATION_CLIP_H
|
||||
#define LMMS_AUTOMATION_CLIP_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QPointer>
|
||||
@@ -46,6 +46,7 @@ class TimePos;
|
||||
namespace gui
|
||||
{
|
||||
class AutomationClipView;
|
||||
class AutomationEditor;
|
||||
} // namespace gui
|
||||
|
||||
|
||||
@@ -54,15 +55,15 @@ class LMMS_EXPORT AutomationClip : public Clip
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ProgressionTypes
|
||||
enum class ProgressionType
|
||||
{
|
||||
DiscreteProgression,
|
||||
LinearProgression,
|
||||
CubicHermiteProgression
|
||||
Discrete,
|
||||
Linear,
|
||||
CubicHermite
|
||||
} ;
|
||||
|
||||
using timeMap = QMap<int, AutomationNode>;
|
||||
using objectVector = QVector<QPointer<AutomatableModel>>;
|
||||
using objectVector = std::vector<QPointer<AutomatableModel>>;
|
||||
|
||||
using TimemapIterator = timeMap::const_iterator;
|
||||
|
||||
@@ -76,11 +77,11 @@ public:
|
||||
const objectVector& objects() const;
|
||||
|
||||
// progression-type stuff
|
||||
inline ProgressionTypes progressionType() const
|
||||
inline ProgressionType progressionType() const
|
||||
{
|
||||
return m_progressionType;
|
||||
}
|
||||
void setProgressionType( ProgressionTypes _new_progression_type );
|
||||
void setProgressionType( ProgressionType _new_progression_type );
|
||||
|
||||
inline float getTension() const
|
||||
{
|
||||
@@ -111,6 +112,13 @@ public:
|
||||
|
||||
void resetNodes(const int tick0, const int tick1);
|
||||
|
||||
/**
|
||||
* @brief Resets the tangents from the nodes between the given ticks
|
||||
* @param Int first tick of the range
|
||||
* @param Int second tick of the range
|
||||
*/
|
||||
void resetTangents(const int tick0, const int tick1);
|
||||
|
||||
void recordValue(TimePos time, float value);
|
||||
|
||||
TimePos setDragValue( const TimePos & time,
|
||||
@@ -151,10 +159,21 @@ public:
|
||||
return m_timeMap.isEmpty() == false;
|
||||
}
|
||||
|
||||
static bool supportsTangentEditing(ProgressionType pType)
|
||||
{
|
||||
// Update function if we have new progression types that support tangent editing
|
||||
return pType == ProgressionType::CubicHermite;
|
||||
}
|
||||
|
||||
inline bool canEditTangents() const
|
||||
{
|
||||
return supportsTangentEditing(m_progressionType);
|
||||
}
|
||||
|
||||
float valueAt( const TimePos & _time ) const;
|
||||
float *valuesAfter( const TimePos & _time ) const;
|
||||
|
||||
const QString name() const;
|
||||
QString name() const;
|
||||
|
||||
// settings-management
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
@@ -167,7 +186,7 @@ public:
|
||||
|
||||
|
||||
static bool isAutomated( const AutomatableModel * _m );
|
||||
static QVector<AutomationClip *> clipsForModel( const AutomatableModel * _m );
|
||||
static std::vector<AutomationClip*> clipsForModel(const AutomatableModel* _m);
|
||||
static AutomationClip * globalAutomationClip( AutomatableModel * _m );
|
||||
static void resolveAllIDs();
|
||||
|
||||
@@ -190,6 +209,15 @@ private:
|
||||
void generateTangents(timeMap::iterator it, int numToGenerate);
|
||||
float valueAt( timeMap::const_iterator v, int offset ) const;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* This function combines the song tracks, pattern store tracks,
|
||||
* and the global automation track all in one vector.
|
||||
*
|
||||
* @return std::vector<Track*>
|
||||
*/
|
||||
static std::vector<Track*> combineAllTracks();
|
||||
|
||||
// Mutex to make methods involving automation clips thread safe
|
||||
// Mutable so we can lock it from const objects
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
|
||||
@@ -199,17 +227,20 @@ private:
|
||||
#endif
|
||||
|
||||
AutomationTrack * m_autoTrack;
|
||||
QVector<jo_id_t> m_idsToResolve;
|
||||
std::vector<jo_id_t> m_idsToResolve;
|
||||
objectVector m_objects;
|
||||
timeMap m_timeMap; // actual values
|
||||
timeMap m_oldTimeMap; // old values for storing the values before setDragValue() is called.
|
||||
float m_tension;
|
||||
bool m_hasAutomation;
|
||||
ProgressionTypes m_progressionType;
|
||||
ProgressionType m_progressionType;
|
||||
|
||||
bool m_dragging;
|
||||
bool m_dragKeepOutValue; // Should we keep the current dragged node's outValue?
|
||||
float m_dragOutValue; // The outValue of the dragged node's
|
||||
bool m_dragLockedTan; // If the dragged node has it's tangents locked
|
||||
float m_dragInTan; // The dragged node's inTangent
|
||||
float m_dragOutTan; // The dragged node's outTangent
|
||||
|
||||
bool m_isRecording;
|
||||
float m_lastRecordedValue;
|
||||
@@ -221,6 +252,7 @@ private:
|
||||
|
||||
friend class gui::AutomationClipView;
|
||||
friend class AutomationNode;
|
||||
friend class gui::AutomationEditor;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -252,6 +284,11 @@ inline float OUTTAN(AutomationClip::TimemapIterator it)
|
||||
return it->getOutTangent();
|
||||
}
|
||||
|
||||
inline float LOCKEDTAN(AutomationClip::TimemapIterator it)
|
||||
{
|
||||
return it->lockedTangents();
|
||||
}
|
||||
|
||||
inline int POS(AutomationClip::TimemapIterator it)
|
||||
{
|
||||
return it.key();
|
||||
@@ -260,4 +297,4 @@ inline int POS(AutomationClip::TimemapIterator it)
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUTOMATION_CLIP_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATION_CLIP_VIEW_H
|
||||
#define AUTOMATION_CLIP_VIEW_H
|
||||
#ifndef LMMS_GUI_AUTOMATION_CLIP_VIEW_H
|
||||
#define LMMS_GUI_AUTOMATION_CLIP_VIEW_H
|
||||
|
||||
#include <QStaticText>
|
||||
|
||||
@@ -74,9 +74,6 @@ private:
|
||||
QPixmap m_paintPixmap;
|
||||
|
||||
QStaticText m_staticTextName;
|
||||
|
||||
static QPixmap * s_clip_rec;
|
||||
|
||||
void scaleTimemapToFit( float oldMin, float oldMax );
|
||||
} ;
|
||||
|
||||
@@ -85,4 +82,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_AUTOMATION_CLIP_VIEW_H
|
||||
|
||||
@@ -23,18 +23,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATION_EDITOR_H
|
||||
#define AUTOMATION_EDITOR_H
|
||||
#ifndef LMMS_GUI_AUTOMATION_EDITOR_H
|
||||
#define LMMS_GUI_AUTOMATION_EDITOR_H
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
#include <array>
|
||||
|
||||
#include "Editor.h"
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "TimePos.h"
|
||||
#include "AutomationClip.h"
|
||||
#include "ComboBoxModel.h"
|
||||
#include "Editor.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "MidiClip.h"
|
||||
#include "SampleClip.h"
|
||||
#include "TimePos.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
class QPainter;
|
||||
class QPixmap;
|
||||
@@ -62,12 +65,18 @@ class AutomationEditor : public QWidget, public JournallingObject
|
||||
Q_PROPERTY(QColor lineColor MEMBER m_lineColor)
|
||||
Q_PROPERTY(QColor nodeInValueColor MEMBER m_nodeInValueColor)
|
||||
Q_PROPERTY(QColor nodeOutValueColor MEMBER m_nodeOutValueColor)
|
||||
Q_PROPERTY(QColor nodeTangentLineColor MEMBER m_nodeTangentLineColor)
|
||||
Q_PROPERTY(QBrush scaleColor MEMBER m_scaleColor)
|
||||
Q_PROPERTY(QBrush graphColor MEMBER m_graphColor)
|
||||
Q_PROPERTY(QColor crossColor MEMBER m_crossColor)
|
||||
Q_PROPERTY(QColor backgroundShade MEMBER m_backgroundShade)
|
||||
Q_PROPERTY(QColor ghostNoteColor MEMBER m_ghostNoteColor)
|
||||
Q_PROPERTY(QColor detuningNoteColor MEMBER m_detuningNoteColor)
|
||||
Q_PROPERTY(QColor ghostSampleColor MEMBER m_ghostSampleColor)
|
||||
public:
|
||||
void setCurrentClip(AutomationClip * new_clip);
|
||||
void setGhostMidiClip(MidiClip* newMidiClip);
|
||||
void setGhostSample(SampleClip* newSample);
|
||||
|
||||
inline const AutomationClip * currentClip() const
|
||||
{
|
||||
@@ -86,11 +95,12 @@ public:
|
||||
return "automationeditor";
|
||||
}
|
||||
|
||||
enum EditModes
|
||||
enum class EditMode
|
||||
{
|
||||
DRAW,
|
||||
ERASE,
|
||||
DRAW_OUTVALUES
|
||||
Draw,
|
||||
Erase,
|
||||
DrawOutValues,
|
||||
EditTangents
|
||||
};
|
||||
|
||||
public slots:
|
||||
@@ -117,6 +127,13 @@ protected:
|
||||
inline void drawLevelTick(QPainter & p, int tick, float value);
|
||||
|
||||
timeMap::iterator getNodeAt(int x, int y, bool outValue = false, int r = 5);
|
||||
/**
|
||||
* @brief Given a mouse X coordinate, returns a timeMap::iterator that points to
|
||||
* the closest node.
|
||||
* @param Int X coordinate
|
||||
* @return timeMap::iterator with the closest node or timeMap.end() if there are no nodes.
|
||||
*/
|
||||
timeMap::iterator getClosestNode(int x);
|
||||
|
||||
void drawLine( int x0, float y0, int x1, float y1 );
|
||||
bool fineTuneValue(timeMap::iterator node, bool editingOutValue);
|
||||
@@ -128,10 +145,16 @@ protected slots:
|
||||
void horScrolled( int new_pos );
|
||||
void verScrolled( int new_pos );
|
||||
|
||||
void setEditMode(AutomationEditor::EditModes mode);
|
||||
void setEditMode(AutomationEditor::EditMode mode);
|
||||
void setEditMode(int mode);
|
||||
|
||||
void setProgressionType(AutomationClip::ProgressionTypes type);
|
||||
void setProgressionType(AutomationClip::ProgressionType type);
|
||||
/**
|
||||
* @brief This method handles the AutomationEditorWindow event of changing
|
||||
* progression types. After that, it calls updateEditTanButton so the edit
|
||||
* tangents button is updated accordingly
|
||||
* @param Int New progression type
|
||||
*/
|
||||
void setProgressionType(int type);
|
||||
void setTension();
|
||||
|
||||
@@ -143,16 +166,25 @@ protected slots:
|
||||
/// Updates the clip's quantization using the current user selected value.
|
||||
void setQuantization();
|
||||
|
||||
void resetGhostNotes()
|
||||
{
|
||||
m_ghostNotes = nullptr;
|
||||
m_ghostSample = nullptr;
|
||||
update();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
enum Actions
|
||||
enum class Action
|
||||
{
|
||||
NONE,
|
||||
MOVE_VALUE,
|
||||
ERASE_VALUES,
|
||||
MOVE_OUTVALUE,
|
||||
RESET_OUTVALUES,
|
||||
DRAW_LINE
|
||||
None,
|
||||
MoveValue,
|
||||
EraseValues,
|
||||
MoveOutValue,
|
||||
ResetOutValues,
|
||||
DrawLine,
|
||||
MoveTangent,
|
||||
ResetTangents
|
||||
} ;
|
||||
|
||||
// some constants...
|
||||
@@ -165,22 +197,29 @@ private:
|
||||
|
||||
static const int VALUES_WIDTH = 64;
|
||||
|
||||
static const int NOTE_HEIGHT = 10; // height of individual notes
|
||||
static const int NOTE_MARGIN = 40; // total border margin for notes
|
||||
static const int MIN_NOTE_RANGE = 20; // min number of keys for fixed size
|
||||
static const int SAMPLE_MARGIN = 40;
|
||||
static constexpr int MAX_SAMPLE_HEIGHT = 400; // constexpr for use in min
|
||||
|
||||
AutomationEditor();
|
||||
AutomationEditor( const AutomationEditor & );
|
||||
~AutomationEditor() override;
|
||||
|
||||
static QPixmap * s_toolDraw;
|
||||
static QPixmap * s_toolErase;
|
||||
static QPixmap * s_toolDrawOut;
|
||||
static QPixmap * s_toolMove;
|
||||
static QPixmap * s_toolYFlip;
|
||||
static QPixmap * s_toolXFlip;
|
||||
QPixmap m_toolDraw = embed::getIconPixmap("edit_draw");
|
||||
QPixmap m_toolErase = embed::getIconPixmap("edit_erase");
|
||||
QPixmap m_toolDrawOut = embed::getIconPixmap("edit_draw_outvalue");
|
||||
QPixmap m_toolEditTangents = embed::getIconPixmap("edit_tangent");
|
||||
QPixmap m_toolMove = embed::getIconPixmap("edit_move");
|
||||
QPixmap m_toolYFlip = embed::getIconPixmap("flip_y");
|
||||
QPixmap m_toolXFlip = embed::getIconPixmap("flip_x");
|
||||
|
||||
ComboBoxModel m_zoomingXModel;
|
||||
ComboBoxModel m_zoomingYModel;
|
||||
ComboBoxModel m_quantizeModel;
|
||||
|
||||
static const QVector<float> m_zoomXLevels;
|
||||
static const std::array<float, 7> m_zoomXLevels;
|
||||
|
||||
FloatModel * m_tensionModel;
|
||||
|
||||
@@ -192,6 +231,10 @@ private:
|
||||
float m_bottomLevel;
|
||||
float m_topLevel;
|
||||
|
||||
MidiClip* m_ghostNotes = nullptr;
|
||||
QPointer<SampleClip> m_ghostSample = nullptr; // QPointer to set to nullptr on deletion
|
||||
bool m_renderSample = false;
|
||||
|
||||
void centerTopBottomScroll();
|
||||
void updateTopBottomLevels();
|
||||
|
||||
@@ -200,7 +243,7 @@ private:
|
||||
|
||||
TimePos m_currentPosition;
|
||||
|
||||
Actions m_action;
|
||||
Action m_action;
|
||||
|
||||
int m_moveXOffset;
|
||||
|
||||
@@ -214,7 +257,12 @@ private:
|
||||
// Time position (key) of automation node whose outValue is being dragged
|
||||
int m_draggedOutValueKey;
|
||||
|
||||
EditModes m_editMode;
|
||||
// The tick from the node whose tangent is being dragged
|
||||
int m_draggedTangentTick;
|
||||
// Whether the tangent being dragged is the InTangent or OutTangent
|
||||
bool m_draggedOutTangent;
|
||||
|
||||
EditMode m_editMode;
|
||||
|
||||
bool m_mouseDownLeft;
|
||||
bool m_mouseDownRight; //true if right click is being held down
|
||||
@@ -224,6 +272,7 @@ private:
|
||||
|
||||
void drawCross(QPainter & p );
|
||||
void drawAutomationPoint( QPainter & p, timeMap::iterator it );
|
||||
void drawAutomationTangents(QPainter& p, timeMap::iterator it);
|
||||
bool inPatternEditor();
|
||||
|
||||
QColor m_barLineColor;
|
||||
@@ -232,9 +281,13 @@ private:
|
||||
QBrush m_graphColor;
|
||||
QColor m_nodeInValueColor;
|
||||
QColor m_nodeOutValueColor;
|
||||
QColor m_nodeTangentLineColor;
|
||||
QBrush m_scaleColor;
|
||||
QColor m_crossColor;
|
||||
QColor m_backgroundShade;
|
||||
QColor m_ghostNoteColor;
|
||||
QColor m_detuningNoteColor;
|
||||
QColor m_ghostSampleColor;
|
||||
|
||||
friend class AutomationEditorWindow;
|
||||
|
||||
@@ -258,6 +311,9 @@ public:
|
||||
~AutomationEditorWindow() override = default;
|
||||
|
||||
void setCurrentClip(AutomationClip* clip);
|
||||
void setGhostMidiClip(MidiClip* clip) { m_editor->setGhostMidiClip(clip); };
|
||||
void setGhostSample(SampleClip* newSample) { m_editor->setGhostSample(newSample); };
|
||||
|
||||
const AutomationClip* currentClip();
|
||||
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
@@ -284,8 +340,21 @@ protected slots:
|
||||
|
||||
private slots:
|
||||
void updateWindowTitle();
|
||||
void setProgressionType(int progType);
|
||||
/**
|
||||
* @brief The Edit Tangent edit mode should only be available for
|
||||
* Cubic Hermite progressions, so this method is responsable for disabling it
|
||||
* for other edit modes and reenabling it when it changes back to the Edit Tangent
|
||||
* mode.
|
||||
*/
|
||||
void updateEditTanButton();
|
||||
|
||||
private:
|
||||
QAction* m_drawAction;
|
||||
QAction* m_eraseAction;
|
||||
QAction* m_drawOutAction;
|
||||
QAction* m_editTanAction;
|
||||
|
||||
QAction* m_discreteAction;
|
||||
QAction* m_linearAction;
|
||||
QAction* m_cubicHermiteAction;
|
||||
@@ -298,10 +367,12 @@ private:
|
||||
ComboBox * m_zoomingXComboBox;
|
||||
ComboBox * m_zoomingYComboBox;
|
||||
ComboBox * m_quantizeComboBox;
|
||||
|
||||
QPushButton* m_resetGhostNotes;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_AUTOMATION_EDITOR_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATION_NODE_H
|
||||
#define AUTOMATION_NODE_H
|
||||
#ifndef LMMS_AUTOMATION_NODE_H
|
||||
#define LMMS_AUTOMATION_NODE_H
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
@@ -125,6 +125,22 @@ public:
|
||||
m_outTangent = tangent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the tangents from the node are locked
|
||||
*/
|
||||
inline const bool lockedTangents() const
|
||||
{
|
||||
return m_lockedTangents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Locks or Unlocks the tangents from this node
|
||||
*/
|
||||
inline void setLockedTangents(bool b)
|
||||
{
|
||||
m_lockedTangents = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the clip this node belongs to
|
||||
* @param AutomationClip* clip that m_clip will be
|
||||
@@ -152,8 +168,13 @@ private:
|
||||
// outValue are equal, inTangent and outTangent are equal too.
|
||||
float m_inTangent;
|
||||
float m_outTangent;
|
||||
|
||||
// If the tangents were edited manually, this will be true. That way
|
||||
// the tangents from this node will not be recalculated. It's set back
|
||||
// to false if the tangents are reset.
|
||||
bool m_lockedTangents;
|
||||
};
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUTOMATION_NODE_H
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATION_TRACK_H
|
||||
#define AUTOMATION_TRACK_H
|
||||
#ifndef LMMS_AUTOMATION_TRACK_H
|
||||
#define LMMS_AUTOMATION_TRACK_H
|
||||
|
||||
#include "Track.h"
|
||||
|
||||
@@ -62,4 +62,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUTOMATION_TRACK_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATION_TRACK_VIEW_H
|
||||
#define AUTOMATION_TRACK_VIEW_H
|
||||
#ifndef LMMS_GUI_AUTOMATION_TRACK_VIEW_H
|
||||
#define LMMS_GUI_AUTOMATION_TRACK_VIEW_H
|
||||
|
||||
#include "TrackView.h"
|
||||
|
||||
@@ -52,4 +52,4 @@ public:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_AUTOMATION_TRACK_VIEW_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BANDLIMITEDWAVE_H
|
||||
#define BANDLIMITEDWAVE_H
|
||||
#ifndef LMMS_BANDLIMITEDWAVE_H
|
||||
#define LMMS_BANDLIMITEDWAVE_H
|
||||
|
||||
class QDataStream;
|
||||
class QString;
|
||||
@@ -89,14 +89,15 @@ QDataStream& operator>> ( QDataStream &in, WaveMipMap &waveMipMap );
|
||||
class LMMS_EXPORT BandLimitedWave
|
||||
{
|
||||
public:
|
||||
enum Waveforms
|
||||
enum class Waveform
|
||||
{
|
||||
BLSaw,
|
||||
BLSquare,
|
||||
BLTriangle,
|
||||
BLMoog,
|
||||
NumBLWaveforms
|
||||
Count
|
||||
};
|
||||
constexpr static auto NumWaveforms = static_cast<std::size_t>(Waveform::Count);
|
||||
|
||||
BandLimitedWave() = default;
|
||||
virtual ~BandLimitedWave() = default;
|
||||
@@ -127,7 +128,7 @@ public:
|
||||
* \param _wavelen The wavelength (length of one cycle, ie. the inverse of frequency) of the wanted oscillation, measured in sample frames
|
||||
* \param _wave The wanted waveform. Options currently are saw, triangle, square and moog saw.
|
||||
*/
|
||||
static inline sample_t oscillate( float _ph, float _wavelen, Waveforms _wave )
|
||||
static inline sample_t oscillate( float _ph, float _wavelen, Waveform _wave )
|
||||
{
|
||||
// get the next higher tlen
|
||||
int t = 0;
|
||||
@@ -139,27 +140,28 @@ public:
|
||||
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 sample_t s1 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, lookup );
|
||||
const sample_t s2 = s_waveforms[ static_cast<std::size_t>(_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 s0 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, lm );
|
||||
const sample_t s3 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, ( lookup + 2 ) % tlen );
|
||||
const sample_t sr = optimal4pInterpolate( s0, s1, s2, s3, ip );
|
||||
|
||||
return sr;
|
||||
|
||||
/* lookup = lookup << 1;
|
||||
/*
|
||||
lookup = lookup << 1;
|
||||
tlen = tlen << 1;
|
||||
t += 1;
|
||||
const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, lookup );
|
||||
const sample_t s4 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen );
|
||||
const sample_t s3 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, lookup );
|
||||
const sample_t s4 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, ( lookup + 1 ) % tlen );
|
||||
const sample_t s34 = linearInterpolate( s3, s4, ip );
|
||||
|
||||
const float ip2 = ( ( tlen - _wavelen ) / tlen - 0.5 ) * 2.0;
|
||||
|
||||
return linearInterpolate( s12, s34, ip2 );
|
||||
*/
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
@@ -167,11 +169,11 @@ public:
|
||||
|
||||
static bool s_wavesGenerated;
|
||||
|
||||
static std::array<WaveMipMap, NumBLWaveforms> s_waveforms;
|
||||
static std::array<WaveMipMap, NumWaveforms> s_waveforms;
|
||||
|
||||
static QString s_wavetableDir;
|
||||
};
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_BANDLIMITEDWAVE_H
|
||||
|
||||
76
include/BarModelEditor.h
Normal file
76
include/BarModelEditor.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* BarModelEditor.h - edit model values using a bar display
|
||||
*
|
||||
* Copyright (c) 2023-now Michael Gregorius
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef LMMS_GUI_BAR_MODEL_EDITOR_H
|
||||
#define LMMS_GUI_BAR_MODEL_EDITOR_H
|
||||
|
||||
#include "FloatModelEditorBase.h"
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class LMMS_EXPORT BarModelEditor : public FloatModelEditorBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Q_PROPERTY(QBrush backgroundBrush READ getBackgroundBrush WRITE setBackgroundBrush)
|
||||
Q_PROPERTY(QBrush barBrush READ getBarBrush WRITE setBarBrush)
|
||||
Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
|
||||
|
||||
BarModelEditor(QString text, FloatModel * floatModel, QWidget * parent = nullptr);
|
||||
|
||||
// Define how the widget will behave in a layout
|
||||
QSizePolicy sizePolicy() const;
|
||||
|
||||
QSize minimumSizeHint() const override;
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
QBrush const & getBackgroundBrush() const;
|
||||
void setBackgroundBrush(QBrush const & backgroundBrush);
|
||||
|
||||
QBrush const & getBarBrush() const;
|
||||
void setBarBrush(QBrush const & barBrush);
|
||||
|
||||
QColor const & getTextColor() const;
|
||||
void setTextColor(QColor const & textColor);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
QString const m_text;
|
||||
|
||||
QBrush m_backgroundBrush;
|
||||
QBrush m_barBrush;
|
||||
QColor m_textColor;
|
||||
};
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_BAR_MODEL_EDITOR_H
|
||||
@@ -28,9 +28,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BASIC_FILTERS_H
|
||||
#define BASIC_FILTERS_H
|
||||
#ifndef LMMS_BASIC_FILTERS_H
|
||||
#define LMMS_BASIC_FILTERS_H
|
||||
|
||||
#ifndef __USE_XOPEN
|
||||
#define __USE_XOPEN
|
||||
@@ -41,7 +40,6 @@
|
||||
#include "lmms_basics.h"
|
||||
#include "lmms_constants.h"
|
||||
#include "interpolation.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
@@ -51,7 +49,6 @@ template<ch_cnt_t CHANNELS=DEFAULT_CHANNELS> class BasicFilters;
|
||||
template<ch_cnt_t CHANNELS>
|
||||
class LinkwitzRiley
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
LinkwitzRiley( float sampleRate )
|
||||
{
|
||||
@@ -146,9 +143,13 @@ using StereoLinkwitzRiley = LinkwitzRiley<2>;
|
||||
template<ch_cnt_t CHANNELS>
|
||||
class BiQuad
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
BiQuad()
|
||||
BiQuad() :
|
||||
m_a1(0.),
|
||||
m_a2(0.),
|
||||
m_b0(0.),
|
||||
m_b1(0.),
|
||||
m_b2(0.)
|
||||
{
|
||||
clearHistory();
|
||||
}
|
||||
@@ -189,7 +190,6 @@ using StereoBiQuad = BiQuad<2>;
|
||||
template<ch_cnt_t CHANNELS>
|
||||
class OnePole
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
OnePole()
|
||||
{
|
||||
@@ -210,7 +210,7 @@ public:
|
||||
|
||||
inline float update( float s, ch_cnt_t ch )
|
||||
{
|
||||
if( qAbs( s ) < 1.0e-10f && qAbs( m_z1[ch] ) < 1.0e-10f ) return 0.0f;
|
||||
if (std::abs(s) < 1.0e-10f && std::abs(m_z1[ch]) < 1.0e-10f) return 0.0f;
|
||||
return m_z1[ch] = s * m_a0 + m_z1[ch] * m_b1;
|
||||
}
|
||||
|
||||
@@ -223,9 +223,8 @@ using StereoOnePole = OnePole<2>;
|
||||
template<ch_cnt_t CHANNELS>
|
||||
class BasicFilters
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
enum FilterTypes
|
||||
enum class FilterType
|
||||
{
|
||||
LowPass,
|
||||
HiPass,
|
||||
@@ -248,8 +247,7 @@ public:
|
||||
Highpass_SV,
|
||||
Notch_SV,
|
||||
FastFormant,
|
||||
Tripole,
|
||||
NumFilters
|
||||
Tripole
|
||||
};
|
||||
|
||||
static inline float minFreq()
|
||||
@@ -262,20 +260,20 @@ public:
|
||||
return( 0.01f );
|
||||
}
|
||||
|
||||
inline void setFilterType( const int _idx )
|
||||
inline void setFilterType( const FilterType _idx )
|
||||
{
|
||||
m_doubleFilter = _idx == DoubleLowPass || _idx == DoubleMoog;
|
||||
m_doubleFilter = _idx == FilterType::DoubleLowPass || _idx == FilterType::DoubleMoog;
|
||||
if( !m_doubleFilter )
|
||||
{
|
||||
m_type = static_cast<FilterTypes>( _idx );
|
||||
m_type = _idx;
|
||||
return;
|
||||
}
|
||||
|
||||
// Double lowpass mode, backwards-compat for the goofy
|
||||
// Add-NumFilters to signify doubleFilter stuff
|
||||
m_type = _idx == DoubleLowPass
|
||||
? LowPass
|
||||
: Moog;
|
||||
m_type = _idx == FilterType::DoubleLowPass
|
||||
? FilterType::LowPass
|
||||
: FilterType::Moog;
|
||||
if( m_subFilter == nullptr )
|
||||
{
|
||||
m_subFilter = new BasicFilters<CHANNELS>(
|
||||
@@ -330,33 +328,39 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
inline void setSampleRate(const sample_rate_t sampleRate)
|
||||
{
|
||||
m_sampleRate = sampleRate;
|
||||
m_sampleRatio = 1.f / m_sampleRate;
|
||||
if (m_subFilter != nullptr)
|
||||
{
|
||||
m_subFilter->setSampleRate(m_sampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
inline sample_t update( sample_t _in0, ch_cnt_t _chnl )
|
||||
{
|
||||
sample_t out;
|
||||
sample_t out = 0.0f;
|
||||
switch( m_type )
|
||||
{
|
||||
case Moog:
|
||||
case FilterType::Moog:
|
||||
{
|
||||
sample_t x = _in0 - m_r*m_y4[_chnl];
|
||||
|
||||
// four cascaded onepole filters
|
||||
// (bilinear transform)
|
||||
m_y1[_chnl] = qBound( -10.0f,
|
||||
( x + m_oldx[_chnl] ) * m_p
|
||||
- m_k * m_y1[_chnl],
|
||||
10.0f );
|
||||
m_y2[_chnl] = qBound( -10.0f,
|
||||
( m_y1[_chnl] + m_oldy1[_chnl] ) * m_p
|
||||
- m_k * m_y2[_chnl],
|
||||
10.0f );
|
||||
m_y3[_chnl] = qBound( -10.0f,
|
||||
( m_y2[_chnl] + m_oldy2[_chnl] ) * m_p
|
||||
- m_k * m_y3[_chnl],
|
||||
10.0f );
|
||||
m_y4[_chnl] = qBound( -10.0f,
|
||||
( m_y3[_chnl] + m_oldy3[_chnl] ) * m_p
|
||||
- m_k * m_y4[_chnl],
|
||||
m_y1[_chnl] = std::clamp((x + m_oldx[_chnl]) * m_p
|
||||
- m_k * m_y1[_chnl], -10.0f,
|
||||
10.0f);
|
||||
m_y2[_chnl] = std::clamp((m_y1[_chnl] + m_oldy1[_chnl]) * m_p
|
||||
- m_k * m_y2[_chnl], -10.0f,
|
||||
10.0f);
|
||||
m_y3[_chnl] = std::clamp((m_y2[_chnl] + m_oldy2[_chnl]) * m_p
|
||||
- m_k * m_y3[_chnl], -10.0f,
|
||||
10.0f );
|
||||
m_y4[_chnl] = std::clamp((m_y3[_chnl] + m_oldy3[_chnl]) * m_p
|
||||
- m_k * m_y4[_chnl], -10.0f,
|
||||
10.0f);
|
||||
|
||||
m_oldx[_chnl] = x;
|
||||
m_oldy1[_chnl] = m_y1[_chnl];
|
||||
@@ -369,27 +373,23 @@ public:
|
||||
|
||||
// 3x onepole filters with 4x oversampling and interpolation of oversampled signal:
|
||||
// input signal is linear-interpolated after oversampling, output signal is averaged from oversampled outputs
|
||||
case Tripole:
|
||||
case FilterType::Tripole:
|
||||
{
|
||||
out = 0.0f;
|
||||
float ip = 0.0f;
|
||||
for( int i = 0; i < 4; ++i )
|
||||
{
|
||||
ip += 0.25f;
|
||||
sample_t x = linearInterpolate( m_last[_chnl], _in0, ip ) - m_r * m_y3[_chnl];
|
||||
|
||||
m_y1[_chnl] = qBound( -10.0f,
|
||||
( x + m_oldx[_chnl] ) * m_p
|
||||
- m_k * m_y1[_chnl],
|
||||
10.0f );
|
||||
m_y2[_chnl] = qBound( -10.0f,
|
||||
( m_y1[_chnl] + m_oldy1[_chnl] ) * m_p
|
||||
- m_k * m_y2[_chnl],
|
||||
10.0f );
|
||||
m_y3[_chnl] = qBound( -10.0f,
|
||||
( m_y2[_chnl] + m_oldy2[_chnl] ) * m_p
|
||||
- m_k * m_y3[_chnl],
|
||||
10.0f );
|
||||
m_y1[_chnl] = std::clamp((x + m_oldx[_chnl]) * m_p
|
||||
- m_k * m_y1[_chnl], -10.0f,
|
||||
10.0f);
|
||||
m_y2[_chnl] = std::clamp((m_y1[_chnl] + m_oldy1[_chnl]) * m_p
|
||||
- m_k * m_y2[_chnl], -10.0f,
|
||||
10.0f);
|
||||
m_y3[_chnl] = std::clamp((m_y2[_chnl] + m_oldy2[_chnl]) * m_p
|
||||
- m_k * m_y3[_chnl], -10.0f,
|
||||
10.0f);
|
||||
m_oldx[_chnl] = x;
|
||||
m_oldy1[_chnl] = m_y1[_chnl];
|
||||
m_oldy2[_chnl] = m_y2[_chnl];
|
||||
@@ -405,8 +405,8 @@ public:
|
||||
// and extended to other SV filter types
|
||||
// /* Hal Chamberlin's state variable filter */
|
||||
|
||||
case Lowpass_SV:
|
||||
case Bandpass_SV:
|
||||
case FilterType::Lowpass_SV:
|
||||
case FilterType::Bandpass_SV:
|
||||
{
|
||||
float highpass;
|
||||
|
||||
@@ -422,15 +422,14 @@ public:
|
||||
}
|
||||
|
||||
/* mix filter output into output buffer */
|
||||
return m_type == Lowpass_SV
|
||||
return m_type == FilterType::Lowpass_SV
|
||||
? m_delay4[_chnl]
|
||||
: m_delay3[_chnl];
|
||||
}
|
||||
|
||||
case Highpass_SV:
|
||||
case FilterType::Highpass_SV:
|
||||
{
|
||||
float hp;
|
||||
|
||||
for( int i = 0; i < 2; ++i ) // 2x oversample
|
||||
{
|
||||
m_delay2[_chnl] = m_delay2[_chnl] + m_svf1 * m_delay1[_chnl];
|
||||
@@ -441,10 +440,9 @@ public:
|
||||
return hp;
|
||||
}
|
||||
|
||||
case Notch_SV:
|
||||
case FilterType::Notch_SV:
|
||||
{
|
||||
float hp1, hp2;
|
||||
|
||||
float hp1;
|
||||
for( int i = 0; i < 2; ++i ) // 2x oversample
|
||||
{
|
||||
m_delay2[_chnl] = m_delay2[_chnl] + m_svf1 * m_delay1[_chnl]; /* delay2/4 = lowpass output */
|
||||
@@ -452,7 +450,7 @@ public:
|
||||
m_delay1[_chnl] = m_svf1 * hp1 + m_delay1[_chnl]; /* delay1/3 = bandpass output */
|
||||
|
||||
m_delay4[_chnl] = m_delay4[_chnl] + m_svf2 * m_delay3[_chnl];
|
||||
hp2 = m_delay2[_chnl] - m_delay4[_chnl] - m_svq * m_delay3[_chnl];
|
||||
float hp2 = m_delay2[_chnl] - m_delay4[_chnl] - m_svq * m_delay3[_chnl];
|
||||
m_delay3[_chnl] = m_svf2 * hp2 + m_delay3[_chnl];
|
||||
}
|
||||
|
||||
@@ -466,22 +464,22 @@ public:
|
||||
// can be driven up to self-oscillation (BTW: do not remove the limits!!!).
|
||||
// (C) 1998 ... 2009 S.Fendt. Released under the GPL v2.0 or any later version.
|
||||
|
||||
case Lowpass_RC12:
|
||||
case FilterType::Lowpass_RC12:
|
||||
{
|
||||
sample_t lp, bp, hp, in;
|
||||
sample_t lp = 0.0f;
|
||||
for( int n = 4; n != 0; --n )
|
||||
{
|
||||
in = _in0 + m_rcbp0[_chnl] * m_rcq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
sample_t in = _in0 + m_rcbp0[_chnl] * m_rcq;
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
lp = in * m_rcb + m_rclp0[_chnl] * m_rca;
|
||||
lp = qBound( -1.0f, lp, 1.0f );
|
||||
lp = std::clamp(lp, -1.0f, 1.0f);
|
||||
|
||||
hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
sample_t hp = m_rcc * (m_rchp0[_chnl] + in - m_rclast0[_chnl]);
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
sample_t bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_rclast0[_chnl] = in;
|
||||
m_rclp0[_chnl] = lp;
|
||||
@@ -490,45 +488,45 @@ public:
|
||||
}
|
||||
return lp;
|
||||
}
|
||||
case Highpass_RC12:
|
||||
case Bandpass_RC12:
|
||||
case FilterType::Highpass_RC12:
|
||||
case FilterType::Bandpass_RC12:
|
||||
{
|
||||
sample_t hp, bp, in;
|
||||
sample_t hp, bp;
|
||||
for( int n = 4; n != 0; --n )
|
||||
{
|
||||
in = _in0 + m_rcbp0[_chnl] * m_rcq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
sample_t in = _in0 + m_rcbp0[_chnl] * m_rcq;
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_rclast0[_chnl] = in;
|
||||
m_rchp0[_chnl] = hp;
|
||||
m_rcbp0[_chnl] = bp;
|
||||
}
|
||||
return m_type == Highpass_RC12 ? hp : bp;
|
||||
return m_type == FilterType::Highpass_RC12 ? hp : bp;
|
||||
}
|
||||
|
||||
case Lowpass_RC24:
|
||||
case FilterType::Lowpass_RC24:
|
||||
{
|
||||
sample_t lp, bp, hp, in;
|
||||
sample_t lp;
|
||||
for( int n = 4; n != 0; --n )
|
||||
{
|
||||
// first stage is as for the 12dB case...
|
||||
in = _in0 + m_rcbp0[_chnl] * m_rcq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
sample_t in = _in0 + m_rcbp0[_chnl] * m_rcq;
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
lp = in * m_rcb + m_rclp0[_chnl] * m_rca;
|
||||
lp = qBound( -1.0f, lp, 1.0f );
|
||||
lp = std::clamp(lp, -1.0f, 1.0f);
|
||||
|
||||
hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
sample_t hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
sample_t bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_rclast0[_chnl] = in;
|
||||
m_rclp0[_chnl] = lp;
|
||||
@@ -537,16 +535,16 @@ public:
|
||||
|
||||
// second stage gets the output of the first stage as input...
|
||||
in = lp + m_rcbp1[_chnl] * m_rcq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
in = std::clamp(in, -1.0f, 1.0f );
|
||||
|
||||
lp = in * m_rcb + m_rclp1[_chnl] * m_rca;
|
||||
lp = qBound( -1.0f, lp, 1.0f );
|
||||
lp = std::clamp(lp, -1.0f, 1.0f);
|
||||
|
||||
hp = m_rcc * ( m_rchp1[_chnl] + in - m_rclast1[_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_rcb + m_rcbp1[_chnl] * m_rca;
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_rclast1[_chnl] = in;
|
||||
m_rclp1[_chnl] = lp;
|
||||
@@ -555,91 +553,89 @@ public:
|
||||
}
|
||||
return lp;
|
||||
}
|
||||
case Highpass_RC24:
|
||||
case Bandpass_RC24:
|
||||
case FilterType::Highpass_RC24:
|
||||
case FilterType::Bandpass_RC24:
|
||||
{
|
||||
sample_t hp, bp, in;
|
||||
sample_t hp, bp;
|
||||
for( int n = 4; n != 0; --n )
|
||||
{
|
||||
// first stage is as for the 12dB case...
|
||||
in = _in0 + m_rcbp0[_chnl] * m_rcq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
sample_t in = _in0 + m_rcbp0[_chnl] * m_rcq;
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_rclast0[_chnl] = in;
|
||||
m_rchp0[_chnl] = hp;
|
||||
m_rcbp0[_chnl] = bp;
|
||||
|
||||
// second stage gets the output of the first stage as input...
|
||||
in = m_type == Highpass_RC24
|
||||
in = m_type == FilterType::Highpass_RC24
|
||||
? hp + m_rcbp1[_chnl] * m_rcq
|
||||
: bp + m_rcbp1[_chnl] * m_rcq;
|
||||
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
hp = m_rcc * ( m_rchp1[_chnl] + in - m_rclast1[_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_rcb + m_rcbp1[_chnl] * m_rca;
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_rclast1[_chnl] = in;
|
||||
m_rchp1[_chnl] = hp;
|
||||
m_rcbp1[_chnl] = bp;
|
||||
}
|
||||
return m_type == Highpass_RC24 ? hp : bp;
|
||||
return m_type == FilterType::Highpass_RC24 ? hp : bp;
|
||||
}
|
||||
|
||||
case Formantfilter:
|
||||
case FastFormant:
|
||||
case FilterType::Formantfilter:
|
||||
case FilterType::FastFormant:
|
||||
{
|
||||
if( qAbs( _in0 ) < 1.0e-10f && qAbs( m_vflast[0][_chnl] ) < 1.0e-10f ) { return 0.0f; } // performance hack - skip processing when the numbers get too small
|
||||
sample_t hp, bp, in;
|
||||
if (std::abs(_in0) < 1.0e-10f && std::abs(m_vflast[0][_chnl]) < 1.0e-10f) { return 0.0f; } // performance hack - skip processing when the numbers get too small
|
||||
|
||||
out = 0;
|
||||
const int os = m_type == FastFormant ? 1 : 4; // no oversampling for fast formant
|
||||
const int os = m_type == FilterType::FastFormant ? 1 : 4; // no oversampling for fast formant
|
||||
for( int o = 0; o < os; ++o )
|
||||
{
|
||||
// first formant
|
||||
in = _in0 + m_vfbp[0][_chnl] * m_vfq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
sample_t in = _in0 + m_vfbp[0][_chnl] * m_vfq;
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
hp = m_vfc[0] * ( m_vfhp[0][_chnl] + in - m_vflast[0][_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
sample_t hp = m_vfc[0] * ( m_vfhp[0][_chnl] + in - m_vflast[0][_chnl] );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_vfb[0] + m_vfbp[0][_chnl] * m_vfa[0];
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
sample_t bp = hp * m_vfb[0] + m_vfbp[0][_chnl] * m_vfa[0];
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_vflast[0][_chnl] = in;
|
||||
m_vfhp[0][_chnl] = hp;
|
||||
m_vfbp[0][_chnl] = bp;
|
||||
|
||||
in = bp + m_vfbp[2][_chnl] * m_vfq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
hp = m_vfc[0] * ( m_vfhp[2][_chnl] + in - m_vflast[2][_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_vfb[0] + m_vfbp[2][_chnl] * m_vfa[0];
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_vflast[2][_chnl] = in;
|
||||
m_vfhp[2][_chnl] = hp;
|
||||
m_vfbp[2][_chnl] = bp;
|
||||
|
||||
in = bp + m_vfbp[4][_chnl] * m_vfq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
hp = m_vfc[0] * ( m_vfhp[4][_chnl] + in - m_vflast[4][_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_vfb[0] + m_vfbp[4][_chnl] * m_vfa[0];
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_vflast[4][_chnl] = in;
|
||||
m_vfhp[4][_chnl] = hp;
|
||||
@@ -649,39 +645,39 @@ public:
|
||||
|
||||
// second formant
|
||||
in = _in0 + m_vfbp[0][_chnl] * m_vfq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
hp = m_vfc[1] * ( m_vfhp[1][_chnl] + in - m_vflast[1][_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_vfb[1] + m_vfbp[1][_chnl] * m_vfa[1];
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_vflast[1][_chnl] = in;
|
||||
m_vfhp[1][_chnl] = hp;
|
||||
m_vfbp[1][_chnl] = bp;
|
||||
|
||||
in = bp + m_vfbp[3][_chnl] * m_vfq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
hp = m_vfc[1] * ( m_vfhp[3][_chnl] + in - m_vflast[3][_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_vfb[1] + m_vfbp[3][_chnl] * m_vfa[1];
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_vflast[3][_chnl] = in;
|
||||
m_vfhp[3][_chnl] = hp;
|
||||
m_vfbp[3][_chnl] = bp;
|
||||
|
||||
in = bp + m_vfbp[5][_chnl] * m_vfq;
|
||||
in = qBound( -1.0f, in, 1.0f );
|
||||
in = std::clamp(in, -1.0f, 1.0f);
|
||||
|
||||
hp = m_vfc[1] * ( m_vfhp[5][_chnl] + in - m_vflast[5][_chnl] );
|
||||
hp = qBound( -1.0f, hp, 1.0f );
|
||||
hp = std::clamp(hp, -1.0f, 1.0f);
|
||||
|
||||
bp = hp * m_vfb[1] + m_vfbp[5][_chnl] * m_vfa[1];
|
||||
bp = qBound( -1.0f, bp, 1.0f );
|
||||
bp = std::clamp(bp, -1.0f, 1.0f);
|
||||
|
||||
m_vflast[5][_chnl] = in;
|
||||
m_vfhp[5][_chnl] = hp;
|
||||
@@ -689,7 +685,7 @@ public:
|
||||
|
||||
out += bp;
|
||||
}
|
||||
return m_type == FastFormant ? out * 2.0f : out * 0.5f;
|
||||
return m_type == FilterType::FastFormant ? out * 2.0f : out * 0.5f;
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -710,16 +706,16 @@ public:
|
||||
inline void calcFilterCoeffs( float _freq, float _q )
|
||||
{
|
||||
// temp coef vars
|
||||
_q = qMax( _q, minQ() );
|
||||
_q = std::max(_q, minQ());
|
||||
|
||||
if( m_type == Lowpass_RC12 ||
|
||||
m_type == Bandpass_RC12 ||
|
||||
m_type == Highpass_RC12 ||
|
||||
m_type == Lowpass_RC24 ||
|
||||
m_type == Bandpass_RC24 ||
|
||||
m_type == Highpass_RC24 )
|
||||
if( m_type == FilterType::Lowpass_RC12 ||
|
||||
m_type == FilterType::Bandpass_RC12 ||
|
||||
m_type == FilterType::Highpass_RC12 ||
|
||||
m_type == FilterType::Lowpass_RC24 ||
|
||||
m_type == FilterType::Bandpass_RC24 ||
|
||||
m_type == FilterType::Highpass_RC24 )
|
||||
{
|
||||
_freq = qBound( 50.0f, _freq, 20000.0f );
|
||||
_freq = std::clamp(_freq, 50.0f, 20000.0f);
|
||||
const float sr = m_sampleRatio * 0.25f;
|
||||
const float f = 1.0f / ( _freq * F_2PI );
|
||||
|
||||
@@ -732,10 +728,10 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_type == Formantfilter ||
|
||||
m_type == FastFormant )
|
||||
if( m_type == FilterType::Formantfilter ||
|
||||
m_type == FilterType::FastFormant )
|
||||
{
|
||||
_freq = qBound( minFreq(), _freq, 20000.0f ); // limit freq and q for not getting bad noise out of the filter...
|
||||
_freq = std::clamp(_freq, minFreq(), 20000.0f); // limit freq and q for not getting bad noise out of the filter...
|
||||
|
||||
// formats for a, e, i, o, u, a
|
||||
static const float _f[6][2] = { { 1000, 1400 }, { 500, 2300 },
|
||||
@@ -758,7 +754,7 @@ public:
|
||||
const float f1 = 1.0f / ( linearInterpolate( _f[vowel+0][1], _f[vowel+1][1], fract ) * F_2PI );
|
||||
|
||||
// samplerate coeff: depends on oversampling
|
||||
const float sr = m_type == FastFormant ? m_sampleRatio : m_sampleRatio * 0.25f;
|
||||
const float sr = m_type == FilterType::FastFormant ? m_sampleRatio : m_sampleRatio * 0.25f;
|
||||
|
||||
m_vfa[0] = 1.0f - sr / ( f0 + sr );
|
||||
m_vfb[0] = 1.0f - m_vfa[0];
|
||||
@@ -769,11 +765,11 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_type == Moog ||
|
||||
m_type == DoubleMoog )
|
||||
if( m_type == FilterType::Moog ||
|
||||
m_type == FilterType::DoubleMoog )
|
||||
{
|
||||
// [ 0 - 0.5 ]
|
||||
const float f = qBound( minFreq(), _freq, 20000.0f ) * m_sampleRatio;
|
||||
const float f = std::clamp(_freq, minFreq(), 20000.0f) * m_sampleRatio;
|
||||
// (Empirical tunning)
|
||||
m_p = ( 3.6f - 3.2f * f ) * f;
|
||||
m_k = 2.0f * m_p - 1;
|
||||
@@ -788,9 +784,9 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_type == Tripole )
|
||||
if( m_type == FilterType::Tripole )
|
||||
{
|
||||
const float f = qBound( 20.0f, _freq, 20000.0f ) * m_sampleRatio * 0.25f;
|
||||
const float f = std::clamp(_freq, 20.0f, 20000.0f) * m_sampleRatio * 0.25f;
|
||||
|
||||
m_p = ( 3.6f - 3.2f * f ) * f;
|
||||
m_k = 2.0f * m_p - 1.0f;
|
||||
@@ -799,20 +795,20 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_type == Lowpass_SV ||
|
||||
m_type == Bandpass_SV ||
|
||||
m_type == Highpass_SV ||
|
||||
m_type == Notch_SV )
|
||||
if( m_type == FilterType::Lowpass_SV ||
|
||||
m_type == FilterType::Bandpass_SV ||
|
||||
m_type == FilterType::Highpass_SV ||
|
||||
m_type == FilterType::Notch_SV )
|
||||
{
|
||||
const float f = sinf( qMax( minFreq(), _freq ) * m_sampleRatio * F_PI );
|
||||
m_svf1 = qMin( f, 0.825f );
|
||||
m_svf2 = qMin( f * 2.0f, 0.825f );
|
||||
m_svq = qMax( 0.0001f, 2.0f - ( _q * 0.1995f ) );
|
||||
const float f = sinf(std::max(minFreq(), _freq) * m_sampleRatio * F_PI);
|
||||
m_svf1 = std::min(f, 0.825f);
|
||||
m_svf2 = std::min(f * 2.0f, 0.825f);
|
||||
m_svq = std::max(0.0001f, 2.0f - (_q * 0.1995f));
|
||||
return;
|
||||
}
|
||||
|
||||
// other filters
|
||||
_freq = qBound( minFreq(), _freq, 20000.0f );
|
||||
_freq = std::clamp(_freq, minFreq(), 20000.0f);
|
||||
const float omega = F_2PI * _freq * m_sampleRatio;
|
||||
const float tsin = sinf( omega ) * 0.5f;
|
||||
const float tcos = cosf( omega );
|
||||
@@ -826,38 +822,38 @@ public:
|
||||
|
||||
switch( m_type )
|
||||
{
|
||||
case LowPass:
|
||||
case FilterType::LowPass:
|
||||
{
|
||||
const float b1 = ( 1.0f - tcos ) * a0;
|
||||
const float b0 = b1 * 0.5f;
|
||||
m_biQuad.setCoeffs( a1, a2, b0, b1, b0 );
|
||||
break;
|
||||
}
|
||||
case HiPass:
|
||||
case FilterType::HiPass:
|
||||
{
|
||||
const float b1 = ( -1.0f - tcos ) * a0;
|
||||
const float b0 = b1 * -0.5f;
|
||||
m_biQuad.setCoeffs( a1, a2, b0, b1, b0 );
|
||||
break;
|
||||
}
|
||||
case BandPass_CSG:
|
||||
case FilterType::BandPass_CSG:
|
||||
{
|
||||
const float b0 = tsin * a0;
|
||||
m_biQuad.setCoeffs( a1, a2, b0, 0.0f, -b0 );
|
||||
break;
|
||||
}
|
||||
case BandPass_CZPG:
|
||||
case FilterType::BandPass_CZPG:
|
||||
{
|
||||
const float b0 = alpha * a0;
|
||||
m_biQuad.setCoeffs( a1, a2, b0, 0.0f, -b0 );
|
||||
break;
|
||||
}
|
||||
case Notch:
|
||||
case FilterType::Notch:
|
||||
{
|
||||
m_biQuad.setCoeffs( a1, a2, a0, a1, a0 );
|
||||
break;
|
||||
}
|
||||
case AllPass:
|
||||
case FilterType::AllPass:
|
||||
{
|
||||
m_biQuad.setCoeffs( a1, a2, a2, a1, 1.0f );
|
||||
break;
|
||||
@@ -906,7 +902,7 @@ private:
|
||||
// in/out history for Lowpass_SV (state-variant lowpass)
|
||||
frame m_delay1, m_delay2, m_delay3, m_delay4;
|
||||
|
||||
FilterTypes m_type;
|
||||
FilterType m_type;
|
||||
bool m_doubleFilter;
|
||||
|
||||
float m_sampleRate;
|
||||
@@ -918,4 +914,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_BASIC_FILTERS_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BUFFER_MANAGER_H
|
||||
#define BUFFER_MANAGER_H
|
||||
#ifndef LMMS_BUFFER_MANAGER_H
|
||||
#define LMMS_BUFFER_MANAGER_H
|
||||
|
||||
#include "lmms_export.h"
|
||||
#include "lmms_basics.h"
|
||||
@@ -54,4 +54,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_BUFFER_MANAGER_H
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_GUI_CPU_LOAD_WIDGET_H
|
||||
#define LMMS_GUI_CPU_LOAD_WIDGET_H
|
||||
|
||||
#ifndef CPULOAD_WIDGET_H
|
||||
#define CPULOAD_WIDGET_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <QTimer>
|
||||
#include <QPixmap>
|
||||
#include <QWidget>
|
||||
@@ -41,6 +41,7 @@ namespace lmms::gui
|
||||
class CPULoadWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int stepSize MEMBER m_stepSize)
|
||||
public:
|
||||
CPULoadWidget( QWidget * _parent );
|
||||
~CPULoadWidget() override = default;
|
||||
@@ -55,6 +56,8 @@ protected slots:
|
||||
|
||||
|
||||
private:
|
||||
int stepSize() const { return std::max(1, m_stepSize); }
|
||||
|
||||
int m_currentLoad;
|
||||
|
||||
QPixmap m_temp;
|
||||
@@ -65,9 +68,11 @@ private:
|
||||
|
||||
QTimer m_updateTimer;
|
||||
|
||||
int m_stepSize = 1;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_CPU_LOAD_WIDGET_H
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CAPTION_MENU_H
|
||||
#define CAPTION_MENU_H
|
||||
#ifndef LMMS_GUI_CAPTION_MENU_H
|
||||
#define LMMS_GUI_CAPTION_MENU_H
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
@@ -47,4 +46,4 @@ public:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_CAPTION_MENU_H
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRACK_CONTENT_OBJECT_H
|
||||
#define TRACK_CONTENT_OBJECT_H
|
||||
#ifndef LMMS_CLIP_H
|
||||
#define LMMS_CLIP_H
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <QColor>
|
||||
|
||||
@@ -48,7 +50,6 @@ class TrackView;
|
||||
class LMMS_EXPORT Clip : public Model, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
MM_OPERATORS
|
||||
mapPropertyFromModel(bool,isMuted,setMuted,m_mutedModel);
|
||||
mapPropertyFromModel(bool,isSolo,setSolo,m_soloModel);
|
||||
public:
|
||||
@@ -109,24 +110,8 @@ public:
|
||||
return m_autoResize;
|
||||
}
|
||||
|
||||
QColor color() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void setColor( const QColor & c )
|
||||
{
|
||||
m_color = c;
|
||||
}
|
||||
|
||||
bool hasColor();
|
||||
|
||||
void useCustomClipColor( bool b );
|
||||
|
||||
bool usesCustomClipColor()
|
||||
{
|
||||
return m_useCustomClipColor;
|
||||
}
|
||||
auto color() const -> const std::optional<QColor>& { return m_color; }
|
||||
void setColor(const std::optional<QColor>& color);
|
||||
|
||||
virtual void movePosition( const TimePos & pos );
|
||||
virtual void changeLength( const TimePos & length );
|
||||
@@ -164,13 +149,6 @@ signals:
|
||||
|
||||
|
||||
private:
|
||||
enum Actions
|
||||
{
|
||||
NoAction,
|
||||
Move,
|
||||
Resize
|
||||
} ;
|
||||
|
||||
Track * m_track;
|
||||
QString m_name;
|
||||
|
||||
@@ -184,8 +162,7 @@ private:
|
||||
|
||||
bool m_selectViewOnCreate;
|
||||
|
||||
QColor m_color;
|
||||
bool m_useCustomClipColor;
|
||||
std::optional<QColor> m_color;
|
||||
|
||||
friend class ClipView;
|
||||
|
||||
@@ -194,4 +171,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_CLIP_H
|
||||
|
||||
@@ -22,9 +22,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRACK_CONTENT_OBJECT_VIEW_H
|
||||
#define TRACK_CONTENT_OBJECT_VIEW_H
|
||||
#ifndef LMMS_GUI_CLIP_VIEW_H
|
||||
#define LMMS_GUI_CLIP_VIEW_H
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <QVector>
|
||||
|
||||
@@ -140,7 +141,7 @@ public slots:
|
||||
void resetColor();
|
||||
|
||||
protected:
|
||||
enum ContextMenuAction
|
||||
enum class ContextMenuAction
|
||||
{
|
||||
Remove,
|
||||
Cut,
|
||||
@@ -184,6 +185,7 @@ protected:
|
||||
|
||||
virtual void paintTextLabel(QString const & text, QPainter & painter);
|
||||
|
||||
auto hasCustomColor() const -> bool;
|
||||
|
||||
protected slots:
|
||||
void updateLength();
|
||||
@@ -191,9 +193,9 @@ protected slots:
|
||||
|
||||
|
||||
private:
|
||||
enum Actions
|
||||
enum class Action
|
||||
{
|
||||
NoAction,
|
||||
None,
|
||||
Move,
|
||||
MoveSelection,
|
||||
Resize,
|
||||
@@ -206,7 +208,7 @@ private:
|
||||
static TextFloat * s_textFloat;
|
||||
|
||||
Clip * m_clip;
|
||||
Actions m_action;
|
||||
Action m_action;
|
||||
QPoint m_initialMousePos;
|
||||
QPoint m_initialMouseGlobalPos;
|
||||
QVector<TimePos> m_initialOffsets;
|
||||
@@ -241,7 +243,7 @@ private:
|
||||
bool mouseMovedDistance( QMouseEvent * me, int distance );
|
||||
TimePos draggedClipPos( QMouseEvent * me );
|
||||
int knifeMarkerPos( QMouseEvent * me );
|
||||
void setColor(const QColor* color);
|
||||
void setColor(const std::optional<QColor>& color);
|
||||
//! Return true iff the clip could be split. Currently only implemented for samples
|
||||
virtual bool splitClip( const TimePos pos ){ return false; };
|
||||
void updateCursor(QMouseEvent * me);
|
||||
@@ -252,4 +254,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_CLIP_VIEW_H
|
||||
|
||||
@@ -22,11 +22,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CLIPBOARD_H
|
||||
#define CLIPBOARD_H
|
||||
#ifndef LMMS_CLIPBOARD_H
|
||||
#define LMMS_CLIPBOARD_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QDomElement>
|
||||
#include <QMap>
|
||||
|
||||
#include "lmms_export.h"
|
||||
|
||||
class QMimeData;
|
||||
|
||||
@@ -44,7 +46,7 @@ namespace lmms::Clipboard
|
||||
bool hasFormat( MimeType mT );
|
||||
|
||||
// Helper methods for String data
|
||||
void copyString( const QString & str, MimeType mT );
|
||||
void LMMS_EXPORT copyString(const QString& str, MimeType mT);
|
||||
QString getString( MimeType mT );
|
||||
|
||||
// Helper methods for String Pair data
|
||||
@@ -68,4 +70,4 @@ namespace lmms::Clipboard
|
||||
|
||||
} // namespace lmms::Clipboard
|
||||
|
||||
#endif
|
||||
#endif // LMMS_CLIPBOARD_H
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COLOR_CHOOSER_H
|
||||
#define COLOR_CHOOSER_H
|
||||
#ifndef LMMS_GUI_COLOR_CHOOSER_H
|
||||
#define LMMS_GUI_COLOR_CHOOSER_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <QColor>
|
||||
@@ -34,7 +34,7 @@ namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
class ColorChooser: public QColorDialog
|
||||
class ColorChooser : public QColorDialog
|
||||
{
|
||||
public:
|
||||
ColorChooser(const QColor &initial, QWidget *parent): QColorDialog(initial, parent) {};
|
||||
@@ -68,5 +68,4 @@ private:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LMMS_GUI_COLOR_CHOOSER_H
|
||||
|
||||
54
include/ColorHelper.h
Normal file
54
include/ColorHelper.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* ColorHelper.h - Helper methods for color related algorithms, etc.
|
||||
*
|
||||
* Copyright (c) 2024- Michael Gregorius
|
||||
*
|
||||
* 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 LMMS_GUI_COLOR_HELPER_H
|
||||
#define LMMS_GUI_COLOR_HELPER_H
|
||||
|
||||
#include <QColor>
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class ColorHelper
|
||||
{
|
||||
public:
|
||||
static QColor interpolateInRgb(const QColor& a, const QColor& b, float t)
|
||||
{
|
||||
qreal ar, ag, ab, aa;
|
||||
a.getRgbF(&ar, &ag, &ab, &aa);
|
||||
|
||||
qreal br, bg, bb, ba;
|
||||
b.getRgbF(&br, &bg, &bb, &ba);
|
||||
|
||||
const float interH = lerp(ar, br, t);
|
||||
const float interS = lerp(ag, bg, t);
|
||||
const float interV = lerp(ab, bb, t);
|
||||
const float interA = lerp(aa, ba, t);
|
||||
|
||||
return QColor::fromRgbF(interH, interS, interV, interA);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_COLOR_HELPER_H
|
||||
@@ -22,9 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef COMBOBOX_H
|
||||
#define COMBOBOX_H
|
||||
#ifndef LMMS_GUI_COMBOBOX_H
|
||||
#define LMMS_GUI_COMBOBOX_H
|
||||
|
||||
#include <QMenu>
|
||||
#include <QWidget>
|
||||
@@ -67,9 +66,9 @@ protected:
|
||||
|
||||
|
||||
private:
|
||||
static QPixmap* s_background;
|
||||
static QPixmap* s_arrow;
|
||||
static QPixmap* s_arrowSelected;
|
||||
QPixmap m_background = embed::getIconPixmap("combobox_bg");
|
||||
QPixmap m_arrow = embed::getIconPixmap("combobox_arrow");
|
||||
QPixmap m_arrowSelected = embed::getIconPixmap("combobox_arrow_selected");
|
||||
|
||||
QMenu m_menu;
|
||||
|
||||
@@ -83,4 +82,4 @@ private slots:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_COMBOBOX_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMBOBOX_MODEL_H
|
||||
#define COMBOBOX_MODEL_H
|
||||
#ifndef LMMS_COMBOBOX_MODEL_H
|
||||
#define LMMS_COMBOBOX_MODEL_H
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
@@ -72,12 +72,12 @@ public:
|
||||
|
||||
const QString & itemText( int i ) const
|
||||
{
|
||||
return m_items[qBound<int>( minValue(), i, maxValue() )].first;
|
||||
return m_items[std::clamp(i, minValue(), maxValue())].first;
|
||||
}
|
||||
|
||||
const PixmapLoader* itemPixmap( int i ) const
|
||||
{
|
||||
return m_items[qBound<int>( minValue(), i, maxValue() )].second.get();
|
||||
return m_items[std::clamp(i, minValue(), maxValue())].second.get();
|
||||
}
|
||||
|
||||
int size() const
|
||||
@@ -95,4 +95,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_COMBOBOX_MODEL_H
|
||||
|
||||
@@ -22,18 +22,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CONFIG_MGR_H
|
||||
#define CONFIG_MGR_H
|
||||
#ifndef LMMS_CONFIG_MANAGER_H
|
||||
#define LMMS_CONFIG_MANAGER_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QPair>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
#include <QObject>
|
||||
|
||||
#include <vector>
|
||||
#include "lmms_export.h"
|
||||
|
||||
|
||||
@@ -240,11 +239,8 @@ public:
|
||||
|
||||
void addRecentlyOpenedProject(const QString & _file);
|
||||
|
||||
const QString & value(const QString & cls,
|
||||
const QString & attribute) const;
|
||||
const QString & value(const QString & cls,
|
||||
const QString & attribute,
|
||||
const QString & defaultVal) const;
|
||||
QString value(const QString& cls, const QString& attribute, const QString& defaultVal = "") const;
|
||||
|
||||
void setValue(const QString & cls, const QString & attribute,
|
||||
const QString & value);
|
||||
void deleteValue(const QString & cls, const QString & attribute);
|
||||
@@ -303,7 +299,7 @@ private:
|
||||
unsigned int m_configVersion;
|
||||
QStringList m_recentlyOpenedProjects;
|
||||
|
||||
using stringPairVector = QVector<QPair<QString, QString>>;
|
||||
using stringPairVector = std::vector<QPair<QString, QString>>;
|
||||
using settingsMap = QMap<QString, stringPairVector>;
|
||||
settingsMap m_settings;
|
||||
|
||||
@@ -314,4 +310,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_CONFIG_MANAGER_H
|
||||
|
||||
@@ -70,8 +70,8 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONTROLLAYOUT_H
|
||||
#define CONTROLLAYOUT_H
|
||||
#ifndef LMMS_GUI_CONTROL_LAYOUT_H
|
||||
#define LMMS_GUI_CONTROL_LAYOUT_H
|
||||
|
||||
#include <QLayout>
|
||||
#include <QMultiMap>
|
||||
@@ -141,4 +141,4 @@ private:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // CONTROLLAYOUT_H
|
||||
#endif // LMMS_GUI_CONTROL_LAYOUT_H
|
||||
|
||||
@@ -23,9 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CONTROLLER_H
|
||||
#define CONTROLLER_H
|
||||
#ifndef LMMS_CONTROLLER_H
|
||||
#define LMMS_CONTROLLER_H
|
||||
|
||||
#include "lmms_export.h"
|
||||
#include "Engine.h"
|
||||
@@ -46,26 +45,25 @@ class ControllerDialog;
|
||||
|
||||
} // namespace gui
|
||||
|
||||
using ControllerVector = QVector<Controller*>;
|
||||
using ControllerVector = std::vector<Controller*>;
|
||||
|
||||
class LMMS_EXPORT Controller : public Model, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ControllerTypes
|
||||
enum class ControllerType
|
||||
{
|
||||
DummyController,
|
||||
LfoController,
|
||||
MidiController,
|
||||
PeakController,
|
||||
Dummy,
|
||||
Lfo,
|
||||
Midi,
|
||||
Peak,
|
||||
/*
|
||||
XYController,
|
||||
EquationController
|
||||
XY,
|
||||
Equation
|
||||
*/
|
||||
NumControllerTypes
|
||||
} ;
|
||||
|
||||
Controller( ControllerTypes _type, Model * _parent,
|
||||
Controller( ControllerType _type, Model * _parent,
|
||||
const QString & _display_name );
|
||||
|
||||
~Controller() override;
|
||||
@@ -84,7 +82,7 @@ public:
|
||||
m_sampleExact = _exact;
|
||||
}
|
||||
|
||||
inline ControllerTypes type() const
|
||||
inline ControllerType type() const
|
||||
{
|
||||
return( m_type );
|
||||
}
|
||||
@@ -95,8 +93,8 @@ public:
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case LfoController: return( true );
|
||||
case PeakController: return( true );
|
||||
case ControllerType::Lfo: return( true );
|
||||
case ControllerType::Peak: return( true );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -113,13 +111,13 @@ public:
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
QString nodeName() const override;
|
||||
|
||||
static Controller * create( ControllerTypes _tt, Model * _parent );
|
||||
static Controller * create( ControllerType _tt, Model * _parent );
|
||||
static Controller * create( const QDomElement & _this,
|
||||
Model * _parent );
|
||||
|
||||
inline static float fittedValue( float _val )
|
||||
{
|
||||
return qBound<float>( 0.0f, _val, 1.0f );
|
||||
return std::clamp(_val, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
static long runningPeriods()
|
||||
@@ -166,7 +164,7 @@ protected:
|
||||
int m_connectionCount;
|
||||
|
||||
QString m_name;
|
||||
ControllerTypes m_type;
|
||||
ControllerType m_type;
|
||||
|
||||
static ControllerVector s_controllers;
|
||||
|
||||
@@ -184,5 +182,4 @@ signals:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LMMS_CONTROLLER_H
|
||||
|
||||
@@ -26,17 +26,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CONTROLLER_CONNECTION_H
|
||||
#define CONTROLLER_CONNECTION_H
|
||||
#ifndef LMMS_CONTROLLER_CONNECTION_H
|
||||
#define LMMS_CONTROLLER_CONNECTION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
#include "Controller.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "ValueBuffer.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace gui
|
||||
class ControllerConnectionDialog;
|
||||
}
|
||||
|
||||
using ControllerConnectionVector = QVector<ControllerConnection*>;
|
||||
using ControllerConnectionVector = std::vector<ControllerConnection*>;
|
||||
|
||||
class LMMS_EXPORT ControllerConnection : public QObject, public JournallingObject
|
||||
{
|
||||
@@ -128,5 +128,4 @@ signals:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LMMS_CONTROLLER_CONNECTION_H
|
||||
|
||||
@@ -23,9 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CONTROLLER_CONNECTION_DIALOG_H
|
||||
#define CONTROLLER_CONNECTION_DIALOG_H
|
||||
#ifndef LMMS_GUI_CONTROLLER_CONNECTION_DIALOG_H
|
||||
#define LMMS_GUI_CONTROLLER_CONNECTION_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QSortFilterProxyModel>
|
||||
@@ -111,4 +110,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_CONTROLLER_CONNECTION_DIALOG_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_DIALOG_H
|
||||
#define CONTROLLER_DIALOG_H
|
||||
#ifndef LMMS_GUI_CONTROLLER_DIALOG_H
|
||||
#define LMMS_GUI_CONTROLLER_DIALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
@@ -61,4 +61,4 @@ protected:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_CONTROLLER_DIALOG_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_RACK_VIEW_H
|
||||
#define CONTROLLER_RACK_VIEW_H
|
||||
#ifndef LMMS_GUI_CONTROLLER_RACK_VIEW_H
|
||||
#define LMMS_GUI_CONTROLLER_RACK_VIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QCloseEvent>
|
||||
@@ -92,4 +92,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_CONTROLLER_RACK_VIEW_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_VIEW_H
|
||||
#define CONTROLLER_VIEW_H
|
||||
#ifndef LMMS_GUI_CONTROLLER_VIEW_H
|
||||
#define LMMS_GUI_CONTROLLER_VIEW_H
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
@@ -88,4 +88,4 @@ private:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_CONTROLLER_VIEW_H
|
||||
|
||||
@@ -22,10 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONTROLS_H
|
||||
#define CONTROLS_H
|
||||
|
||||
|
||||
#ifndef LMMS_GUI_CONTROLS_H
|
||||
#define LMMS_GUI_CONTROLS_H
|
||||
|
||||
// headers only required for covariance
|
||||
#include "AutomatableModel.h"
|
||||
@@ -146,4 +144,4 @@ public:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // CONTROLS_H
|
||||
#endif // LMMS_GUI_CONTROLS_H
|
||||
|
||||
@@ -1,6 +1,29 @@
|
||||
/* Text customizable knob */
|
||||
#ifndef CUSTOM_TEXT_KNOB_H
|
||||
#define CUSTOM_TEXT_KNOB_H
|
||||
/*
|
||||
* CustomTextKnob.h
|
||||
*
|
||||
* Copyright (c) 2020 Ibuki Sugiyama <main/at/fuwa.dev>
|
||||
*
|
||||
* 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 LMMS_GUI_CUSTOM_TEXT_KNOB_H
|
||||
#define LMMS_GUI_CUSTOM_TEXT_KNOB_H
|
||||
|
||||
#include "Knob.h"
|
||||
|
||||
@@ -13,7 +36,7 @@ class LMMS_EXPORT CustomTextKnob : public Knob
|
||||
protected:
|
||||
inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible
|
||||
public:
|
||||
CustomTextKnob( knobTypes _knob_num, QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() );
|
||||
CustomTextKnob( KnobType _knob_num, QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() );
|
||||
|
||||
CustomTextKnob( QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() ); //!< default ctor
|
||||
|
||||
@@ -34,4 +57,4 @@ protected:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_CUSTOM_TEXT_KNOB_H
|
||||
|
||||
@@ -23,15 +23,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DATA_FILE_H
|
||||
#define DATA_FILE_H
|
||||
#ifndef LMMS_DATA_FILE_H
|
||||
#define LMMS_DATA_FILE_H
|
||||
|
||||
#include <map>
|
||||
#include <QDomDocument>
|
||||
#include <vector>
|
||||
|
||||
#include "lmms_export.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class QTextStream;
|
||||
|
||||
@@ -43,14 +42,13 @@ class ProjectVersion;
|
||||
|
||||
class LMMS_EXPORT DataFile : public QDomDocument
|
||||
{
|
||||
MM_OPERATORS
|
||||
|
||||
using UpgradeMethod = void(DataFile::*)();
|
||||
|
||||
public:
|
||||
enum Types
|
||||
enum class Type
|
||||
{
|
||||
UnknownType,
|
||||
Unknown,
|
||||
SongProject,
|
||||
SongProjectTemplate,
|
||||
InstrumentTrackSettings,
|
||||
@@ -58,10 +56,8 @@ public:
|
||||
ClipboardData,
|
||||
JournalData,
|
||||
EffectSettings,
|
||||
MidiClip,
|
||||
TypeCount
|
||||
MidiClip
|
||||
} ;
|
||||
using Type = Types;
|
||||
|
||||
DataFile( const QString& fileName );
|
||||
DataFile( const QByteArray& data );
|
||||
@@ -129,6 +125,11 @@ private:
|
||||
void upgrade_defaultTripleOscillatorHQ();
|
||||
void upgrade_mixerRename();
|
||||
void upgrade_bbTcoRename();
|
||||
void upgrade_sampleAndHold();
|
||||
void upgrade_midiCCIndexing();
|
||||
void upgrade_loopsRename();
|
||||
void upgrade_noteTypes();
|
||||
void upgrade_fixCMTDelays();
|
||||
|
||||
// List of all upgrade methods
|
||||
static const std::vector<UpgradeMethod> UPGRADE_METHODS;
|
||||
@@ -148,10 +149,9 @@ private:
|
||||
QDomElement m_head;
|
||||
Type m_type;
|
||||
unsigned int m_fileVersion;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_DATA_FILE_H
|
||||
|
||||
@@ -22,15 +22,13 @@
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DELAY_H
|
||||
#define DELAY_H
|
||||
|
||||
#ifndef LMMS_DELAY_H
|
||||
#define LMMS_DELAY_H
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "lmms_math.h"
|
||||
#include "interpolation.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
@@ -75,20 +73,20 @@ public:
|
||||
m_delay( 0 ),
|
||||
m_fraction( 0.0 )
|
||||
{
|
||||
m_buffer = MM_ALLOC<frame>(maxDelay );
|
||||
m_buffer = new frame[maxDelay];
|
||||
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
|
||||
}
|
||||
virtual ~CombFeedback()
|
||||
{
|
||||
MM_FREE( m_buffer );
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
inline void setMaxDelay( int maxDelay )
|
||||
{
|
||||
if( maxDelay > m_size )
|
||||
{
|
||||
MM_FREE( m_buffer );
|
||||
m_buffer = MM_ALLOC<frame>( maxDelay );
|
||||
delete[] m_buffer;
|
||||
m_buffer = new frame[maxDelay];
|
||||
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
|
||||
}
|
||||
m_size = maxDelay;
|
||||
@@ -146,20 +144,20 @@ class CombFeedfwd
|
||||
m_delay( 0 ),
|
||||
m_fraction( 0.0 )
|
||||
{
|
||||
m_buffer = MM_ALLOC<frame>( maxDelay );
|
||||
m_buffer = new frame[maxDelay];
|
||||
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
|
||||
}
|
||||
virtual ~CombFeedfwd()
|
||||
{
|
||||
MM_FREE( m_buffer );
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
inline void setMaxDelay( int maxDelay )
|
||||
{
|
||||
if( maxDelay > m_size )
|
||||
{
|
||||
MM_FREE( m_buffer );
|
||||
m_buffer = MM_ALLOC<frame>( maxDelay );
|
||||
delete[] m_buffer;
|
||||
m_buffer = new frame[maxDelay];
|
||||
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
|
||||
}
|
||||
m_size = maxDelay;
|
||||
@@ -217,20 +215,20 @@ class CombFeedbackDualtap
|
||||
m_delay( 0 ),
|
||||
m_fraction( 0.0 )
|
||||
{
|
||||
m_buffer = MM_ALLOC<frame>( maxDelay );
|
||||
m_buffer = new frame[maxDelay];
|
||||
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
|
||||
}
|
||||
virtual ~CombFeedbackDualtap()
|
||||
{
|
||||
MM_FREE( m_buffer );
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
inline void setMaxDelay( int maxDelay )
|
||||
{
|
||||
if( maxDelay > m_size )
|
||||
{
|
||||
MM_FREE( m_buffer );
|
||||
m_buffer = MM_ALLOC<frame>( maxDelay );
|
||||
delete[] m_buffer;
|
||||
m_buffer = new frame[maxDelay];
|
||||
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
|
||||
}
|
||||
m_size = maxDelay;
|
||||
@@ -298,20 +296,20 @@ public:
|
||||
m_delay( 0 ),
|
||||
m_fraction( 0.0 )
|
||||
{
|
||||
m_buffer = MM_ALLOC<frame>( maxDelay );
|
||||
m_buffer = new frame[maxDelay];
|
||||
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
|
||||
}
|
||||
virtual ~AllpassDelay()
|
||||
{
|
||||
MM_FREE( m_buffer );
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
inline void setMaxDelay( int maxDelay )
|
||||
{
|
||||
if( maxDelay > m_size )
|
||||
{
|
||||
MM_FREE( m_buffer );
|
||||
m_buffer = MM_ALLOC<frame>( maxDelay );
|
||||
delete[] m_buffer;
|
||||
m_buffer = new frame[maxDelay];
|
||||
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
|
||||
}
|
||||
m_size = maxDelay;
|
||||
@@ -365,4 +363,4 @@ using StereoAllpassDelay = AllpassDelay<2>;
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_DELAY_H
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DEPRECATIONHELPER_H
|
||||
#define DEPRECATIONHELPER_H
|
||||
#ifndef LMMS_DEPRECATIONHELPER_H
|
||||
#define LMMS_DEPRECATIONHELPER_H
|
||||
|
||||
#include <QFontMetrics>
|
||||
#include <QWheelEvent>
|
||||
@@ -66,4 +66,4 @@ inline QPoint position(QWheelEvent *wheelEvent)
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // DEPRECATIONHELPER_H
|
||||
#endif // LMMS_DEPRECATIONHELPER_H
|
||||
|
||||
@@ -23,11 +23,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DETUNING_HELPER_H
|
||||
#define DETUNING_HELPER_H
|
||||
#ifndef LMMS_DETUNING_HELPER_H
|
||||
#define LMMS_DETUNING_HELPER_H
|
||||
|
||||
#include "InlineAutomation.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
@@ -35,7 +34,6 @@ namespace lmms
|
||||
class DetuningHelper : public InlineAutomation
|
||||
{
|
||||
Q_OBJECT
|
||||
MM_OPERATORS
|
||||
public:
|
||||
DetuningHelper() :
|
||||
InlineAutomation()
|
||||
@@ -64,4 +62,4 @@ public:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_DETUNING_HELPER_H
|
||||
|
||||
@@ -23,9 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DRUMSYNTH_H
|
||||
#define DRUMSYNTH_H
|
||||
#ifndef LMMS_DRUM_SYNTH_H
|
||||
#define LMMS_DRUM_SYNTH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lmms_basics.h"
|
||||
@@ -57,4 +56,4 @@ class DrumSynth {
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // DRUMSYNTH_H
|
||||
#endif // LMMS_DRUM_SYNTH_H
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DSP_EFFECT_LIBRARY_H
|
||||
#define DSP_EFFECT_LIBRARY_H
|
||||
#ifndef LMMS_DSPEFFECTLIBRARY_H
|
||||
#define LMMS_DSPEFFECTLIBRARY_H
|
||||
|
||||
#include "lmms_math.h"
|
||||
#include "lmms_constants.h"
|
||||
@@ -188,7 +187,7 @@ namespace lmms::DspEffectLibrary
|
||||
template<typename sample_t>
|
||||
inline sample_t saturate( sample_t x )
|
||||
{
|
||||
return qMin<sample_t>( qMax<sample_t>( -1.0f, x ), 1.0f );
|
||||
return std::min<sample_t>(std::max<sample_t>(-1.0f, x), 1.0f);
|
||||
}
|
||||
|
||||
|
||||
@@ -199,7 +198,7 @@ namespace lmms::DspEffectLibrary
|
||||
const sample_t _gain,
|
||||
const sample_t _ratio,
|
||||
const FastBassBoost & _orig = FastBassBoost() ) :
|
||||
m_frequency( qMax<sample_t>( _frequency, 10.0 ) ),
|
||||
m_frequency(std::max<sample_t>(_frequency, 10.0)),
|
||||
m_gain1( 1.0 / ( m_frequency + 1.0 ) ),
|
||||
m_gain2( _gain ),
|
||||
m_ratio( _ratio ),
|
||||
@@ -331,5 +330,4 @@ namespace lmms::DspEffectLibrary
|
||||
|
||||
} // namespace lmms::DspEffectLibrary
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_DSPEFFECTLIBRARY_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DUMMY_EFFECT_H
|
||||
#define DUMMY_EFFECT_H
|
||||
#ifndef LMMS_DUMMY_EFFECT_H
|
||||
#define LMMS_DUMMY_EFFECT_H
|
||||
|
||||
#include <QDomElement>
|
||||
|
||||
@@ -149,4 +149,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_DUMMY_EFFECT_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DUMMY_INSTRUMENT_H
|
||||
#define DUMMY_INSTRUMENT_H
|
||||
#ifndef LMMS_DUMMY_INSTRUMENT_H
|
||||
#define LMMS_DUMMY_INSTRUMENT_H
|
||||
|
||||
#include "Instrument.h"
|
||||
#include "InstrumentView.h"
|
||||
@@ -77,4 +77,4 @@ public:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_DUMMY_INSTRUMENT_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DUMMY_PLUGIN_H
|
||||
#define DUMMY_PLUGIN_H
|
||||
#ifndef LMMS_DUMMY_PLUGIN_H
|
||||
#define LMMS_DUMMY_PLUGIN_H
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "PluginView.h"
|
||||
@@ -68,4 +68,4 @@ protected:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_DUMMY_PLUGIN_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EDITOR_COMMON_H
|
||||
#define EDITOR_COMMON_H
|
||||
#ifndef LMMS_GUI_EDITOR_H
|
||||
#define LMMS_GUI_EDITOR_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QToolBar>
|
||||
@@ -113,4 +113,4 @@ protected:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_EDITOR_H
|
||||
|
||||
@@ -23,15 +23,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_H
|
||||
#define EFFECT_H
|
||||
#ifndef LMMS_EFFECT_H
|
||||
#define LMMS_EFFECT_H
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "Engine.h"
|
||||
#include "AudioEngine.h"
|
||||
#include "AutomatableModel.h"
|
||||
#include "TempoSyncKnobModel.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
@@ -49,7 +48,6 @@ class EffectView;
|
||||
|
||||
class LMMS_EXPORT Effect : public Plugin
|
||||
{
|
||||
MM_OPERATORS
|
||||
Q_OBJECT
|
||||
public:
|
||||
Effect( const Plugin::Descriptor * _desc,
|
||||
@@ -157,6 +155,11 @@ public:
|
||||
{
|
||||
m_noRun = _state;
|
||||
}
|
||||
|
||||
inline TempoSyncKnobModel* autoQuitModel()
|
||||
{
|
||||
return &m_autoQuitModel;
|
||||
}
|
||||
|
||||
EffectChain * effectChain() const
|
||||
{
|
||||
@@ -241,4 +244,4 @@ using EffectKeyList = Effect::Descriptor::SubPluginFeatures::KeyList;
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_EFFECT_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_CHAIN_H
|
||||
#define EFFECT_CHAIN_H
|
||||
#ifndef LMMS_EFFECT_CHAIN_H
|
||||
#define LMMS_EFFECT_CHAIN_H
|
||||
|
||||
#include "Model.h"
|
||||
#include "SerializingObject.h"
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
using EffectList = QVector<Effect*>;
|
||||
using EffectList = std::vector<Effect*>;
|
||||
EffectList m_effects;
|
||||
|
||||
BoolModel m_enabledModel;
|
||||
@@ -85,5 +85,4 @@ signals:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LMMS_EFFECT_CHAIN_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_CONTROL_DIALOG_H
|
||||
#define EFFECT_CONTROL_DIALOG_H
|
||||
#ifndef LMMS_GUI_EFFECT_CONTROL_DIALOG_H
|
||||
#define LMMS_GUI_EFFECT_CONTROL_DIALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
@@ -64,4 +64,4 @@ protected:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_EFFECT_CONTROL_DIALOG_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_CONTROLS_H
|
||||
#define EFFECT_CONTROLS_H
|
||||
#ifndef LMMS_EFFECT_CONTROLS_H
|
||||
#define LMMS_EFFECT_CONTROLS_H
|
||||
|
||||
#include "Model.h"
|
||||
#include "JournallingObject.h"
|
||||
@@ -82,4 +82,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_EFFECT_CONTROLS_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_RACK_VIEW_H
|
||||
#define EFFECT_RACK_VIEW_H
|
||||
#ifndef LMMS_GUI_EFFECT_RACK_VIEW_H
|
||||
#define LMMS_GUI_EFFECT_RACK_VIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
@@ -88,4 +88,4 @@ private:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_EFFECT_RACK_VIEW_H
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* EffectSelectDialog.h - dialog to choose effect plugin
|
||||
*
|
||||
* Copyright (c) 2006-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2023 Lost Robot <r94231/at/gmail.com>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
@@ -22,53 +23,98 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_SELECT_DIALOG_H
|
||||
#define EFFECT_SELECT_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStandardItemModel>
|
||||
#ifndef LMMS_GUI_EFFECT_SELECT_DIALOG_H
|
||||
#define LMMS_GUI_EFFECT_SELECT_DIALOG_H
|
||||
|
||||
#include "Effect.h"
|
||||
|
||||
|
||||
namespace Ui { class EffectSelectDialog; }
|
||||
#include <QDialog>
|
||||
#include <QHeaderView>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
#include <QRegularExpression>
|
||||
#include <QScrollArea>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTableView>
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class DualColumnFilterProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DualColumnFilterProxyModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void setEffectTypeFilter(const QString& filter)
|
||||
{
|
||||
m_effectTypeFilter = filter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override
|
||||
{
|
||||
QModelIndex nameIndex = sourceModel()->index(source_row, 0, source_parent);
|
||||
QModelIndex typeIndex = sourceModel()->index(source_row, 1, source_parent);
|
||||
|
||||
QString name = sourceModel()->data(nameIndex, Qt::DisplayRole).toString();
|
||||
QString type = sourceModel()->data(typeIndex, Qt::DisplayRole).toString();
|
||||
|
||||
// TODO: cleanup once we drop Qt5 support
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5,12,0))
|
||||
QRegularExpression nameRegularExpression(filterRegularExpression());
|
||||
nameRegularExpression.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
|
||||
|
||||
bool nameFilterPassed = nameRegularExpression.match(name).capturedStart() != -1;
|
||||
#else
|
||||
QRegExp nameRegularExpression(filterRegExp());
|
||||
nameRegularExpression.setCaseSensitivity(Qt::CaseInsensitive);
|
||||
|
||||
bool nameFilterPassed = nameRegularExpression.indexIn(name) != -1;
|
||||
#endif
|
||||
|
||||
bool typeFilterPassed = type.contains(m_effectTypeFilter, Qt::CaseInsensitive);
|
||||
|
||||
return nameFilterPassed && typeFilterPassed;
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_effectTypeFilter;
|
||||
};
|
||||
|
||||
|
||||
class EffectSelectDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectSelectDialog( QWidget * _parent );
|
||||
~EffectSelectDialog() override;
|
||||
|
||||
Effect * instantiateSelectedPlugin( EffectChain * _parent );
|
||||
EffectSelectDialog(QWidget* parent);
|
||||
|
||||
Effect* instantiateSelectedPlugin(EffectChain* parent);
|
||||
|
||||
protected slots:
|
||||
void acceptSelection();
|
||||
void rowChanged( const QModelIndex &, const QModelIndex & );
|
||||
void sortAgain();
|
||||
void rowChanged(const QModelIndex&, const QModelIndex&);
|
||||
void updateSelection();
|
||||
|
||||
|
||||
bool eventFilter(QObject* obj, QEvent* event) override;
|
||||
|
||||
private:
|
||||
Ui::EffectSelectDialog * ui;
|
||||
|
||||
EffectKeyList m_effectKeys;
|
||||
EffectKey m_currentSelection;
|
||||
|
||||
QStandardItemModel m_sourceModel;
|
||||
QSortFilterProxyModel m_model;
|
||||
QWidget * m_descriptionWidget;
|
||||
|
||||
} ;
|
||||
|
||||
DualColumnFilterProxyModel m_model;
|
||||
QWidget* m_descriptionWidget;
|
||||
QTableView* m_pluginList;
|
||||
QScrollArea* m_scrollArea;
|
||||
QLineEdit* m_filterEdit;
|
||||
};
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,13 +23,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_VIEW_H
|
||||
#define EFFECT_VIEW_H
|
||||
#ifndef LMMS_GUI_EFFECT_VIEW_H
|
||||
#define LMMS_GUI_EFFECT_VIEW_H
|
||||
|
||||
#include "AutomatableModel.h"
|
||||
#include "PluginView.h"
|
||||
#include "Effect.h"
|
||||
|
||||
class QGraphicsOpacityEffect;
|
||||
class QGroupBox;
|
||||
class QLabel;
|
||||
class QPushButton;
|
||||
@@ -61,6 +62,11 @@ public:
|
||||
}
|
||||
|
||||
static constexpr int DEFAULT_WIDTH = 215;
|
||||
static constexpr int DEFAULT_HEIGHT = 60;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
|
||||
public slots:
|
||||
void editControls();
|
||||
@@ -90,10 +96,13 @@ private:
|
||||
Knob * m_gate;
|
||||
QMdiSubWindow * m_subWindow;
|
||||
EffectControlDialog * m_controlView;
|
||||
|
||||
bool m_dragging;
|
||||
QGraphicsOpacityEffect* m_opacityEffect;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_EFFECT_VIEW_H
|
||||
|
||||
@@ -22,14 +22,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
#ifndef LMMS_ENGINE_H
|
||||
#define LMMS_ENGINE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
#include "lmms_export.h"
|
||||
#include "lmms_basics.h"
|
||||
@@ -157,5 +155,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LMMS_ENGINE_H
|
||||
|
||||
@@ -22,10 +22,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ENVELOPE_AND_LFO_PARAMETERS_H
|
||||
#define ENVELOPE_AND_LFO_PARAMETERS_H
|
||||
#ifndef LMMS_ENVELOPE_AND_LFO_PARAMETERS_H
|
||||
#define LMMS_ENVELOPE_AND_LFO_PARAMETERS_H
|
||||
|
||||
#include <QVector>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "JournallingObject.h"
|
||||
#include "AutomatableModel.h"
|
||||
@@ -70,7 +71,18 @@ public:
|
||||
using LfoList = QList<EnvelopeAndLfoParameters*>;
|
||||
LfoList m_lfos;
|
||||
|
||||
} ;
|
||||
};
|
||||
|
||||
enum class LfoShape
|
||||
{
|
||||
SineWave,
|
||||
TriangleWave,
|
||||
SawWave,
|
||||
SquareWave,
|
||||
UserDefinedWave,
|
||||
RandomWave,
|
||||
Count
|
||||
};
|
||||
|
||||
EnvelopeAndLfoParameters( float _value_for_zero_amount,
|
||||
Model * _parent );
|
||||
@@ -113,6 +125,28 @@ public:
|
||||
return m_rFrames;
|
||||
}
|
||||
|
||||
// Envelope
|
||||
const FloatModel& getPredelayModel() const { return m_predelayModel; }
|
||||
const FloatModel& getAttackModel() const { return m_attackModel; }
|
||||
const FloatModel& getHoldModel() const { return m_holdModel; }
|
||||
const FloatModel& getDecayModel() const { return m_decayModel; }
|
||||
const FloatModel& getSustainModel() const { return m_sustainModel; }
|
||||
const FloatModel& getReleaseModel() const { return m_releaseModel; }
|
||||
const FloatModel& getAmountModel() const { return m_amountModel; }
|
||||
FloatModel& getAmountModel() { return m_amountModel; }
|
||||
|
||||
|
||||
// LFO
|
||||
inline f_cnt_t getLfoPredelayFrames() const { return m_lfoPredelayFrames; }
|
||||
inline f_cnt_t getLfoAttackFrames() const { return m_lfoAttackFrames; }
|
||||
inline f_cnt_t getLfoOscillationFrames() const { return m_lfoOscillationFrames; }
|
||||
|
||||
const FloatModel& getLfoAmountModel() const { return m_lfoAmountModel; }
|
||||
FloatModel& getLfoAmountModel() { return m_lfoAmountModel; }
|
||||
const TempoSyncKnobModel& getLfoSpeedModel() const { return m_lfoSpeedModel; }
|
||||
const BoolModel& getX100Model() const { return m_x100Model; }
|
||||
const IntModel& getLfoWaveModel() const { return m_lfoWaveModel; }
|
||||
std::shared_ptr<const SampleBuffer> getLfoUserWave() const { return m_userWave; }
|
||||
|
||||
public slots:
|
||||
void updateSampleVars();
|
||||
@@ -167,18 +201,9 @@ private:
|
||||
sample_t * m_lfoShapeData;
|
||||
sample_t m_random;
|
||||
bool m_bad_lfoShapeData;
|
||||
SampleBuffer m_userWave;
|
||||
std::shared_ptr<const SampleBuffer> m_userWave = SampleBuffer::emptyBuffer();
|
||||
|
||||
enum LfoShapes
|
||||
{
|
||||
SineWave,
|
||||
TriangleWave,
|
||||
SawWave,
|
||||
SquareWave,
|
||||
UserDefinedWave,
|
||||
RandomWave,
|
||||
NumLfoShapes
|
||||
} ;
|
||||
constexpr static auto NumLfoShapes = static_cast<std::size_t>(LfoShape::Count);
|
||||
|
||||
sample_t lfoShapeSample( fpp_t _frame_offset );
|
||||
void updateLfoShapeData();
|
||||
@@ -190,4 +215,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_ENVELOPE_AND_LFO_PARAMETERS_H
|
||||
|
||||
@@ -23,16 +23,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ENVELOPE_AND_LFO_VIEW_H
|
||||
#define ENVELOPE_AND_LFO_VIEW_H
|
||||
#ifndef LMMS_GUI_ENVELOPE_AND_LFO_VIEW_H
|
||||
#define LMMS_GUI_ENVELOPE_AND_LFO_VIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "ModelView.h"
|
||||
|
||||
class QPaintEvent;
|
||||
class QPixmap;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
@@ -46,6 +43,8 @@ class Knob;
|
||||
class LedCheckBox;
|
||||
class PixmapButton;
|
||||
class TempoSyncKnob;
|
||||
class EnvelopeGraph;
|
||||
class LfoGraph;
|
||||
|
||||
|
||||
|
||||
@@ -62,8 +61,6 @@ protected:
|
||||
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
void mousePressEvent( QMouseEvent * _me ) override;
|
||||
void paintEvent( QPaintEvent * _pe ) override;
|
||||
|
||||
|
||||
protected slots:
|
||||
@@ -71,13 +68,10 @@ protected slots:
|
||||
|
||||
|
||||
private:
|
||||
static QPixmap * s_envGraph;
|
||||
static QPixmap * s_lfoGraph;
|
||||
|
||||
EnvelopeAndLfoParameters * m_params;
|
||||
|
||||
|
||||
// envelope stuff
|
||||
EnvelopeGraph* m_envelopeGraph;
|
||||
Knob * m_predelayKnob;
|
||||
Knob * m_attackKnob;
|
||||
Knob * m_holdKnob;
|
||||
@@ -87,6 +81,7 @@ private:
|
||||
Knob * m_amountKnob;
|
||||
|
||||
// LFO stuff
|
||||
LfoGraph* m_lfoGraph;
|
||||
Knob * m_lfoPredelayKnob;
|
||||
Knob * m_lfoAttackKnob;
|
||||
TempoSyncKnob * m_lfoSpeedKnob;
|
||||
@@ -96,12 +91,10 @@ private:
|
||||
|
||||
LedCheckBox * m_x100Cb;
|
||||
LedCheckBox * m_controlEnvAmountCb;
|
||||
|
||||
float m_randomGraph;
|
||||
} ;
|
||||
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_ENVELOPE_AND_LFO_VIEW_H
|
||||
|
||||
77
include/EnvelopeGraph.h
Normal file
77
include/EnvelopeGraph.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* EnvelopeGraph.h - Displays envelope graphs
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2024- Michael Gregorius
|
||||
*
|
||||
* 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 LMMS_GUI_ENVELOPE_GRAPH_H
|
||||
#define LMMS_GUI_ENVELOPE_GRAPH_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "ModelView.h"
|
||||
#include "embed.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class EnvelopeAndLfoParameters;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class EnvelopeGraph : public QWidget, public ModelView
|
||||
{
|
||||
public:
|
||||
enum class ScalingMode
|
||||
{
|
||||
Dynamic,
|
||||
Absolute,
|
||||
Relative
|
||||
};
|
||||
|
||||
public:
|
||||
EnvelopeGraph(QWidget* parent);
|
||||
|
||||
protected:
|
||||
void modelChanged() override;
|
||||
|
||||
void mousePressEvent(QMouseEvent*) override;
|
||||
void contextMenuEvent(QContextMenuEvent*) override;
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
|
||||
private:
|
||||
void toggleAmountModel();
|
||||
|
||||
private:
|
||||
QPixmap m_envGraph = embed::getIconPixmap("envelope_graph");
|
||||
|
||||
EnvelopeAndLfoParameters* m_params = nullptr;
|
||||
|
||||
ScalingMode m_scaling = ScalingMode::Dynamic;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GUI_ENVELOPE_GRAPH_H
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EXPORT_FILTER_H
|
||||
#define EXPORT_FILTER_H
|
||||
#ifndef LMMS_EXPORT_FILTER_H
|
||||
#define LMMS_EXPORT_FILTER_H
|
||||
|
||||
#include <QFile>
|
||||
|
||||
@@ -69,4 +69,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_EXPORT_FILTER_H
|
||||
|
||||
@@ -23,9 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef EXPORT_PROJECT_DIALOG_H
|
||||
#define EXPORT_PROJECT_DIALOG_H
|
||||
#ifndef LMMS_GUI_EXPORT_PROJECT_DIALOG_H
|
||||
#define LMMS_GUI_EXPORT_PROJECT_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
@@ -63,12 +62,11 @@ private:
|
||||
QString m_fileExtension;
|
||||
bool m_multiExport;
|
||||
|
||||
ProjectRenderer::ExportFileFormats m_ft;
|
||||
ProjectRenderer::ExportFileFormat m_ft;
|
||||
std::unique_ptr<RenderManager> m_renderManager;
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_EXPORT_PROJECT_DIALOG_H
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FADE_BUTTON_H
|
||||
#define FADE_BUTTON_H
|
||||
#ifndef LMMS_GUI_FADE_BUTTON_H
|
||||
#define LMMS_GUI_FADE_BUTTON_H
|
||||
|
||||
#include <QAbstractButton>
|
||||
#include <QColor>
|
||||
@@ -77,4 +76,4 @@ private:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_FADE_BUTTON_H
|
||||
|
||||
117
include/Fader.h
117
include/Fader.h
@@ -44,9 +44,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FADER_H
|
||||
#define FADER_H
|
||||
#ifndef LMMS_GUI_FADER_H
|
||||
#define LMMS_GUI_FADER_H
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QPixmap>
|
||||
@@ -54,32 +53,35 @@
|
||||
|
||||
|
||||
#include "AutomatableModelView.h"
|
||||
#include "embed.h"
|
||||
#include "lmms_math.h"
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class TextFloat;
|
||||
class SimpleTextFloat;
|
||||
|
||||
|
||||
class LMMS_EXPORT Fader : public QWidget, public FloatModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_PROPERTY( QColor peakGreen READ peakGreen WRITE setPeakGreen )
|
||||
Q_PROPERTY( QColor peakRed READ peakRed WRITE setPeakRed )
|
||||
Q_PROPERTY( QColor peakYellow READ peakYellow WRITE setPeakYellow )
|
||||
Q_PROPERTY( bool levelsDisplayedInDBFS READ getLevelsDisplayedInDBFS WRITE setLevelsDisplayedInDBFS )
|
||||
Q_PROPERTY(QColor peakOk MEMBER m_peakOk)
|
||||
Q_PROPERTY(QColor peakClip MEMBER m_peakClip)
|
||||
Q_PROPERTY(QColor peakWarn MEMBER m_peakWarn)
|
||||
Q_PROPERTY(bool levelsDisplayedInDBFS MEMBER m_levelsDisplayedInDBFS)
|
||||
Q_PROPERTY(bool renderUnityLine READ getRenderUnityLine WRITE setRenderUnityLine)
|
||||
Q_PROPERTY(QColor unityMarker MEMBER m_unityMarker)
|
||||
|
||||
Fader( FloatModel * _model, const QString & _name, QWidget * _parent );
|
||||
Fader( FloatModel * _model, const QString & _name, QWidget * _parent, QPixmap * back, QPixmap * leds, QPixmap * knob );
|
||||
Fader(FloatModel* model, const QString& name, QWidget* parent);
|
||||
Fader(FloatModel* model, const QString& name, QWidget* parent, const QPixmap& knob);
|
||||
~Fader() override = default;
|
||||
|
||||
void init(FloatModel * model, QString const & name);
|
||||
|
||||
void setPeak_L( float fPeak );
|
||||
void setPeak_L(float fPeak);
|
||||
float getPeak_L() { return m_fPeakValue_L; }
|
||||
|
||||
void setPeak_R( float fPeak );
|
||||
void setPeak_R(float fPeak);
|
||||
float getPeak_R() { return m_fPeakValue_R; }
|
||||
|
||||
inline float getMinPeak() const { return m_fMinPeak; }
|
||||
@@ -88,91 +90,74 @@ public:
|
||||
inline float getMaxPeak() const { return m_fMaxPeak; }
|
||||
inline void setMaxPeak(float maxPeak) { m_fMaxPeak = maxPeak; }
|
||||
|
||||
QColor const & peakGreen() const;
|
||||
void setPeakGreen( const QColor & c );
|
||||
inline bool getRenderUnityLine() const { return m_renderUnityLine; }
|
||||
inline void setRenderUnityLine(bool value = true) { m_renderUnityLine = value; }
|
||||
|
||||
QColor const & peakRed() const;
|
||||
void setPeakRed( const QColor & c );
|
||||
|
||||
QColor const & peakYellow() const;
|
||||
void setPeakYellow( const QColor & c );
|
||||
|
||||
inline bool getLevelsDisplayedInDBFS() const { return m_levelsDisplayedInDBFS; }
|
||||
inline void setLevelsDisplayedInDBFS(bool value = true) { m_levelsDisplayedInDBFS = value; }
|
||||
|
||||
void setDisplayConversion( bool b )
|
||||
void setDisplayConversion(bool b)
|
||||
{
|
||||
m_conversionFactor = b ? 100.0 : 1.0;
|
||||
}
|
||||
|
||||
inline void setHintText( const QString & _txt_before,
|
||||
const QString & _txt_after )
|
||||
inline void setHintText(const QString& txt_before,
|
||||
const QString& txt_after)
|
||||
{
|
||||
setDescription( _txt_before );
|
||||
setUnit( _txt_after );
|
||||
setDescription(txt_before);
|
||||
setUnit(txt_after);
|
||||
}
|
||||
|
||||
private:
|
||||
void contextMenuEvent( QContextMenuEvent * _me ) override;
|
||||
void mousePressEvent( QMouseEvent *ev ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent* mouseEvent ) override;
|
||||
void mouseMoveEvent( QMouseEvent *ev ) override;
|
||||
void mouseReleaseEvent( QMouseEvent * _me ) override;
|
||||
void wheelEvent( QWheelEvent *ev ) override;
|
||||
void paintEvent( QPaintEvent *ev ) override;
|
||||
void contextMenuEvent(QContextMenuEvent* me) override;
|
||||
void mousePressEvent(QMouseEvent* ev) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent* mouseEvent) override;
|
||||
void mouseMoveEvent(QMouseEvent* ev) override;
|
||||
void mouseReleaseEvent(QMouseEvent* me) override;
|
||||
void wheelEvent(QWheelEvent* ev) override;
|
||||
void paintEvent(QPaintEvent* ev) override;
|
||||
|
||||
inline bool clips(float const & value) const { return value >= 1.0f; }
|
||||
|
||||
void paintDBFSLevels(QPaintEvent *ev, QPainter & painter);
|
||||
void paintLinearLevels(QPaintEvent *ev, QPainter & painter);
|
||||
void paintLevels(QPaintEvent* ev, QPainter& painter, bool linear = false);
|
||||
|
||||
int knobPosY() const
|
||||
{
|
||||
float fRange = model()->maxValue() - model()->minValue();
|
||||
float realVal = model()->value() - model()->minValue();
|
||||
|
||||
return height() - ( ( height() - m_knob->height() ) * ( realVal / fRange ) );
|
||||
return height() - ((height() - m_knob.height()) * (realVal / fRange));
|
||||
}
|
||||
|
||||
void setPeak( float fPeak, float &targetPeak, float &persistentPeak, QElapsedTimer &lastPeakTimer );
|
||||
int calculateDisplayPeak( float fPeak );
|
||||
void setPeak(float fPeak, float& targetPeak, float& persistentPeak, QElapsedTimer& lastPeakTimer);
|
||||
|
||||
void updateTextFloat();
|
||||
|
||||
// Private members
|
||||
private:
|
||||
float m_fPeakValue_L;
|
||||
float m_fPeakValue_R;
|
||||
float m_persistentPeak_L;
|
||||
float m_persistentPeak_R;
|
||||
float m_fMinPeak;
|
||||
float m_fMaxPeak;
|
||||
float m_fPeakValue_L {0.};
|
||||
float m_fPeakValue_R {0.};
|
||||
float m_persistentPeak_L {0.};
|
||||
float m_persistentPeak_R {0.};
|
||||
float m_fMinPeak {dbfsToAmp(-42)};
|
||||
float m_fMaxPeak {dbfsToAmp(9)};
|
||||
|
||||
QElapsedTimer m_lastPeakTimer_L;
|
||||
QElapsedTimer m_lastPeakTimer_R;
|
||||
|
||||
static QPixmap * s_back;
|
||||
static QPixmap * s_leds;
|
||||
static QPixmap * s_knob;
|
||||
|
||||
QPixmap * m_back;
|
||||
QPixmap * m_leds;
|
||||
QPixmap * m_knob;
|
||||
QPixmap m_knob {embed::getIconPixmap("fader_knob")};
|
||||
|
||||
bool m_levelsDisplayedInDBFS;
|
||||
bool m_levelsDisplayedInDBFS {true};
|
||||
|
||||
int m_moveStartPoint;
|
||||
float m_startValue;
|
||||
int m_moveStartPoint {-1};
|
||||
float m_startValue {0.};
|
||||
|
||||
static TextFloat * s_textFloat;
|
||||
static SimpleTextFloat* s_textFloat;
|
||||
|
||||
QColor m_peakGreen;
|
||||
QColor m_peakRed;
|
||||
QColor m_peakYellow;
|
||||
QColor m_peakOk {10, 212, 92};
|
||||
QColor m_peakClip {193, 32, 56};
|
||||
QColor m_peakWarn {214, 236, 82};
|
||||
QColor m_unityMarker {63, 63, 63, 255};
|
||||
|
||||
bool m_renderUnityLine {true};
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_FADER_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FIFO_BUFFER_H
|
||||
#define FIFO_BUFFER_H
|
||||
#ifndef LMMS_FIFO_BUFFER_H
|
||||
#define LMMS_FIFO_BUFFER_H
|
||||
|
||||
#include <QSemaphore>
|
||||
|
||||
@@ -94,4 +94,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_FIFO_BUFFER_H
|
||||
|
||||
@@ -22,21 +22,24 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FILE_BROWSER_H
|
||||
#define FILE_BROWSER_H
|
||||
#ifndef LMMS_GUI_FILE_BROWSER_H
|
||||
#define LMMS_GUI_FILE_BROWSER_H
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDir>
|
||||
#include <QMutex>
|
||||
#include "embed.h"
|
||||
|
||||
#include "FileBrowserSearcher.h"
|
||||
#include <QProgressBar>
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
|
||||
#include <QRecursiveMutex>
|
||||
#endif
|
||||
#include <QTreeWidget>
|
||||
|
||||
|
||||
#include "SideBarWidget.h"
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
@@ -67,17 +70,31 @@ public:
|
||||
*/
|
||||
FileBrowser( const QString & directories, const QString & filter,
|
||||
const QString & title, const QPixmap & pm,
|
||||
QWidget * parent, bool dirs_as_items = false, bool recurse = false,
|
||||
QWidget * parent, bool dirs_as_items = false,
|
||||
const QString& userDir = "",
|
||||
const QString& factoryDir = "");
|
||||
|
||||
~FileBrowser() override = default;
|
||||
|
||||
static QStringList directoryBlacklist()
|
||||
{
|
||||
static auto s_blacklist = QStringList{
|
||||
#ifdef LMMS_BUILD_LINUX
|
||||
"/bin", "/boot", "/dev", "/etc", "/proc", "/run", "/sbin",
|
||||
"/sys"
|
||||
#endif
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
"C:\\Windows"
|
||||
#endif
|
||||
};
|
||||
return s_blacklist;
|
||||
}
|
||||
static QDir::Filters dirFilters() { return QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot; }
|
||||
static QDir::SortFlags sortFlags() { return QDir::LocaleAware | QDir::DirsFirst | QDir::Name | QDir::IgnoreCase; }
|
||||
|
||||
private slots:
|
||||
void reloadTree();
|
||||
void expandItems( QTreeWidgetItem * item=nullptr, QList<QString> expandedDirs = QList<QString>() );
|
||||
// call with item=NULL to filter the entire tree
|
||||
bool filterItems( const QString & filter, QTreeWidgetItem * item=nullptr );
|
||||
void expandItems(const QList<QString>& expandedDirs, QTreeWidgetItem* item = nullptr);
|
||||
void giveFocusToFilter();
|
||||
|
||||
private:
|
||||
@@ -85,21 +102,33 @@ private:
|
||||
|
||||
void addItems( const QString & path );
|
||||
|
||||
void saveDirectoriesStates();
|
||||
void restoreDirectoriesStates();
|
||||
|
||||
void buildSearchTree();
|
||||
void onSearch(const QString& filter);
|
||||
void toggleSearch(bool on);
|
||||
|
||||
FileBrowserTreeWidget * m_fileBrowserTreeWidget;
|
||||
FileBrowserTreeWidget * m_searchTreeWidget;
|
||||
|
||||
QLineEdit * m_filterEdit;
|
||||
|
||||
std::shared_ptr<FileBrowserSearcher::SearchFuture> m_currentSearch;
|
||||
QProgressBar* m_searchIndicator = nullptr;
|
||||
|
||||
QString m_directories; //!< Directories to search, split with '*'
|
||||
QString m_filter; //!< Filter as used in QDir::match()
|
||||
|
||||
bool m_dirsAsItems;
|
||||
bool m_recurse;
|
||||
|
||||
void addContentCheckBox();
|
||||
QCheckBox* m_showUserContent = nullptr;
|
||||
QCheckBox* m_showFactoryContent = nullptr;
|
||||
QString m_userDir;
|
||||
QString m_factoryDir;
|
||||
QList<QString> m_savedExpandedDirs;
|
||||
QString m_previousFilterValue;
|
||||
} ;
|
||||
|
||||
|
||||
@@ -116,7 +145,6 @@ public:
|
||||
//! that are expanded in the tree.
|
||||
QList<QString> expandedDirs( QTreeWidgetItem * item = nullptr ) const;
|
||||
|
||||
|
||||
protected:
|
||||
void contextMenuEvent( QContextMenuEvent * e ) override;
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
@@ -165,12 +193,10 @@ private slots:
|
||||
|
||||
|
||||
|
||||
|
||||
class Directory : public QTreeWidgetItem
|
||||
{
|
||||
public:
|
||||
Directory( const QString & filename, const QString & path,
|
||||
const QString & filter );
|
||||
Directory(const QString& filename, const QString& path, const QString& filter, bool disableEntryPopulation = false);
|
||||
|
||||
void update();
|
||||
|
||||
@@ -195,14 +221,12 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void initPixmaps();
|
||||
|
||||
bool addItems( const QString & path );
|
||||
|
||||
|
||||
static QPixmap * s_folderPixmap;
|
||||
static QPixmap * s_folderOpenedPixmap;
|
||||
static QPixmap * s_folderLockedPixmap;
|
||||
QPixmap m_folderPixmap = embed::getIconPixmap("folder");
|
||||
QPixmap m_folderOpenedPixmap = embed::getIconPixmap("folder_opened");
|
||||
QPixmap m_folderLockedPixmap = embed::getIconPixmap("folder_locked");
|
||||
|
||||
//! Directories that lead here
|
||||
//! Initially, this is just set to the current path of a directory
|
||||
@@ -215,7 +239,7 @@ private:
|
||||
QString m_filter;
|
||||
|
||||
int m_dirCount;
|
||||
|
||||
bool m_disableEntryPopulation = false;
|
||||
} ;
|
||||
|
||||
|
||||
@@ -224,20 +248,19 @@ private:
|
||||
class FileItem : public QTreeWidgetItem
|
||||
{
|
||||
public:
|
||||
enum FileTypes
|
||||
enum class FileType
|
||||
{
|
||||
ProjectFile,
|
||||
PresetFile,
|
||||
SampleFile,
|
||||
SoundFontFile,
|
||||
PatchFile,
|
||||
MidiFile,
|
||||
VstPluginFile,
|
||||
UnknownFile,
|
||||
NumFileTypes
|
||||
Project,
|
||||
Preset,
|
||||
Sample,
|
||||
SoundFont,
|
||||
Patch,
|
||||
Midi,
|
||||
VstPlugin,
|
||||
Unknown
|
||||
} ;
|
||||
|
||||
enum FileHandling
|
||||
enum class FileHandling
|
||||
{
|
||||
NotSupported,
|
||||
LoadAsProject,
|
||||
@@ -256,7 +279,7 @@ public:
|
||||
return QFileInfo(m_path, text(0)).absoluteFilePath();
|
||||
}
|
||||
|
||||
inline FileTypes type() const
|
||||
inline FileType type() const
|
||||
{
|
||||
return( m_type );
|
||||
}
|
||||
@@ -268,27 +291,20 @@ public:
|
||||
|
||||
inline bool isTrack() const
|
||||
{
|
||||
return m_handling == LoadAsPreset || m_handling == LoadByPlugin;
|
||||
return m_handling == FileHandling::LoadAsPreset || m_handling == FileHandling::LoadByPlugin;
|
||||
}
|
||||
|
||||
QString extension();
|
||||
static QString extension( const QString & file );
|
||||
static QString defaultFilters();
|
||||
|
||||
|
||||
private:
|
||||
void initPixmaps();
|
||||
void determineFileType();
|
||||
|
||||
static QPixmap * s_projectFilePixmap;
|
||||
static QPixmap * s_presetFilePixmap;
|
||||
static QPixmap * s_sampleFilePixmap;
|
||||
static QPixmap * s_soundfontFilePixmap;
|
||||
static QPixmap * s_vstPluginFilePixmap;
|
||||
static QPixmap * s_midiFilePixmap;
|
||||
static QPixmap * s_unknownFilePixmap;
|
||||
|
||||
QString m_path;
|
||||
FileTypes m_type;
|
||||
FileType m_type;
|
||||
FileHandling m_handling;
|
||||
|
||||
} ;
|
||||
@@ -298,4 +314,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_FILE_BROWSER_H
|
||||
|
||||
148
include/FileBrowserSearcher.h
Normal file
148
include/FileBrowserSearcher.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* FileBrowserSearcher.h - Batch processor for searching the filesystem
|
||||
*
|
||||
* Copyright (c) 2023 saker <sakertooth@gmail.com>
|
||||
*
|
||||
* 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 LMMS_FILE_BROWSER_SEARCHER_H
|
||||
#define LMMS_FILE_BROWSER_SEARCHER_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <mingw.condition_variable.h>
|
||||
#include <mingw.mutex.h>
|
||||
#include <mingw.thread.h>
|
||||
#else
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
namespace lmms::gui {
|
||||
|
||||
//! An active object that handles searching for files that match a certain filter across the file system.
|
||||
class FileBrowserSearcher
|
||||
{
|
||||
public:
|
||||
//! Number of milliseconds to wait for before a match should be processed by the user.
|
||||
static constexpr int MillisecondsPerMatch = 1;
|
||||
|
||||
//! The future object for FileBrowserSearcher. It is used to track the current state of search operations, as
|
||||
// well as retrieve matches.
|
||||
class SearchFuture
|
||||
{
|
||||
public:
|
||||
//! Possible state values of the future object.
|
||||
enum class State
|
||||
{
|
||||
Idle,
|
||||
Running,
|
||||
Cancelled,
|
||||
Completed
|
||||
};
|
||||
|
||||
//! Constructs a future object using the specified filter, paths, and valid file extensions in the Idle state.
|
||||
SearchFuture(const QString& filter, const QStringList& paths, const QStringList& extensions)
|
||||
: m_filter(filter)
|
||||
, m_paths(paths)
|
||||
, m_extensions(extensions)
|
||||
{
|
||||
}
|
||||
|
||||
//! Retrieves a match from the match list.
|
||||
auto match() -> QString
|
||||
{
|
||||
const auto lock = std::lock_guard{m_matchesMutex};
|
||||
return m_matches.empty() ? QString{} : m_matches.takeFirst();
|
||||
}
|
||||
|
||||
//! Returns the current state of this future object.
|
||||
auto state() -> State { return m_state; }
|
||||
|
||||
//! Returns the filter used.
|
||||
auto filter() -> const QString& { return m_filter; }
|
||||
|
||||
//! Returns the paths to filter.
|
||||
auto paths() -> const QStringList& { return m_paths; }
|
||||
|
||||
//! Returns the valid file extensions.
|
||||
auto extensions() -> const QStringList& { return m_extensions; }
|
||||
|
||||
private:
|
||||
//! Adds a match to the match list.
|
||||
auto addMatch(const QString& match) -> void
|
||||
{
|
||||
const auto lock = std::lock_guard{m_matchesMutex};
|
||||
m_matches.append(match);
|
||||
}
|
||||
|
||||
QString m_filter;
|
||||
QStringList m_paths;
|
||||
QStringList m_extensions;
|
||||
|
||||
QStringList m_matches;
|
||||
std::mutex m_matchesMutex;
|
||||
|
||||
std::atomic<State> m_state = State::Idle;
|
||||
|
||||
friend FileBrowserSearcher;
|
||||
};
|
||||
|
||||
~FileBrowserSearcher();
|
||||
|
||||
//! Enqueues a search to be ran by the worker thread.
|
||||
//! Returns a future that the caller can use to track state and results of the operation.
|
||||
auto search(const QString& filter, const QStringList& paths, const QStringList& extensions)
|
||||
-> std::shared_ptr<SearchFuture>;
|
||||
|
||||
//! Sends a signal to cancel a running search.
|
||||
auto cancel() -> void { m_cancelRunningSearch = true; }
|
||||
|
||||
//! Returns the global instance of the searcher object.
|
||||
static auto instance() -> FileBrowserSearcher*
|
||||
{
|
||||
static auto s_instance = FileBrowserSearcher{};
|
||||
return &s_instance;
|
||||
}
|
||||
|
||||
private:
|
||||
//! Event loop for the worker thread.
|
||||
auto run() -> void;
|
||||
|
||||
//! Using Depth-first search (DFS), filters the specified path and adds any matches to the future list.
|
||||
auto process(SearchFuture* searchFuture, const QString& path) -> bool;
|
||||
|
||||
std::queue<std::shared_ptr<SearchFuture>> m_searchQueue;
|
||||
std::atomic<bool> m_cancelRunningSearch = false;
|
||||
|
||||
bool m_workerStopped = false;
|
||||
std::mutex m_workerMutex;
|
||||
std::condition_variable m_workerCond;
|
||||
std::thread m_worker{[this] { run(); }};
|
||||
};
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_FILE_BROWSER_SEARCHER_H
|
||||
@@ -22,9 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FILEDIALOG_H
|
||||
#define FILEDIALOG_H
|
||||
#ifndef LMMS_GUI_FILE_DIALOG_H
|
||||
#define LMMS_GUI_FILE_DIALOG_H
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
@@ -57,4 +56,4 @@ public:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // FILEDIALOG_H
|
||||
#endif // LMMS_GUI_FILE_DIALOG_H
|
||||
|
||||
83
include/Flags.h
Normal file
83
include/Flags.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Flags.h - class to make flags from enums
|
||||
*
|
||||
* Copyright (c) 2023 Dominic Clark
|
||||
*
|
||||
* 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 LMMS_FLAGS_H
|
||||
#define LMMS_FLAGS_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace lmms {
|
||||
|
||||
template<typename T>
|
||||
class Flags
|
||||
{
|
||||
static_assert(std::is_enum_v<T>, "lmms::Flags can only be used with enum types");
|
||||
|
||||
public:
|
||||
using EnumType = T;
|
||||
using UnderlyingType = std::underlying_type_t<T>;
|
||||
|
||||
constexpr Flags() = default;
|
||||
|
||||
constexpr Flags(T value) : // Intentionally not explicit
|
||||
m_value{static_cast<UnderlyingType>(value)}
|
||||
{}
|
||||
|
||||
constexpr explicit Flags(UnderlyingType value) :
|
||||
m_value{value}
|
||||
{}
|
||||
|
||||
constexpr auto testAll(Flags flags) const -> bool { return (*this & flags) == flags; }
|
||||
constexpr auto testAny(Flags flags) const -> bool { return (*this & flags) != Flags{}; }
|
||||
constexpr auto testFlag(EnumType flag) const -> bool { return static_cast<bool>(*this & flag); }
|
||||
|
||||
constexpr auto operator~() const -> Flags { return Flags{~m_value}; }
|
||||
friend constexpr auto operator&(Flags l, Flags r) -> Flags { return Flags{l.m_value & r.m_value}; }
|
||||
friend constexpr auto operator|(Flags l, Flags r) -> Flags { return Flags{l.m_value | r.m_value}; }
|
||||
friend constexpr auto operator^(Flags l, Flags r) -> Flags { return Flags{l.m_value ^ r.m_value}; }
|
||||
friend constexpr auto operator+(Flags l, Flags r) -> Flags { return Flags{l.m_value | r.m_value}; }
|
||||
friend constexpr auto operator-(Flags l, Flags r) -> Flags { return Flags{l.m_value & ~r.m_value}; }
|
||||
|
||||
constexpr auto operator&=(Flags f) -> Flags& { m_value &= f.m_value; return *this; }
|
||||
constexpr auto operator|=(Flags f) -> Flags& { m_value |= f.m_value; return *this; }
|
||||
constexpr auto operator^=(Flags f) -> Flags& { m_value ^= f.m_value; return *this; }
|
||||
constexpr auto operator+=(Flags f) -> Flags& { m_value |= f.m_value; return *this; }
|
||||
constexpr auto operator-=(Flags f) -> Flags& { m_value &= ~f.m_value; return *this; }
|
||||
|
||||
constexpr explicit operator UnderlyingType() const { return m_value; } // TODO C++23: explicit(std::is_scoped_enum<T>)
|
||||
constexpr explicit operator bool() const { return m_value != 0; }
|
||||
|
||||
friend constexpr auto operator==(Flags l, Flags r) -> bool { return l.m_value == r.m_value; } // TODO C++20: = default
|
||||
friend constexpr auto operator!=(Flags l, Flags r) -> bool { return l.m_value != r.m_value; } // TODO C++20: Remove
|
||||
|
||||
private:
|
||||
UnderlyingType m_value = 0;
|
||||
};
|
||||
|
||||
#define LMMS_DECLARE_OPERATORS_FOR_FLAGS(type) \
|
||||
constexpr inline auto operator|(type l, type r) -> ::lmms::Flags<type> { return ::lmms::Flags{l} | ::lmms::Flags{r}; }
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_FLAGS_H
|
||||
121
include/FloatModelEditorBase.h
Normal file
121
include/FloatModelEditorBase.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* FloatModelEditorBase.h - Base editor for float models
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2023 Michael Gregorius
|
||||
*
|
||||
* 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 LMMS_GUI_FLOAT_MODEL_EDITOR_BASE_H
|
||||
#define LMMS_GUI_FLOAT_MODEL_EDITOR_BASE_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPoint>
|
||||
|
||||
#include "AutomatableModelView.h"
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class SimpleTextFloat;
|
||||
|
||||
class LMMS_EXPORT FloatModelEditorBase : public QWidget, public FloatModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
mapPropertyFromModel(bool, isVolumeKnob, setVolumeKnob, m_volumeKnob);
|
||||
mapPropertyFromModel(float, volumeRatio, setVolumeRatio, m_volumeRatio);
|
||||
|
||||
void initUi(const QString & name); //!< to be called by ctors
|
||||
|
||||
public:
|
||||
enum class DirectionOfManipulation
|
||||
{
|
||||
Vertical,
|
||||
Horizontal
|
||||
};
|
||||
|
||||
FloatModelEditorBase(DirectionOfManipulation directionOfManipulation = DirectionOfManipulation::Vertical, QWidget * _parent = nullptr, const QString & _name = QString()); //!< default ctor
|
||||
FloatModelEditorBase(const FloatModelEditorBase& other) = delete;
|
||||
|
||||
// TODO: remove
|
||||
inline void setHintText(const QString & txt_before, const QString & txt_after)
|
||||
{
|
||||
setDescription(txt_before);
|
||||
setUnit(txt_after);
|
||||
}
|
||||
|
||||
signals:
|
||||
void sliderPressed();
|
||||
void sliderReleased();
|
||||
void sliderMoved(float value);
|
||||
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent * me) override;
|
||||
void dragEnterEvent(QDragEnterEvent * dee) override;
|
||||
void dropEvent(QDropEvent * de) override;
|
||||
void focusOutEvent(QFocusEvent * fe) override;
|
||||
void mousePressEvent(QMouseEvent * me) override;
|
||||
void mouseReleaseEvent(QMouseEvent * me) override;
|
||||
void mouseMoveEvent(QMouseEvent * me) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent * me) override;
|
||||
void paintEvent(QPaintEvent * me) override;
|
||||
void wheelEvent(QWheelEvent * me) override;
|
||||
|
||||
void enterEvent(QEvent *event) override;
|
||||
void leaveEvent(QEvent *event) override;
|
||||
|
||||
virtual float getValue(const QPoint & p);
|
||||
|
||||
private slots:
|
||||
virtual void enterValue();
|
||||
void friendlyUpdate();
|
||||
void toggleScale();
|
||||
|
||||
private:
|
||||
virtual QString displayValue() const;
|
||||
|
||||
void doConnections() override;
|
||||
|
||||
void showTextFloat(int msecBeforeDisplay, int msecDisplayTime);
|
||||
void setPosition(const QPoint & p);
|
||||
|
||||
inline float pageSize() const
|
||||
{
|
||||
return (model()->maxValue() - model()->minValue()) / 100.0f;
|
||||
}
|
||||
|
||||
static SimpleTextFloat * s_textFloat;
|
||||
|
||||
BoolModel m_volumeKnob;
|
||||
FloatModel m_volumeRatio;
|
||||
|
||||
QPoint m_lastMousePos; //!< mouse position in last mouseMoveEvent
|
||||
float m_leftOver;
|
||||
bool m_buttonPressed;
|
||||
|
||||
DirectionOfManipulation m_directionOfManipulation;
|
||||
};
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_FLOAT_MODEL_EDITOR_BASE_H
|
||||
@@ -23,9 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GRAPH_H
|
||||
#define GRAPH_H
|
||||
#ifndef LMMS_GUI_GRAPH_H
|
||||
#define LMMS_GUI_GRAPH_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPixmap>
|
||||
@@ -49,13 +48,12 @@ class LMMS_EXPORT Graph : public QWidget, public ModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum graphStyle
|
||||
enum class Style
|
||||
{
|
||||
NearestStyle, //!< draw as stairs
|
||||
LinearStyle, //!< connect each 2 samples with a line, with wrapping
|
||||
LinearNonCyclicStyle, //!< LinearStyle without wrapping
|
||||
BarStyle, //!< draw thick bars
|
||||
NumGraphStyles
|
||||
Nearest, //!< draw as stairs
|
||||
Linear, //!< connect each 2 samples with a line, with wrapping
|
||||
LinearNonCyclic, //!< Linear without wrapping
|
||||
Bar, //!< draw thick bars
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -63,7 +61,7 @@ public:
|
||||
* @param _width Pixel width of widget
|
||||
* @param _height Pixel height of widget
|
||||
*/
|
||||
Graph( QWidget * _parent, graphStyle _style = Graph::LinearStyle,
|
||||
Graph( QWidget * _parent, Style _style = Style::Linear,
|
||||
int _width = 132,
|
||||
int _height = 104
|
||||
);
|
||||
@@ -79,13 +77,13 @@ public:
|
||||
return castModel<graphModel>();
|
||||
}
|
||||
|
||||
inline graphStyle getGraphStyle()
|
||||
inline Style getGraphStyle()
|
||||
{
|
||||
return m_graphStyle;
|
||||
}
|
||||
|
||||
|
||||
inline void setGraphStyle( graphStyle _s )
|
||||
inline void setGraphStyle( Style _s )
|
||||
{
|
||||
m_graphStyle = _s;
|
||||
update();
|
||||
@@ -115,7 +113,7 @@ private:
|
||||
QPixmap m_foreground;
|
||||
QColor m_graphColor;
|
||||
|
||||
graphStyle m_graphStyle;
|
||||
Style m_graphStyle;
|
||||
|
||||
bool m_mouseDown;
|
||||
int m_lastCursorX;
|
||||
@@ -228,4 +226,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_GRAPH_H
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GROUP_BOX_H
|
||||
#define GROUP_BOX_H
|
||||
#ifndef LMMS_GUI_GROUP_BOX_H
|
||||
#define LMMS_GUI_GROUP_BOX_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
@@ -51,6 +50,21 @@ public:
|
||||
return m_led;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether the LED button is shown or not
|
||||
*
|
||||
* @return true LED button is shown
|
||||
* @return false LED button is hidden
|
||||
*/
|
||||
bool ledButtonShown() const;
|
||||
|
||||
/**
|
||||
* @brief Sets if the LED check box is shown or not
|
||||
*
|
||||
* @param value Set to true to show the LED check box or to false to hide it.
|
||||
*/
|
||||
void setLedButtonShown(bool value);
|
||||
|
||||
int titleBarHeight() const
|
||||
{
|
||||
return m_titleBarHeight;
|
||||
@@ -74,5 +88,4 @@ private:
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_GROUP_BOX_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GUIAPPLICATION_H
|
||||
#define GUIAPPLICATION_H
|
||||
#ifndef LMMS_GUI_GUI_APPLICATION_H
|
||||
#define LMMS_GUI_GUI_APPLICATION_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
@@ -96,4 +96,4 @@ LMMS_EXPORT GuiApplication* getGUI();
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // GUIAPPLICATION_H
|
||||
#endif // LMMS_GUI_GUI_APPLICATION_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IMPORT_FILTER_H
|
||||
#define IMPORT_FILTER_H
|
||||
#ifndef LMMS_IMPORT_FILTER_H
|
||||
#define LMMS_IMPORT_FILTER_H
|
||||
|
||||
#include <QFile>
|
||||
|
||||
@@ -114,4 +114,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_IMPORT_FILTER_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INLINE_AUTOMATION_H
|
||||
#define INLINE_AUTOMATION_H
|
||||
#ifndef LMMS_INLINE_AUTOMATION_H
|
||||
#define LMMS_INLINE_AUTOMATION_H
|
||||
|
||||
#include "AutomationNode.h"
|
||||
#include "AutomationClip.h"
|
||||
@@ -99,4 +99,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_INLINE_AUTOMATION_H
|
||||
|
||||
@@ -23,13 +23,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INSTRUMENT_H
|
||||
#define INSTRUMENT_H
|
||||
#ifndef LMMS_INSTRUMENT_H
|
||||
#define LMMS_INSTRUMENT_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "Flags.h"
|
||||
#include "lmms_export.h"
|
||||
#include "lmms_basics.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "Plugin.h"
|
||||
#include "TimePos.h"
|
||||
|
||||
@@ -45,9 +46,8 @@ class Track;
|
||||
|
||||
class LMMS_EXPORT Instrument : public Plugin
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
enum Flag
|
||||
enum class Flag
|
||||
{
|
||||
NoFlags = 0x00,
|
||||
IsSingleStreamed = 0x01, /*! Instrument provides a single audio stream for all notes */
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
IsNotBendable = 0x04, /*! Instrument can't react to pitch bend changes */
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(Flags, Flag);
|
||||
using Flags = lmms::Flags<Flag>;
|
||||
|
||||
Instrument(InstrumentTrack * _instrument_track,
|
||||
const Descriptor * _descriptor,
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
|
||||
virtual Flags flags() const
|
||||
{
|
||||
return NoFlags;
|
||||
return Flag::NoFlags;
|
||||
}
|
||||
|
||||
// sub-classes can re-implement this for receiving all incoming
|
||||
@@ -149,9 +149,9 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Instrument::Flags)
|
||||
LMMS_DECLARE_OPERATORS_FOR_FLAGS(Instrument::Flag)
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_INSTRUMENT_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INSTRUMENT_FUNCTION_VIEWS_H
|
||||
#define INSTRUMENT_FUNCTION_VIEWS_H
|
||||
#ifndef LMMS_INSTRUMENT_FUNCTION_VIEWS_H
|
||||
#define LMMS_INSTRUMENT_FUNCTION_VIEWS_H
|
||||
|
||||
#include "ModelView.h"
|
||||
|
||||
@@ -99,4 +99,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_INSTRUMENT_FUNCTION_VIEWS_H
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INSTRUMENT_FUNCTIONS_H
|
||||
#define INSTRUMENT_FUNCTIONS_H
|
||||
#ifndef LMMS_INSTRUMENT_FUNCTIONS_H
|
||||
#define LMMS_INSTRUMENT_FUNCTIONS_H
|
||||
|
||||
#include "JournallingObject.h"
|
||||
#include "lmms_basics.h"
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
struct ChordTable : public QVector<Chord>
|
||||
struct ChordTable
|
||||
{
|
||||
private:
|
||||
ChordTable();
|
||||
@@ -131,6 +131,7 @@ public:
|
||||
};
|
||||
|
||||
static std::array<Init, NUM_CHORD_TABLES> s_initTable;
|
||||
std::vector<Chord> m_chords;
|
||||
|
||||
public:
|
||||
static const ChordTable & getInstance()
|
||||
@@ -150,6 +151,11 @@ public:
|
||||
{
|
||||
return getByName( name, false );
|
||||
}
|
||||
|
||||
const std::vector<Chord>& chords() const
|
||||
{
|
||||
return m_chords;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -170,14 +176,13 @@ class InstrumentFunctionArpeggio : public Model, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ArpDirections
|
||||
enum class ArpDirection
|
||||
{
|
||||
ArpDirUp,
|
||||
ArpDirDown,
|
||||
ArpDirUpAndDown,
|
||||
ArpDirDownAndUp,
|
||||
ArpDirRandom,
|
||||
NumArpDirections
|
||||
Up,
|
||||
Down,
|
||||
UpAndDown,
|
||||
DownAndUp,
|
||||
Random
|
||||
} ;
|
||||
|
||||
InstrumentFunctionArpeggio( Model * _parent );
|
||||
@@ -196,11 +201,11 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
enum ArpModes
|
||||
enum class ArpMode
|
||||
{
|
||||
FreeMode,
|
||||
SortMode,
|
||||
SyncMode
|
||||
Free,
|
||||
Sort,
|
||||
Sync
|
||||
} ;
|
||||
|
||||
BoolModel m_arpEnabledModel;
|
||||
@@ -224,4 +229,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_INSTRUMENT_FUNCTIONS_H
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INSTRUMENT_MIDI_IO_VIEW_H
|
||||
#define INSTRUMENT_MIDI_IO_VIEW_H
|
||||
#ifndef LMMS_GUI_INSTRUMENT_MIDI_IO_VIEW_H
|
||||
#define LMMS_GUI_INSTRUMENT_MIDI_IO_VIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
@@ -76,4 +76,4 @@ private:
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_INSTRUMENT_MIDI_IO_VIEW_H
|
||||
|
||||
@@ -22,67 +22,38 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INSTRUMENT_PLAY_HANDLE_H
|
||||
#define INSTRUMENT_PLAY_HANDLE_H
|
||||
#ifndef LMMS_INSTRUMENT_PLAY_HANDLE_H
|
||||
#define LMMS_INSTRUMENT_PLAY_HANDLE_H
|
||||
|
||||
#include "PlayHandle.h"
|
||||
#include "Instrument.h"
|
||||
#include "NotePlayHandle.h"
|
||||
#include "lmms_export.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class Instrument;
|
||||
class InstrumentTrack;
|
||||
|
||||
class LMMS_EXPORT InstrumentPlayHandle : public PlayHandle
|
||||
{
|
||||
public:
|
||||
InstrumentPlayHandle( Instrument * instrument, InstrumentTrack* instrumentTrack );
|
||||
InstrumentPlayHandle(Instrument * instrument, InstrumentTrack* instrumentTrack);
|
||||
|
||||
~InstrumentPlayHandle() override = default;
|
||||
|
||||
|
||||
void play( sampleFrame * _working_buffer ) override
|
||||
{
|
||||
// ensure that all our nph's have been processed first
|
||||
ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack( m_instrument->instrumentTrack(), true );
|
||||
|
||||
bool nphsLeft;
|
||||
do
|
||||
{
|
||||
nphsLeft = false;
|
||||
for( const NotePlayHandle * constNotePlayHandle : nphv )
|
||||
{
|
||||
NotePlayHandle * notePlayHandle = const_cast<NotePlayHandle *>( constNotePlayHandle );
|
||||
if( notePlayHandle->state() != ThreadableJob::ProcessingState::Done &&
|
||||
!notePlayHandle->isFinished())
|
||||
{
|
||||
nphsLeft = true;
|
||||
notePlayHandle->process();
|
||||
}
|
||||
}
|
||||
}
|
||||
while( nphsLeft );
|
||||
|
||||
m_instrument->play( _working_buffer );
|
||||
}
|
||||
void play(sampleFrame * working_buffer) override;
|
||||
|
||||
bool isFinished() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isFromTrack( const Track* _track ) const override
|
||||
{
|
||||
return m_instrument->isFromTrack( _track );
|
||||
}
|
||||
|
||||
bool isFromTrack(const Track* track) const override;
|
||||
|
||||
private:
|
||||
Instrument* m_instrument;
|
||||
|
||||
} ;
|
||||
|
||||
};
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_INSTRUMENT_PLAY_HANDLE_H
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user