Merge branch 'master' into refac/memory
This commit is contained in:
@@ -22,14 +22,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ABOUT_DIALOG_H
|
||||
#define ABOUT_DIALOG_H
|
||||
#ifndef LMMS_GUI_ABOUT_DIALOG_H
|
||||
#define LMMS_GUI_ABOUT_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "ui_about_dialog.h"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class AboutDialog : public QDialog, public Ui::AboutDialog
|
||||
{
|
||||
@@ -38,6 +39,6 @@ public:
|
||||
|
||||
} ;
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LMMS_GUI_ABOUT_DIALOG_H
|
||||
|
||||
@@ -22,12 +22,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ACTION_GROUP_H
|
||||
#define ACTION_GROUP_H
|
||||
#ifndef LMMS_GUI_ACTION_GROUP_H
|
||||
#define LMMS_GUI_ACTION_GROUP_H
|
||||
|
||||
#include <QActionGroup>
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
/// \brief Convenience subclass of QActionGroup
|
||||
///
|
||||
/// This class provides the same functionality as QActionGroup, but in addition
|
||||
@@ -54,4 +56,6 @@ private:
|
||||
QList<QAction*> m_actions;
|
||||
};
|
||||
|
||||
#endif
|
||||
} // namespace lmms::gui
|
||||
|
||||
#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"
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
#include "AudioDevice.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioAlsa : public QThread, public AudioDevice
|
||||
{
|
||||
@@ -52,7 +54,7 @@ public:
|
||||
m_deviceName(deviceName),
|
||||
m_deviceDescription(deviceDescription)
|
||||
{}
|
||||
~DeviceInfo() {}
|
||||
~DeviceInfo() = default;
|
||||
|
||||
QString const & getDeviceName() const { return m_deviceName; }
|
||||
QString const & getDeviceDescription() const { return m_deviceDescription; }
|
||||
@@ -63,11 +65,11 @@ public:
|
||||
|
||||
};
|
||||
|
||||
typedef std::vector<DeviceInfo> DeviceInfoCollection;
|
||||
using DeviceInfoCollection = std::vector<DeviceInfo>;
|
||||
|
||||
public:
|
||||
AudioAlsa( bool & _success_ful, Mixer* mixer );
|
||||
virtual ~AudioAlsa();
|
||||
AudioAlsa( bool & _success_ful, AudioEngine* audioEngine );
|
||||
~AudioAlsa() override;
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
@@ -82,7 +84,6 @@ public:
|
||||
private:
|
||||
void startProcessing() override;
|
||||
void stopProcessing() override;
|
||||
void applyQualitySettings() override;
|
||||
void run() override;
|
||||
|
||||
int setHWParams( const ch_cnt_t _channels, snd_pcm_access_t _access );
|
||||
@@ -102,6 +103,8 @@ private:
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_HAVE_ALSA
|
||||
|
||||
#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"
|
||||
|
||||
@@ -35,8 +35,11 @@
|
||||
|
||||
|
||||
class QComboBox;
|
||||
class LcdSpinBox;
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class LcdSpinBox;
|
||||
|
||||
class AudioAlsaSetupWidget : public AudioDeviceSetupWidget
|
||||
{
|
||||
@@ -44,7 +47,7 @@ class AudioAlsaSetupWidget : public AudioDeviceSetupWidget
|
||||
|
||||
public:
|
||||
AudioAlsaSetupWidget( QWidget * _parent );
|
||||
virtual ~AudioAlsaSetupWidget();
|
||||
~AudioAlsaSetupWidget() override;
|
||||
|
||||
void saveSettings() override;
|
||||
|
||||
@@ -59,6 +62,8 @@ private:
|
||||
AudioAlsa::DeviceInfoCollection m_deviceInfos;
|
||||
};
|
||||
|
||||
#endif
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_HAVE_ALSA
|
||||
|
||||
#endif // LMMS_GUI_AUDIO_ALSA_SETUP_WIDGET_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* AudioDevice.h - base-class for audio-devices, used by LMMS-mixer
|
||||
* AudioDevice.h - base-class for audio-devices, used by LMMS audio engine
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -22,24 +22,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_DEVICE_H
|
||||
#define AUDIO_DEVICE_H
|
||||
#ifndef LMMS_AUDIO_DEVICE_H
|
||||
#define LMMS_AUDIO_DEVICE_H
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include <QMutex>
|
||||
#include <samplerate.h>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
|
||||
|
||||
class AudioPort;
|
||||
class Mixer;
|
||||
class QThread;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioEngine;
|
||||
class AudioPort;
|
||||
class SampleFrame;
|
||||
|
||||
|
||||
class AudioDevice
|
||||
{
|
||||
public:
|
||||
AudioDevice( const ch_cnt_t _channels, Mixer* mixer );
|
||||
AudioDevice( const ch_cnt_t _channels, AudioEngine* audioEngine );
|
||||
virtual ~AudioDevice();
|
||||
|
||||
inline void lock()
|
||||
@@ -86,27 +90,18 @@ public:
|
||||
|
||||
virtual void stopProcessing();
|
||||
|
||||
virtual void applyQualitySettings();
|
||||
|
||||
|
||||
|
||||
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 SampleFrame* /* _buf*/, const fpp_t /*_frames*/) {}
|
||||
|
||||
// called by according driver for fetching new sound-data
|
||||
fpp_t getNextBuffer( surroundSampleFrame * _ab );
|
||||
fpp_t getNextBuffer(SampleFrame* _ab);
|
||||
|
||||
// convert a given audio-buffer to a buffer in signed 16-bit samples
|
||||
// returns num of bytes in outbuf
|
||||
int convertToS16( const surroundSampleFrame * _ab,
|
||||
int convertToS16(const SampleFrame* _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain,
|
||||
int_sample_t * _output_buffer,
|
||||
const bool _convert_endian = false );
|
||||
|
||||
@@ -114,25 +109,16 @@ protected:
|
||||
void clearS16Buffer( int_sample_t * _outbuf,
|
||||
const fpp_t _frames );
|
||||
|
||||
// resample given buffer from samplerate _src_sr to samplerate _dst_sr
|
||||
fpp_t resample( const surroundSampleFrame * _src,
|
||||
const fpp_t _frames,
|
||||
surroundSampleFrame * _dst,
|
||||
const sample_rate_t _src_sr,
|
||||
const sample_rate_t _dst_sr );
|
||||
|
||||
inline void setSampleRate( const sample_rate_t _new_sr )
|
||||
{
|
||||
m_sampleRate = _new_sr;
|
||||
}
|
||||
|
||||
Mixer* mixer()
|
||||
AudioEngine* audioEngine()
|
||||
{
|
||||
return m_mixer;
|
||||
return m_audioEngine;
|
||||
}
|
||||
|
||||
bool hqAudio() const;
|
||||
|
||||
static void stopProcessingThread( QThread * thread );
|
||||
|
||||
|
||||
@@ -143,17 +129,15 @@ protected:
|
||||
private:
|
||||
sample_rate_t m_sampleRate;
|
||||
ch_cnt_t m_channels;
|
||||
Mixer* m_mixer;
|
||||
AudioEngine* m_audioEngine;
|
||||
bool m_inProcess;
|
||||
|
||||
QMutex m_devMutex;
|
||||
|
||||
SRC_DATA m_srcData;
|
||||
SRC_STATE * m_srcState;
|
||||
SampleFrame* m_buffer;
|
||||
|
||||
surroundSampleFrame * m_buffer;
|
||||
};
|
||||
|
||||
} ;
|
||||
} // 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,24 +23,27 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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:
|
||||
AudioDeviceSetupWidget( const QString & _caption, QWidget * _parent );
|
||||
|
||||
virtual ~AudioDeviceSetupWidget();
|
||||
~AudioDeviceSetupWidget() override = default;
|
||||
|
||||
virtual void saveSettings() = 0;
|
||||
|
||||
virtual void show();
|
||||
};
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H
|
||||
|
||||
@@ -22,26 +22,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_DUMMY_H
|
||||
#define AUDIO_DUMMY_H
|
||||
#ifndef LMMS_AUDIO_DUMMY_H
|
||||
#define LMMS_AUDIO_DUMMY_H
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
#include "AudioEngine.h"
|
||||
#include "MicroTimer.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioDummy : public QThread, public AudioDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioDummy( bool & _success_ful, Mixer* mixer ) :
|
||||
AudioDevice( DEFAULT_CHANNELS, mixer )
|
||||
AudioDummy( bool & _success_ful, AudioEngine* audioEngine ) :
|
||||
AudioDevice( DEFAULT_CHANNELS, audioEngine )
|
||||
{
|
||||
_success_ful = true;
|
||||
}
|
||||
|
||||
virtual ~AudioDummy()
|
||||
~AudioDummy() override
|
||||
{
|
||||
stopProcessing();
|
||||
}
|
||||
@@ -52,17 +54,15 @@ public:
|
||||
}
|
||||
|
||||
|
||||
class setupWidget : public AudioDeviceSetupWidget
|
||||
class setupWidget : public gui::AudioDeviceSetupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent ) :
|
||||
AudioDeviceSetupWidget( AudioDummy::name(), _parent )
|
||||
gui::AudioDeviceSetupWidget( AudioDummy::name(), _parent )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~setupWidget()
|
||||
{
|
||||
}
|
||||
~setupWidget() override = default;
|
||||
|
||||
void saveSettings() override
|
||||
{
|
||||
@@ -94,17 +94,17 @@ private:
|
||||
while( true )
|
||||
{
|
||||
timer.reset();
|
||||
const surroundSampleFrame* b = mixer()->nextBuffer();
|
||||
const SampleFrame* b = audioEngine()->nextBuffer();
|
||||
if( !b )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( mixer()->hasFifoWriter() )
|
||||
if( audioEngine()->hasFifoWriter() )
|
||||
{
|
||||
delete[] b;
|
||||
}
|
||||
|
||||
const int microseconds = static_cast<int>( mixer()->framesPerPeriod() * 1000000.0f / mixer()->processingSampleRate() - timer.elapsed() );
|
||||
const int microseconds = static_cast<int>( audioEngine()->framesPerPeriod() * 1000000.0f / audioEngine()->outputSampleRate() - timer.elapsed() );
|
||||
if( microseconds > 0 )
|
||||
{
|
||||
usleep( microseconds );
|
||||
@@ -114,5 +114,6 @@ private:
|
||||
|
||||
} ;
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_DUMMY_H
|
||||
|
||||
412
include/AudioEngine.h
Normal file
412
include/AudioEngine.h
Normal file
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
* AudioEngine.h - device-independent audio engine for LMMS
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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_ENGINE_H
|
||||
#define LMMS_AUDIO_ENGINE_H
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <QThread>
|
||||
#include <samplerate.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "SampleFrame.h"
|
||||
#include "LocklessList.h"
|
||||
#include "FifoBuffer.h"
|
||||
#include "AudioEngineProfiler.h"
|
||||
#include "PlayHandle.h"
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioDevice;
|
||||
class MidiClient;
|
||||
class AudioPort;
|
||||
class AudioEngineWorkerThread;
|
||||
|
||||
|
||||
constexpr fpp_t MINIMUM_BUFFER_SIZE = 32;
|
||||
constexpr fpp_t DEFAULT_BUFFER_SIZE = 256;
|
||||
constexpr fpp_t MAXIMUM_BUFFER_SIZE = 4096;
|
||||
|
||||
constexpr int BYTES_PER_SAMPLE = sizeof(sample_t);
|
||||
constexpr int BYTES_PER_INT_SAMPLE = sizeof(int_sample_t);
|
||||
constexpr int BYTES_PER_FRAME = sizeof(SampleFrame);
|
||||
|
||||
constexpr float OUTPUT_SAMPLE_MULTIPLIER = 32767.0f;
|
||||
|
||||
class LMMS_EXPORT AudioEngine : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief RAII helper for requestChangesInModel.
|
||||
* Used by AudioEngine::requestChangesGuard.
|
||||
*/
|
||||
class RequestChangesGuard {
|
||||
friend class AudioEngine;
|
||||
|
||||
private:
|
||||
RequestChangesGuard(AudioEngine* audioEngine)
|
||||
: m_audioEngine{audioEngine}
|
||||
{
|
||||
m_audioEngine->requestChangeInModel();
|
||||
}
|
||||
public:
|
||||
|
||||
RequestChangesGuard()
|
||||
: m_audioEngine{nullptr}
|
||||
{
|
||||
}
|
||||
|
||||
RequestChangesGuard(RequestChangesGuard&& other)
|
||||
: RequestChangesGuard()
|
||||
{
|
||||
std::swap(other.m_audioEngine, m_audioEngine);
|
||||
}
|
||||
|
||||
// Disallow copy.
|
||||
RequestChangesGuard(const RequestChangesGuard&) = delete;
|
||||
RequestChangesGuard& operator=(const RequestChangesGuard&) = delete;
|
||||
|
||||
~RequestChangesGuard() {
|
||||
if (m_audioEngine) {
|
||||
m_audioEngine->doneChangeInModel();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
AudioEngine* m_audioEngine;
|
||||
};
|
||||
|
||||
struct qualitySettings
|
||||
{
|
||||
enum class Interpolation
|
||||
{
|
||||
Linear,
|
||||
SincFastest,
|
||||
SincMedium,
|
||||
SincBest
|
||||
} ;
|
||||
|
||||
Interpolation interpolation;
|
||||
|
||||
qualitySettings(Interpolation i) :
|
||||
interpolation(i)
|
||||
{
|
||||
}
|
||||
|
||||
int libsrcInterpolation() const
|
||||
{
|
||||
switch( interpolation )
|
||||
{
|
||||
case Interpolation::Linear:
|
||||
return SRC_ZERO_ORDER_HOLD;
|
||||
case Interpolation::SincFastest:
|
||||
return SRC_SINC_FASTEST;
|
||||
case Interpolation::SincMedium:
|
||||
return SRC_SINC_MEDIUM_QUALITY;
|
||||
case Interpolation::SincBest:
|
||||
return SRC_SINC_BEST_QUALITY;
|
||||
}
|
||||
return SRC_LINEAR;
|
||||
}
|
||||
} ;
|
||||
|
||||
void initDevices();
|
||||
void clear();
|
||||
void clearNewPlayHandles();
|
||||
|
||||
|
||||
// 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
|
||||
{
|
||||
return m_audioDevName;
|
||||
}
|
||||
inline bool audioDevStartFailed() const
|
||||
{
|
||||
return m_audioDevStartFailed;
|
||||
}
|
||||
|
||||
//! Set new audio device. Old device will be deleted,
|
||||
//! unless it's stored using storeAudioDevice
|
||||
void setAudioDevice( AudioDevice * _dev,
|
||||
const struct qualitySettings & _qs,
|
||||
bool _needs_fifo,
|
||||
bool startNow );
|
||||
void storeAudioDevice();
|
||||
void restoreAudioDevice();
|
||||
inline AudioDevice * audioDev()
|
||||
{
|
||||
return m_audioDev;
|
||||
}
|
||||
|
||||
|
||||
// audio-port-stuff
|
||||
inline void addAudioPort(AudioPort * port)
|
||||
{
|
||||
requestChangeInModel();
|
||||
m_audioPorts.push_back(port);
|
||||
doneChangeInModel();
|
||||
}
|
||||
|
||||
void removeAudioPort(AudioPort * port);
|
||||
|
||||
|
||||
// MIDI-client-stuff
|
||||
inline const QString & midiClientName() const
|
||||
{
|
||||
return m_midiClientName;
|
||||
}
|
||||
|
||||
inline MidiClient * midiClient()
|
||||
{
|
||||
return m_midiClient;
|
||||
}
|
||||
|
||||
|
||||
// play-handle stuff
|
||||
bool addPlayHandle( PlayHandle* handle );
|
||||
|
||||
void removePlayHandle( PlayHandle* handle );
|
||||
|
||||
inline PlayHandleList& playHandles()
|
||||
{
|
||||
return m_playHandles;
|
||||
}
|
||||
|
||||
void removePlayHandlesOfTypes(Track * track, PlayHandle::Types types);
|
||||
|
||||
|
||||
// methods providing information for other classes
|
||||
inline fpp_t framesPerPeriod() const
|
||||
{
|
||||
return m_framesPerPeriod;
|
||||
}
|
||||
|
||||
|
||||
AudioEngineProfiler& profiler()
|
||||
{
|
||||
return m_profiler;
|
||||
}
|
||||
|
||||
int cpuLoad() const
|
||||
{
|
||||
return m_profiler.cpuLoad();
|
||||
}
|
||||
|
||||
int detailLoad(const AudioEngineProfiler::DetailType type) const
|
||||
{
|
||||
return m_profiler.detailLoad(type);
|
||||
}
|
||||
|
||||
const qualitySettings & currentQualitySettings() const
|
||||
{
|
||||
return m_qualitySettings;
|
||||
}
|
||||
|
||||
|
||||
sample_rate_t baseSampleRate() const;
|
||||
sample_rate_t outputSampleRate() const;
|
||||
sample_rate_t inputSampleRate() const;
|
||||
|
||||
inline float masterGain() const
|
||||
{
|
||||
return m_masterGain;
|
||||
}
|
||||
|
||||
inline void setMasterGain(const float mo)
|
||||
{
|
||||
m_masterGain = mo;
|
||||
}
|
||||
|
||||
|
||||
static inline sample_t clip(const sample_t s)
|
||||
{
|
||||
if (s > 1.0f)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
else if (s < -1.0f)
|
||||
{
|
||||
return -1.0f;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
bool criticalXRuns() const;
|
||||
|
||||
inline bool hasFifoWriter() const
|
||||
{
|
||||
return m_fifoWriter != nullptr;
|
||||
}
|
||||
|
||||
void pushInputFrames( SampleFrame* _ab, const f_cnt_t _frames );
|
||||
|
||||
inline const SampleFrame* inputBuffer()
|
||||
{
|
||||
return m_inputBuffer[ m_inputBufferRead ];
|
||||
}
|
||||
|
||||
inline f_cnt_t inputBufferFrames() const
|
||||
{
|
||||
return m_inputBufferFrames[ m_inputBufferRead ];
|
||||
}
|
||||
|
||||
inline const SampleFrame* nextBuffer()
|
||||
{
|
||||
return hasFifoWriter() ? m_fifo->read() : renderNextBuffer();
|
||||
}
|
||||
|
||||
void changeQuality(const struct qualitySettings & qs);
|
||||
|
||||
//! Block until a change in model can be done (i.e. wait for audio thread)
|
||||
void requestChangeInModel();
|
||||
void doneChangeInModel();
|
||||
|
||||
RequestChangesGuard requestChangesGuard()
|
||||
{
|
||||
return RequestChangesGuard{this};
|
||||
}
|
||||
|
||||
static bool isAudioDevNameValid(QString name);
|
||||
static bool isMidiDevNameValid(QString name);
|
||||
|
||||
|
||||
signals:
|
||||
void qualitySettingsChanged();
|
||||
void sampleRateChanged();
|
||||
void nextAudioBuffer(const lmms::SampleFrame* buffer);
|
||||
|
||||
|
||||
private:
|
||||
using Fifo = FifoBuffer<SampleFrame*>;
|
||||
|
||||
class fifoWriter : public QThread
|
||||
{
|
||||
public:
|
||||
fifoWriter( AudioEngine * audioEngine, Fifo * fifo );
|
||||
|
||||
void finish();
|
||||
|
||||
|
||||
private:
|
||||
AudioEngine * m_audioEngine;
|
||||
Fifo * m_fifo;
|
||||
volatile bool m_writing;
|
||||
|
||||
void run() override;
|
||||
|
||||
void write(SampleFrame* buffer);
|
||||
} ;
|
||||
|
||||
|
||||
AudioEngine( bool renderOnly );
|
||||
~AudioEngine() override;
|
||||
|
||||
void startProcessing(bool needsFifo = true);
|
||||
void stopProcessing();
|
||||
|
||||
|
||||
AudioDevice * tryAudioDevices();
|
||||
MidiClient * tryMidiClients();
|
||||
|
||||
void renderStageNoteSetup();
|
||||
void renderStageInstruments();
|
||||
void renderStageEffects();
|
||||
void renderStageMix();
|
||||
|
||||
const SampleFrame* renderNextBuffer();
|
||||
|
||||
void swapBuffers();
|
||||
|
||||
void clearInternal();
|
||||
|
||||
bool m_renderOnly;
|
||||
|
||||
std::vector<AudioPort *> m_audioPorts;
|
||||
|
||||
fpp_t m_framesPerPeriod;
|
||||
|
||||
SampleFrame* m_inputBuffer[2];
|
||||
f_cnt_t m_inputBufferFrames[2];
|
||||
f_cnt_t m_inputBufferSize[2];
|
||||
int m_inputBufferRead;
|
||||
int m_inputBufferWrite;
|
||||
|
||||
std::unique_ptr<SampleFrame[]> m_outputBufferRead;
|
||||
std::unique_ptr<SampleFrame[]> m_outputBufferWrite;
|
||||
|
||||
// worker thread stuff
|
||||
std::vector<AudioEngineWorkerThread *> m_workers;
|
||||
int m_numWorkers;
|
||||
|
||||
// playhandle stuff
|
||||
PlayHandleList m_playHandles;
|
||||
// place where new playhandles are added temporarily
|
||||
LocklessList<PlayHandle *> m_newPlayHandles;
|
||||
ConstPlayHandleList m_playHandlesToRemove;
|
||||
|
||||
|
||||
struct qualitySettings m_qualitySettings;
|
||||
float m_masterGain;
|
||||
|
||||
// audio device stuff
|
||||
void doSetAudioDevice( AudioDevice *_dev );
|
||||
AudioDevice * m_audioDev;
|
||||
AudioDevice * m_oldAudioDev;
|
||||
QString m_audioDevName;
|
||||
bool m_audioDevStartFailed;
|
||||
|
||||
// MIDI device stuff
|
||||
MidiClient * m_midiClient;
|
||||
QString m_midiClientName;
|
||||
|
||||
// FIFO stuff
|
||||
Fifo * m_fifo;
|
||||
fifoWriter * m_fifoWriter;
|
||||
|
||||
AudioEngineProfiler m_profiler;
|
||||
|
||||
bool m_clearSignal;
|
||||
|
||||
std::recursive_mutex m_changeMutex;
|
||||
|
||||
friend class Engine;
|
||||
friend class AudioEngineWorkerThread;
|
||||
friend class ProjectRenderer;
|
||||
} ;
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_AUDIO_ENGINE_H
|
||||
111
include/AudioEngineProfiler.h
Normal file
111
include/AudioEngineProfiler.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* AudioEngineProfiler.h - class for profiling performance of AudioEngine
|
||||
*
|
||||
* Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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_ENGINE_PROFILER_H
|
||||
#define LMMS_AUDIO_ENGINE_PROFILER_H
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <QFile>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "MicroTimer.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioEngineProfiler
|
||||
{
|
||||
public:
|
||||
AudioEngineProfiler();
|
||||
~AudioEngineProfiler() = default;
|
||||
|
||||
void startPeriod()
|
||||
{
|
||||
m_periodTimer.reset();
|
||||
}
|
||||
|
||||
void finishPeriod( sample_rate_t sampleRate, fpp_t framesPerPeriod );
|
||||
|
||||
int cpuLoad() const
|
||||
{
|
||||
return m_cpuLoad;
|
||||
}
|
||||
|
||||
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;
|
||||
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 // LMMS_AUDIO_ENGINE_PROFILER_H
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* MixerWorkerThread.h - declaration of class MixerWorkerThread
|
||||
* AudioEngineWorkerThread.h - declaration of class AudioEngineWorkerThread
|
||||
*
|
||||
* Copyright (c) 2009-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -22,18 +22,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MIXER_WORKER_THREAD_H
|
||||
#define MIXER_WORKER_THREAD_H
|
||||
#ifndef LMMS_AUDIO_ENGINE_WORKER_THREAD_H
|
||||
#define LMMS_AUDIO_ENGINE_WORKER_THREAD_H
|
||||
|
||||
#include <QtCore/QThread>
|
||||
#include <QThread>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
class QWaitCondition;
|
||||
class Mixer;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioEngine;
|
||||
class ThreadableJob;
|
||||
|
||||
class MixerWorkerThread : public QThread
|
||||
class AudioEngineWorkerThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -41,18 +45,19 @@ public:
|
||||
class JobQueue
|
||||
{
|
||||
public:
|
||||
enum OperationMode
|
||||
enum class OperationMode
|
||||
{
|
||||
Static, // no jobs added while processing queue
|
||||
Dynamic // jobs can be added while processing queue
|
||||
} ;
|
||||
|
||||
#define JOB_QUEUE_SIZE 8192
|
||||
static constexpr size_t JOB_QUEUE_SIZE = 8192;
|
||||
|
||||
JobQueue() :
|
||||
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);
|
||||
}
|
||||
@@ -66,20 +71,19 @@ public:
|
||||
|
||||
private:
|
||||
std::atomic<ThreadableJob*> m_items[JOB_QUEUE_SIZE];
|
||||
std::atomic_int m_writeIndex;
|
||||
std::atomic_int m_itemsDone;
|
||||
std::atomic_size_t m_writeIndex;
|
||||
std::atomic_size_t m_itemsDone;
|
||||
OperationMode m_opMode;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
MixerWorkerThread( Mixer* mixer );
|
||||
virtual ~MixerWorkerThread();
|
||||
AudioEngineWorkerThread( AudioEngine* audioEngine );
|
||||
~AudioEngineWorkerThread() override;
|
||||
|
||||
virtual void quit();
|
||||
|
||||
static void resetJobQueue( JobQueue::OperationMode _opMode =
|
||||
JobQueue::Static )
|
||||
JobQueue::OperationMode::Static )
|
||||
{
|
||||
globalJobQueue.reset( _opMode );
|
||||
}
|
||||
@@ -93,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,11 +114,11 @@ private:
|
||||
|
||||
static JobQueue globalJobQueue;
|
||||
static QWaitCondition * queueReadyWaitCond;
|
||||
static QList<MixerWorkerThread *> workerThreads;
|
||||
static QList<AudioEngineWorkerThread *> workerThreads;
|
||||
|
||||
volatile bool m_quit;
|
||||
|
||||
} ;
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_ENGINE_WORKER_THREAD_H
|
||||
@@ -23,22 +23,24 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_FILE_DEVICE_H
|
||||
#define AUDIO_FILE_DEVICE_H
|
||||
#ifndef LMMS_AUDIO_FILE_DEVICE_H
|
||||
#define LMMS_AUDIO_FILE_DEVICE_H
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QFile>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "OutputSettings.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioFileDevice : public AudioDevice
|
||||
{
|
||||
public:
|
||||
AudioFileDevice(OutputSettings const & outputSettings,
|
||||
const ch_cnt_t _channels, const QString & _file,
|
||||
Mixer* mixer );
|
||||
virtual ~AudioFileDevice();
|
||||
AudioEngine* audioEngine );
|
||||
~AudioFileDevice() override;
|
||||
|
||||
QString outputFile() const
|
||||
{
|
||||
@@ -66,13 +68,9 @@ private:
|
||||
OutputSettings m_outputSettings;
|
||||
} ;
|
||||
|
||||
using AudioFileDeviceInstantiaton
|
||||
= AudioFileDevice* (*)(const QString&, const OutputSettings&, const ch_cnt_t, AudioEngine*, bool&);
|
||||
|
||||
typedef AudioFileDevice * ( * AudioFileDeviceInstantiaton )
|
||||
( const QString & outputFilename,
|
||||
OutputSettings const & outputSettings,
|
||||
const ch_cnt_t channels,
|
||||
Mixer* mixer,
|
||||
bool & successful );
|
||||
} // namespace lmms
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_FILE_DEVICE_H
|
||||
|
||||
@@ -22,30 +22,33 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
#include "AudioFileDevice.h"
|
||||
#include <sndfile.h>
|
||||
|
||||
class AudioFileFlac: public AudioFileDevice
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioFileFlac : public AudioFileDevice
|
||||
{
|
||||
public:
|
||||
AudioFileFlac(OutputSettings const& outputSettings,
|
||||
ch_cnt_t const channels,
|
||||
bool& successful,
|
||||
QString const& file,
|
||||
Mixer* mixer
|
||||
AudioEngine* audioEngine
|
||||
);
|
||||
|
||||
virtual ~AudioFileFlac();
|
||||
~AudioFileFlac() override;
|
||||
|
||||
static AudioFileDevice* getInst(QString const& outputFilename,
|
||||
OutputSettings const& outputSettings,
|
||||
ch_cnt_t const channels,
|
||||
Mixer* mixer,
|
||||
AudioEngine* audioEngine,
|
||||
bool& successful)
|
||||
{
|
||||
return new AudioFileFlac(
|
||||
@@ -53,7 +56,7 @@ public:
|
||||
channels,
|
||||
successful,
|
||||
outputFilename,
|
||||
mixer
|
||||
audioEngine
|
||||
);
|
||||
}
|
||||
|
||||
@@ -62,13 +65,14 @@ private:
|
||||
SF_INFO m_sfinfo;
|
||||
SNDFILE* m_sf;
|
||||
|
||||
virtual void writeBuffer(surroundSampleFrame const* _ab,
|
||||
fpp_t const frames,
|
||||
float master_gain) override;
|
||||
void writeBuffer(const SampleFrame* _ab, fpp_t const frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
|
||||
};
|
||||
|
||||
#endif //AUDIO_FILE_FLAC_H
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#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"
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#include "lame/lame.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioFileMP3 : public AudioFileDevice
|
||||
{
|
||||
@@ -42,23 +44,21 @@ public:
|
||||
const ch_cnt_t _channels,
|
||||
bool & successful,
|
||||
const QString & _file,
|
||||
Mixer* mixer );
|
||||
virtual ~AudioFileMP3();
|
||||
AudioEngine* audioEngine );
|
||||
~AudioFileMP3() override;
|
||||
|
||||
static AudioFileDevice * getInst( const QString & outputFilename,
|
||||
OutputSettings const & outputSettings,
|
||||
const ch_cnt_t channels,
|
||||
Mixer* mixer,
|
||||
AudioEngine* audioEngine,
|
||||
bool & successful )
|
||||
{
|
||||
return new AudioFileMP3( outputSettings, channels, successful,
|
||||
outputFilename, mixer );
|
||||
outputFilename, audioEngine );
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void writeBuffer( const surroundSampleFrame * /* _buf*/,
|
||||
const fpp_t /*_frames*/,
|
||||
const float /*_master_gain*/ ) override;
|
||||
void writeBuffer(const SampleFrame* /* _buf*/, const fpp_t /*_frames*/) override;
|
||||
|
||||
private:
|
||||
void flushRemainingBuffers();
|
||||
@@ -69,6 +69,8 @@ private:
|
||||
lame_t m_lame;
|
||||
};
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_HAVE_MP3LAME
|
||||
|
||||
#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"
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#include "AudioFileDevice.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioFileOgg : public AudioFileDevice
|
||||
{
|
||||
@@ -42,24 +44,21 @@ public:
|
||||
const ch_cnt_t _channels,
|
||||
bool & _success_ful,
|
||||
const QString & _file,
|
||||
Mixer* mixer );
|
||||
virtual ~AudioFileOgg();
|
||||
AudioEngine* audioEngine );
|
||||
~AudioFileOgg() override;
|
||||
|
||||
static AudioFileDevice * getInst( const QString & outputFilename,
|
||||
OutputSettings const & outputSettings,
|
||||
const ch_cnt_t channels,
|
||||
Mixer* mixer,
|
||||
AudioEngine* audioEngine,
|
||||
bool & successful )
|
||||
{
|
||||
return new AudioFileOgg( outputSettings, channels, successful,
|
||||
outputFilename, mixer );
|
||||
return new AudioFileOgg( outputSettings, channels, successful, outputFilename, audioEngine );
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
virtual void writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain ) override;
|
||||
void writeBuffer(const SampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
@@ -108,6 +107,8 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_HAVE_OGGVORBIS
|
||||
|
||||
#endif // LMMS_AUDIO_FILE_OGG_H
|
||||
|
||||
@@ -23,14 +23,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioFileWave : public AudioFileDevice
|
||||
{
|
||||
@@ -39,24 +41,22 @@ public:
|
||||
const ch_cnt_t channels,
|
||||
bool & successful,
|
||||
const QString & file,
|
||||
Mixer* mixer );
|
||||
virtual ~AudioFileWave();
|
||||
AudioEngine* audioEngine );
|
||||
~AudioFileWave() override;
|
||||
|
||||
static AudioFileDevice * getInst( const QString & outputFilename,
|
||||
OutputSettings const & outputSettings,
|
||||
const ch_cnt_t channels,
|
||||
Mixer* mixer,
|
||||
AudioEngine* audioEngine,
|
||||
bool & successful )
|
||||
{
|
||||
return new AudioFileWave( outputSettings, channels, successful,
|
||||
outputFilename, mixer );
|
||||
outputFilename, audioEngine );
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
virtual void writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
float _master_gain ) override;
|
||||
void writeBuffer(const SampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
@@ -66,4 +66,7 @@ private:
|
||||
SNDFILE * m_sf;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#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"
|
||||
|
||||
@@ -31,109 +31,107 @@
|
||||
#ifndef LMMS_HAVE_WEAKJACK
|
||||
#include <jack/jack.h>
|
||||
#else
|
||||
#include "weak_libjack.h"
|
||||
#include <weak_libjack.h>
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <vector>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
|
||||
class QLineEdit;
|
||||
class LcdSpinBox;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class MidiJack;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class LcdSpinBox;
|
||||
}
|
||||
|
||||
|
||||
class AudioJack : public QObject, public AudioDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioJack( bool & _success_ful, Mixer* mixer );
|
||||
virtual ~AudioJack();
|
||||
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);
|
||||
void removeMidiClient(void) { m_midiClient = nullptr; }
|
||||
jack_client_t * jackClient() {return m_client;};
|
||||
AudioJack* addMidiClient(MidiJack* midiClient);
|
||||
void removeMidiClient() { m_midiClient = nullptr; }
|
||||
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 AudioDeviceSetupWidget
|
||||
class setupWidget : public gui::AudioDeviceSetupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
virtual ~setupWidget();
|
||||
setupWidget(QWidget* parent);
|
||||
~setupWidget() override;
|
||||
|
||||
virtual void saveSettings();
|
||||
void saveSettings() override;
|
||||
|
||||
private:
|
||||
QLineEdit * m_clientName;
|
||||
LcdSpinBox * m_channels;
|
||||
|
||||
} ;
|
||||
|
||||
QLineEdit* m_clientName;
|
||||
gui::LcdSpinBox* m_channels;
|
||||
};
|
||||
|
||||
private slots:
|
||||
void restartAfterZombified();
|
||||
|
||||
|
||||
private:
|
||||
bool initJackClient();
|
||||
|
||||
virtual void startProcessing();
|
||||
virtual void stopProcessing();
|
||||
virtual void applyQualitySettings();
|
||||
void startProcessing() override;
|
||||
void stopProcessing() override;
|
||||
|
||||
virtual void registerPort( AudioPort * _port );
|
||||
virtual void unregisterPort( AudioPort * _port );
|
||||
virtual void renamePort( AudioPort * _port );
|
||||
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;
|
||||
SampleFrame* 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];
|
||||
};
|
||||
|
||||
typedef QMap<AudioPort *, StereoPort> JackPortMap;
|
||||
using JackPortMap = QMap<AudioPort*, StereoPort>;
|
||||
JackPortMap m_portMap;
|
||||
#endif
|
||||
|
||||
signals:
|
||||
void zombified();
|
||||
};
|
||||
|
||||
} ;
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#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"
|
||||
|
||||
@@ -34,17 +34,24 @@
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
|
||||
|
||||
class LcdSpinBox;
|
||||
class QLineEdit;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class LcdSpinBox;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class AudioOss : public QThread, public AudioDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioOss( bool & _success_ful, Mixer* mixer );
|
||||
virtual ~AudioOss();
|
||||
AudioOss( bool & _success_ful, AudioEngine* audioEngine );
|
||||
~AudioOss() override;
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
@@ -54,17 +61,17 @@ public:
|
||||
static QString probeDevice();
|
||||
|
||||
|
||||
class setupWidget : public AudioDeviceSetupWidget
|
||||
class setupWidget : public gui::AudioDeviceSetupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
virtual ~setupWidget();
|
||||
~setupWidget() override;
|
||||
|
||||
void saveSettings() override;
|
||||
|
||||
private:
|
||||
QLineEdit * m_device;
|
||||
LcdSpinBox * m_channels;
|
||||
gui::LcdSpinBox * m_channels;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -72,7 +79,6 @@ public:
|
||||
private:
|
||||
void startProcessing() override;
|
||||
void stopProcessing() override;
|
||||
void applyQualitySettings() override;
|
||||
void run() override;
|
||||
|
||||
int m_audioFD;
|
||||
@@ -81,7 +87,8 @@ private:
|
||||
|
||||
} ;
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_HAVE_OSS
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_OSS_H
|
||||
|
||||
@@ -22,31 +22,31 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_PORT_H
|
||||
#define AUDIO_PORT_H
|
||||
#ifndef LMMS_AUDIO_PORT_H
|
||||
#define LMMS_AUDIO_PORT_H
|
||||
|
||||
#include <memory>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QMutexLocker>
|
||||
#include <QString>
|
||||
#include <QMutex>
|
||||
|
||||
#include "MemoryManager.h"
|
||||
#include "PlayHandle.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class EffectChain;
|
||||
class FloatModel;
|
||||
class BoolModel;
|
||||
|
||||
class AudioPort : public ThreadableJob
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
AudioPort( const QString & _name, bool _has_effect_chain = true,
|
||||
FloatModel * volumeModel = NULL, FloatModel * panningModel = NULL,
|
||||
BoolModel * mutedModel = NULL );
|
||||
FloatModel * volumeModel = nullptr, FloatModel * panningModel = nullptr,
|
||||
BoolModel * mutedModel = nullptr );
|
||||
virtual ~AudioPort();
|
||||
|
||||
inline sampleFrame * buffer()
|
||||
inline SampleFrame* buffer()
|
||||
{
|
||||
return m_portBuffer;
|
||||
}
|
||||
@@ -71,11 +71,11 @@ public:
|
||||
void setExtOutputEnabled( bool _enabled );
|
||||
|
||||
|
||||
// next effect-channel after this audio-port
|
||||
// next mixer-channel after this audio-port
|
||||
// (-1 = none 0 = master)
|
||||
inline fx_ch_t nextFxChannel() const
|
||||
inline mix_ch_t nextMixerChannel() const
|
||||
{
|
||||
return m_nextFxChannel;
|
||||
return m_nextMixerChannel;
|
||||
}
|
||||
|
||||
inline EffectChain * effects()
|
||||
@@ -83,9 +83,9 @@ public:
|
||||
return m_effects.get();
|
||||
}
|
||||
|
||||
void setNextFxChannel( const fx_ch_t _chnl )
|
||||
void setNextMixerChannel( const mix_ch_t _chnl )
|
||||
{
|
||||
m_nextFxChannel = _chnl;
|
||||
m_nextMixerChannel = _chnl;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,11 +112,11 @@ public:
|
||||
private:
|
||||
volatile bool m_bufferUsage;
|
||||
|
||||
sampleFrame * m_portBuffer;
|
||||
SampleFrame* m_portBuffer;
|
||||
QMutex m_portBufferLock;
|
||||
|
||||
bool m_extOutputEnabled;
|
||||
fx_ch_t m_nextFxChannel;
|
||||
mix_ch_t m_nextMixerChannel;
|
||||
|
||||
QString m_name;
|
||||
|
||||
@@ -129,10 +129,11 @@ private:
|
||||
FloatModel * m_panningModel;
|
||||
BoolModel * m_mutedModel;
|
||||
|
||||
friend class Mixer;
|
||||
friend class MixerWorkerThread;
|
||||
friend class AudioEngine;
|
||||
friend class AudioEngineWorkerThread;
|
||||
|
||||
} ;
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_PORT_H
|
||||
|
||||
@@ -22,17 +22,36 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_PORTAUDIO_H
|
||||
#define AUDIO_PORTAUDIO_H
|
||||
#ifndef LMMS_AUDIO_PORTAUDIO_H
|
||||
#define LMMS_AUDIO_PORTAUDIO_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QObject>
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
#include "ComboBoxModel.h"
|
||||
|
||||
#ifdef LMMS_HAVE_PORTAUDIO
|
||||
|
||||
# include <portaudio.h>
|
||||
|
||||
# include "AudioDevice.h"
|
||||
# include "AudioDeviceSetupWidget.h"
|
||||
|
||||
# if defined paNeverDropInput || defined paNonInterleaved
|
||||
# define PORTAUDIO_V19
|
||||
# else
|
||||
# define PORTAUDIO_V18
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioPortAudioSetupUtil : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public slots:
|
||||
void updateBackends();
|
||||
void updateDevices();
|
||||
@@ -41,66 +60,51 @@ public slots:
|
||||
public:
|
||||
ComboBoxModel m_backendModel;
|
||||
ComboBoxModel m_deviceModel;
|
||||
} ;
|
||||
};
|
||||
|
||||
|
||||
#ifdef LMMS_HAVE_PORTAUDIO
|
||||
|
||||
#include <portaudio.h>
|
||||
|
||||
#include <QtCore/QSemaphore>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
|
||||
#if defined paNeverDropInput || defined paNonInterleaved
|
||||
# define PORTAUDIO_V19
|
||||
#else
|
||||
# define PORTAUDIO_V18
|
||||
#endif
|
||||
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class ComboBox;
|
||||
class LcdSpinBox;
|
||||
}
|
||||
|
||||
|
||||
class AudioPortAudio : public AudioDevice
|
||||
{
|
||||
public:
|
||||
AudioPortAudio( bool & _success_ful, Mixer* mixer );
|
||||
virtual ~AudioPortAudio();
|
||||
AudioPortAudio( bool & _success_ful, AudioEngine* audioEngine );
|
||||
~AudioPortAudio() override;
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "PortAudio" );
|
||||
}
|
||||
|
||||
int process_callback(const float* _inputBuffer, float* _outputBuffer, f_cnt_t _framesPerBuffer);
|
||||
|
||||
int process_callback( const float *_inputBuffer,
|
||||
float * _outputBuffer,
|
||||
unsigned long _framesPerBuffer );
|
||||
|
||||
|
||||
class setupWidget : public AudioDeviceSetupWidget
|
||||
class setupWidget : public gui::AudioDeviceSetupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
virtual ~setupWidget();
|
||||
~setupWidget() override;
|
||||
|
||||
virtual void saveSettings();
|
||||
virtual void show();
|
||||
void saveSettings() override;
|
||||
void show() override;
|
||||
|
||||
private:
|
||||
ComboBox * m_backend;
|
||||
ComboBox * m_device;
|
||||
gui::ComboBox * m_backend;
|
||||
gui::ComboBox * m_device;
|
||||
AudioPortAudioSetupUtil m_setupUtil;
|
||||
|
||||
} ;
|
||||
|
||||
private:
|
||||
virtual void startProcessing();
|
||||
virtual void stopProcessing();
|
||||
virtual void applyQualitySettings();
|
||||
void startProcessing() override;
|
||||
void stopProcessing() override;
|
||||
|
||||
#ifdef PORTAUDIO_V19
|
||||
static int _process_callback( const void *_inputBuffer, void * _outputBuffer,
|
||||
@@ -122,10 +126,10 @@ private:
|
||||
unsigned long _framesPerBuffer, PaTimestamp _outTime, void * _arg );
|
||||
|
||||
|
||||
typedef double PaTime;
|
||||
typedef PaDeviceID PaDeviceIndex;
|
||||
using PaTime = double;
|
||||
using PaDeviceIndex = PaDeviceID;
|
||||
|
||||
typedef struct PaStreamParameters
|
||||
using PaStreamParameters = struct
|
||||
{
|
||||
PaDeviceIndex device;
|
||||
int channelCount;
|
||||
@@ -134,7 +138,7 @@ private:
|
||||
void *hostApiSpecificStreamInfo;
|
||||
|
||||
} PaStreamParameters;
|
||||
#endif
|
||||
#endif // PORTAUDIO_V19
|
||||
|
||||
PaStream * m_paStream;
|
||||
PaStreamParameters m_outputParameters;
|
||||
@@ -142,14 +146,16 @@ private:
|
||||
|
||||
bool m_wasPAInitError;
|
||||
|
||||
surroundSampleFrame * m_outBuf;
|
||||
int m_outBufPos;
|
||||
int m_outBufSize;
|
||||
SampleFrame* m_outBuf;
|
||||
std::size_t m_outBufPos;
|
||||
fpp_t m_outBufSize;
|
||||
|
||||
bool m_stopped;
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
#endif // LMMS_HAVE_PORTAUDIO
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#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"
|
||||
|
||||
@@ -36,17 +36,23 @@
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
|
||||
|
||||
class LcdSpinBox;
|
||||
class QLineEdit;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class LcdSpinBox;
|
||||
}
|
||||
|
||||
|
||||
class AudioPulseAudio : public QThread, public AudioDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioPulseAudio( bool & _success_ful, Mixer* mixer );
|
||||
virtual ~AudioPulseAudio();
|
||||
AudioPulseAudio( bool & _success_ful, AudioEngine* audioEngine );
|
||||
~AudioPulseAudio() override;
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
@@ -56,17 +62,17 @@ public:
|
||||
static QString probeDevice();
|
||||
|
||||
|
||||
class setupWidget : public AudioDeviceSetupWidget
|
||||
class setupWidget : public gui::AudioDeviceSetupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
virtual ~setupWidget();
|
||||
~setupWidget() override;
|
||||
|
||||
void saveSettings() override;
|
||||
|
||||
private:
|
||||
QLineEdit * m_device;
|
||||
LcdSpinBox * m_channels;
|
||||
gui::LcdSpinBox * m_channels;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -82,7 +88,6 @@ public:
|
||||
private:
|
||||
void startProcessing() override;
|
||||
void stopProcessing() override;
|
||||
void applyQualitySettings() override;
|
||||
void run() override;
|
||||
|
||||
volatile bool m_quit;
|
||||
@@ -94,6 +99,8 @@ private:
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_HAVE_PULSEAUDIO
|
||||
|
||||
#endif // LMMS_AUDIO_PULSEAUDIO_H
|
||||
|
||||
65
include/AudioResampler.h
Normal file
65
include/AudioResampler.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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; }
|
||||
void setRatio(double ratio);
|
||||
|
||||
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,37 +23,38 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_SAMPLE_RECORDER_H
|
||||
#define AUDIO_SAMPLE_RECORDER_H
|
||||
#ifndef LMMS_AUDIO_SAMPLE_RECORDER_H
|
||||
#define LMMS_AUDIO_SAMPLE_RECORDER_H
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QPair>
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
#include <memory>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class SampleBuffer;
|
||||
|
||||
|
||||
class AudioSampleRecorder : public AudioDevice
|
||||
{
|
||||
public:
|
||||
AudioSampleRecorder( const ch_cnt_t _channels, bool & _success_ful,
|
||||
Mixer* mixer );
|
||||
virtual ~AudioSampleRecorder();
|
||||
AudioSampleRecorder( const ch_cnt_t _channels, bool & _success_ful, AudioEngine* audioEngine );
|
||||
~AudioSampleRecorder() override;
|
||||
|
||||
f_cnt_t framesRecorded() const;
|
||||
void createSampleBuffer( SampleBuffer** sampleBuffer );
|
||||
|
||||
std::shared_ptr<const SampleBuffer> createSampleBuffer();
|
||||
|
||||
private:
|
||||
virtual void writeBuffer( const surroundSampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain ) override;
|
||||
void writeBuffer(const SampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
typedef QList<QPair<sampleFrame *, fpp_t> > BufferList;
|
||||
using BufferList = QList<QPair<SampleFrame*, fpp_t>>;
|
||||
BufferList m_buffers;
|
||||
|
||||
} ;
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUDIO_SAMPLE_RECORDER_H
|
||||
|
||||
@@ -22,32 +22,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_SDL_H
|
||||
#define AUDIO_SDL_H
|
||||
#ifndef LMMS_AUDIO_SDL_H
|
||||
#define LMMS_AUDIO_SDL_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_SDL
|
||||
|
||||
#ifdef LMMS_HAVE_SDL2
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_audio.h>
|
||||
#else
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_audio.h>
|
||||
#endif
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
|
||||
class QLineEdit;
|
||||
class QComboBox;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioSdl : public AudioDevice
|
||||
{
|
||||
public:
|
||||
AudioSdl( bool & _success_ful, Mixer* mixer );
|
||||
virtual ~AudioSdl();
|
||||
AudioSdl( bool & _success_ful, AudioEngine* audioEngine );
|
||||
~AudioSdl() override;
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
@@ -56,59 +52,54 @@ public:
|
||||
}
|
||||
|
||||
|
||||
class setupWidget : public AudioDeviceSetupWidget
|
||||
class setupWidget : public gui::AudioDeviceSetupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
~setupWidget() override;
|
||||
~setupWidget() override = default;
|
||||
|
||||
void saveSettings() override;
|
||||
|
||||
private:
|
||||
void populatePlaybackDeviceComboBox();
|
||||
void populateInputDeviceComboBox();
|
||||
|
||||
private:
|
||||
QLineEdit * m_device;
|
||||
QComboBox* m_playbackDeviceComboBox = nullptr;
|
||||
QComboBox* m_inputDeviceComboBox = nullptr;
|
||||
|
||||
static QString s_systemDefaultDevice;
|
||||
} ;
|
||||
|
||||
|
||||
private:
|
||||
void startProcessing() override;
|
||||
void stopProcessing() override;
|
||||
void applyQualitySettings() override;
|
||||
|
||||
static void sdlAudioCallback( void * _udata, Uint8 * _buf, int _len );
|
||||
void sdlAudioCallback( Uint8 * _buf, int _len );
|
||||
|
||||
#ifdef LMMS_HAVE_SDL2
|
||||
static void sdlInputAudioCallback( void * _udata, Uint8 * _buf, int _len );
|
||||
void sdlInputAudioCallback( Uint8 * _buf, int _len );
|
||||
#endif
|
||||
|
||||
SDL_AudioSpec m_audioHandle;
|
||||
|
||||
surroundSampleFrame * m_outBuf;
|
||||
SampleFrame* m_outBuf;
|
||||
|
||||
#ifdef LMMS_HAVE_SDL2
|
||||
size_t m_currentBufferFramePos;
|
||||
size_t m_currentBufferFramesCount;
|
||||
#else
|
||||
Uint8 * m_convertedBuf;
|
||||
int m_convertedBufPos;
|
||||
int m_convertedBufSize;
|
||||
bool m_outConvertEndian;
|
||||
#endif
|
||||
|
||||
|
||||
bool m_stopped;
|
||||
|
||||
#ifdef LMMS_HAVE_SDL2
|
||||
SDL_AudioDeviceID m_outputDevice;
|
||||
|
||||
SDL_AudioSpec m_inputAudioHandle;
|
||||
SDL_AudioDeviceID m_inputDevice;
|
||||
#endif
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_HAVE_SDL
|
||||
|
||||
#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"
|
||||
|
||||
@@ -36,40 +36,46 @@
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
|
||||
class LcdSpinBox;
|
||||
class QLineEdit;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class LcdSpinBox;
|
||||
}
|
||||
|
||||
|
||||
class AudioSndio : public QThread, public AudioDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioSndio( bool & _success_ful, Mixer * _mixer );
|
||||
virtual ~AudioSndio();
|
||||
AudioSndio( bool & _success_ful, AudioEngine * _audioEngine );
|
||||
~AudioSndio() override;
|
||||
|
||||
inline static QString name( void )
|
||||
inline static QString name()
|
||||
{
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "sndio" );
|
||||
}
|
||||
|
||||
class setupWidget : public AudioDeviceSetupWidget
|
||||
class setupWidget : public gui::AudioDeviceSetupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
virtual ~setupWidget();
|
||||
~setupWidget() override = default;
|
||||
|
||||
void saveSettings( void ) override;
|
||||
void saveSettings() override;
|
||||
|
||||
private:
|
||||
QLineEdit * m_device;
|
||||
LcdSpinBox * m_channels;
|
||||
gui::LcdSpinBox * m_channels;
|
||||
} ;
|
||||
|
||||
private:
|
||||
void startProcessing( void ) override;
|
||||
void stopProcessing( void ) override;
|
||||
void applyQualitySettings( void ) override;
|
||||
void run( void ) override;
|
||||
void startProcessing() override;
|
||||
void stopProcessing() override;
|
||||
void run() override;
|
||||
|
||||
struct sio_hdl *m_hdl;
|
||||
struct sio_par m_par;
|
||||
@@ -78,6 +84,8 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
#endif /* LMMS_HAVE_SNDIO */
|
||||
} // namespace lmms
|
||||
|
||||
#endif /* _AUDIO_SNDIO_H */
|
||||
#endif // LMMS_HAVE_SNDIO
|
||||
|
||||
#endif // LMMS_AUDIO_SNDIO_H
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_SOUNDIO_H
|
||||
#define AUDIO_SOUNDIO_H
|
||||
#ifndef LMMS_AUDIO_SOUNDIO_H
|
||||
#define LMMS_AUDIO_SOUNDIO_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QObject>
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
#include "ComboBoxModel.h"
|
||||
@@ -37,15 +37,21 @@
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class ComboBox;
|
||||
class LcdSpinBox;
|
||||
}
|
||||
|
||||
// Exists only to work around "Error: Meta object features not supported for nested classes"
|
||||
class AudioSoundIoSetupUtil : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~AudioSoundIoSetupUtil();
|
||||
virtual ~AudioSoundIoSetupUtil() = default;
|
||||
|
||||
void *m_setupWidget;
|
||||
public slots:
|
||||
@@ -56,7 +62,7 @@ public slots:
|
||||
class AudioSoundIo : public AudioDevice
|
||||
{
|
||||
public:
|
||||
AudioSoundIo( bool & _success_ful, Mixer* mixer );
|
||||
AudioSoundIo( bool & _success_ful, AudioEngine* audioEngine );
|
||||
virtual ~AudioSoundIo();
|
||||
|
||||
inline static QString name()
|
||||
@@ -64,7 +70,7 @@ public:
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "soundio" );
|
||||
}
|
||||
|
||||
class setupWidget : public AudioDeviceSetupWidget
|
||||
class setupWidget : public gui::AudioDeviceSetupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
@@ -78,8 +84,8 @@ public:
|
||||
private:
|
||||
|
||||
AudioSoundIoSetupUtil m_setupUtil;
|
||||
ComboBox * m_backend;
|
||||
ComboBox * m_device;
|
||||
gui::ComboBox * m_backend;
|
||||
gui::ComboBox * m_device;
|
||||
|
||||
ComboBoxModel m_backendModel;
|
||||
ComboBoxModel m_deviceModel;
|
||||
@@ -104,7 +110,7 @@ private:
|
||||
SoundIo *m_soundio;
|
||||
SoundIoOutStream *m_outstream;
|
||||
|
||||
surroundSampleFrame * m_outBuf;
|
||||
SampleFrame* m_outBuf;
|
||||
int m_outBufSize;
|
||||
fpp_t m_outBufFramesTotal;
|
||||
fpp_t m_outBufFrameIndex;
|
||||
@@ -134,6 +140,9 @@ private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_HAVE_SOUNDIO
|
||||
|
||||
#endif // LMMS_AUDIO_SOUNDIO_H
|
||||
|
||||
@@ -22,14 +22,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef AUTOMATABLE_BUTTON_H
|
||||
#define AUTOMATABLE_BUTTON_H
|
||||
#ifndef LMMS_GUI_AUTOMATABLE_BUTTON_H
|
||||
#define LMMS_GUI_AUTOMATABLE_BUTTON_H
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
#include "AutomatableModelView.h"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class automatableButtonGroup;
|
||||
|
||||
@@ -40,7 +41,7 @@ class LMMS_EXPORT AutomatableButton : public QPushButton, public BoolModelView
|
||||
public:
|
||||
AutomatableButton( QWidget * _parent, const QString & _name
|
||||
= QString() );
|
||||
virtual ~AutomatableButton();
|
||||
~AutomatableButton() override;
|
||||
|
||||
inline void setCheckable( bool _on )
|
||||
{
|
||||
@@ -85,7 +86,7 @@ class LMMS_EXPORT automatableButtonGroup : public QWidget, public IntModelView
|
||||
public:
|
||||
automatableButtonGroup( QWidget * _parent, const QString & _name
|
||||
= QString() );
|
||||
virtual ~automatableButtonGroup();
|
||||
~automatableButtonGroup() override;
|
||||
|
||||
void addButton( AutomatableButton * _btn );
|
||||
void removeButton( AutomatableButton * _btn );
|
||||
@@ -105,5 +106,6 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_AUTOMATABLE_BUTTON_H
|
||||
|
||||
@@ -22,19 +22,24 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATABLE_MODEL_H
|
||||
#define AUTOMATABLE_MODEL_H
|
||||
#ifndef LMMS_AUTOMATABLE_MODEL_H
|
||||
#define LMMS_AUTOMATABLE_MODEL_H
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QMutex>
|
||||
#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"
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
// simple way to map a property of a view to a model
|
||||
#define mapPropertyFromModelPtr(type,getfunc,setfunc,modelname) \
|
||||
public: \
|
||||
@@ -72,12 +77,10 @@ class ControllerConnection;
|
||||
class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
MM_OPERATORS
|
||||
public:
|
||||
using AutoModelVector = std::vector<AutomatableModel*>;
|
||||
|
||||
typedef QVector<AutomatableModel *> AutoModelVector;
|
||||
|
||||
enum ScaleType
|
||||
enum class ScaleType
|
||||
{
|
||||
Linear,
|
||||
Logarithmic,
|
||||
@@ -85,7 +88,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
virtual ~AutomatableModel();
|
||||
~AutomatableModel() override;
|
||||
|
||||
// Implement those by using the MODEL_IS_VISITABLE macro
|
||||
virtual void accept(ModelVisitor& v) = 0;
|
||||
@@ -120,7 +123,7 @@ public:
|
||||
bool isAutomated() const;
|
||||
bool isAutomatedOrControlled() const
|
||||
{
|
||||
return isAutomated() || m_controllerConnection != NULL;
|
||||
return isAutomated() || m_controllerConnection != nullptr;
|
||||
}
|
||||
|
||||
ControllerConnection* controllerConnection() const
|
||||
@@ -141,14 +144,25 @@ public:
|
||||
template<bool>
|
||||
static bool castValue( const float v )
|
||||
{
|
||||
return ( qRound( v ) != 0 );
|
||||
return (std::round(v) != 0);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline T value( int frameOffset = 0 ) const
|
||||
{
|
||||
if( hasLinkedModels() || m_controllerConnection != NULL )
|
||||
if (m_controllerConnection)
|
||||
{
|
||||
if (!m_useControllerValue)
|
||||
{
|
||||
return castValue<T>(m_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return castValue<T>(controllerValue(frameOffset));
|
||||
}
|
||||
}
|
||||
else if (hasLinkedModels())
|
||||
{
|
||||
return castValue<T>( controllerValue( frameOffset ) );
|
||||
}
|
||||
@@ -217,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 );
|
||||
@@ -298,9 +312,15 @@ public:
|
||||
s_periodCounter = 0;
|
||||
}
|
||||
|
||||
bool useControllerValue()
|
||||
{
|
||||
return m_useControllerValue;
|
||||
}
|
||||
|
||||
public slots:
|
||||
virtual void reset();
|
||||
void unlinkControllerConnection();
|
||||
void setUseControllerValue(bool b = true);
|
||||
|
||||
|
||||
protected:
|
||||
@@ -309,7 +329,7 @@ protected:
|
||||
const float min = 0,
|
||||
const float max = 0,
|
||||
const float step = 0,
|
||||
Model* parent = NULL,
|
||||
Model* parent = nullptr,
|
||||
const QString& displayName = QString(),
|
||||
bool defaultConstructed = false );
|
||||
//! returns a value which is in range between min() and
|
||||
@@ -395,9 +415,11 @@ private:
|
||||
// prevent several threads from attempting to write the same vb at the same time
|
||||
QMutex m_valueBufferMutex;
|
||||
|
||||
bool m_useControllerValue;
|
||||
|
||||
signals:
|
||||
void initValueChanged( float val );
|
||||
void destroyed( jo_id_t id );
|
||||
void destroyed( lmms::jo_id_t id );
|
||||
|
||||
} ;
|
||||
|
||||
@@ -438,7 +460,7 @@ class LMMS_EXPORT FloatModel : public TypedAutomatableModel<float>
|
||||
MODEL_IS_VISITABLE
|
||||
public:
|
||||
FloatModel( float val = 0, float min = 0, float max = 0, float step = 0,
|
||||
Model * parent = NULL,
|
||||
Model * parent = nullptr,
|
||||
const QString& displayName = QString(),
|
||||
bool defaultConstructed = false ) :
|
||||
TypedAutomatableModel( val, min, max, step, parent, displayName, defaultConstructed )
|
||||
@@ -456,7 +478,7 @@ class LMMS_EXPORT IntModel : public TypedAutomatableModel<int>
|
||||
MODEL_IS_VISITABLE
|
||||
public:
|
||||
IntModel( int val = 0, int min = 0, int max = 0,
|
||||
Model* parent = NULL,
|
||||
Model* parent = nullptr,
|
||||
const QString& displayName = QString(),
|
||||
bool defaultConstructed = false ) :
|
||||
TypedAutomatableModel( val, min, max, 1, parent, displayName, defaultConstructed )
|
||||
@@ -472,7 +494,7 @@ class LMMS_EXPORT BoolModel : public TypedAutomatableModel<bool>
|
||||
MODEL_IS_VISITABLE
|
||||
public:
|
||||
BoolModel( const bool val = false,
|
||||
Model* parent = NULL,
|
||||
Model* parent = nullptr,
|
||||
const QString& displayName = QString(),
|
||||
bool defaultConstructed = false ) :
|
||||
TypedAutomatableModel( val, false, true, 1, parent, displayName, defaultConstructed )
|
||||
@@ -481,7 +503,8 @@ public:
|
||||
QString displayValue( const float val ) const override;
|
||||
} ;
|
||||
|
||||
typedef QMap<AutomatableModel*, float> AutomatedValueMap;
|
||||
using AutomatedValueMap = QMap<AutomatableModel*, float>;
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#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"
|
||||
@@ -32,11 +32,14 @@
|
||||
class QMenu;
|
||||
class QMouseEvent;
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class LMMS_EXPORT AutomatableModelView : public ModelView
|
||||
{
|
||||
public:
|
||||
AutomatableModelView( Model* model, QWidget* _this );
|
||||
virtual ~AutomatableModelView() = default;
|
||||
~AutomatableModelView() override = default;
|
||||
|
||||
// some basic functions for convenience
|
||||
AutomatableModel* modelUntyped()
|
||||
@@ -132,5 +135,6 @@ using FloatModelView = TypedModelView<FloatModel>;
|
||||
using IntModelView = TypedModelView<IntModel>;
|
||||
using BoolModelView = TypedModelView<BoolModel>;
|
||||
|
||||
#endif
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_AUTOMATABLE_MODEL_VIEW_H
|
||||
|
||||
@@ -22,22 +22,23 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef AUTOMATABLE_SLIDER_H
|
||||
#define AUTOMATABLE_SLIDER_H
|
||||
#ifndef LMMS_GUI_AUTOMATABLE_SLIDER_H
|
||||
#define LMMS_GUI_AUTOMATABLE_SLIDER_H
|
||||
|
||||
#include <QSlider>
|
||||
|
||||
#include "AutomatableModelView.h"
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class AutomatableSlider : public QSlider, public IntModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AutomatableSlider( QWidget * _parent, const QString & _name = QString() );
|
||||
virtual ~AutomatableSlider();
|
||||
~AutomatableSlider() override = default;
|
||||
|
||||
bool showStatus()
|
||||
{
|
||||
@@ -71,7 +72,8 @@ private slots:
|
||||
} ;
|
||||
|
||||
|
||||
typedef IntModel sliderModel;
|
||||
using sliderModel = IntModel;
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_AUTOMATABLE_SLIDER_H
|
||||
|
||||
300
include/AutomationClip.h
Normal file
300
include/AutomationClip.h
Normal file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* AutomationClip.h - declaration of class AutomationClip, which contains
|
||||
* all information about an automation clip
|
||||
*
|
||||
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
*
|
||||
* 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_AUTOMATION_CLIP_H
|
||||
#define LMMS_AUTOMATION_CLIP_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QPointer>
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
|
||||
#include <QRecursiveMutex>
|
||||
#endif
|
||||
|
||||
#include "AutomationNode.h"
|
||||
#include "Clip.h"
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AutomationTrack;
|
||||
class TimePos;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class AutomationClipView;
|
||||
class AutomationEditor;
|
||||
} // namespace gui
|
||||
|
||||
|
||||
|
||||
class LMMS_EXPORT AutomationClip : public Clip
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum class ProgressionType
|
||||
{
|
||||
Discrete,
|
||||
Linear,
|
||||
CubicHermite
|
||||
} ;
|
||||
|
||||
using timeMap = QMap<int, AutomationNode>;
|
||||
using objectVector = std::vector<QPointer<AutomatableModel>>;
|
||||
|
||||
using TimemapIterator = timeMap::const_iterator;
|
||||
|
||||
AutomationClip( AutomationTrack * _auto_track );
|
||||
AutomationClip( const AutomationClip & _clip_to_copy );
|
||||
~AutomationClip() override = default;
|
||||
|
||||
bool addObject( AutomatableModel * _obj, bool _search_dup = true );
|
||||
|
||||
const AutomatableModel * firstObject() const;
|
||||
const objectVector& objects() const;
|
||||
|
||||
// progression-type stuff
|
||||
inline ProgressionType progressionType() const
|
||||
{
|
||||
return m_progressionType;
|
||||
}
|
||||
void setProgressionType( ProgressionType _new_progression_type );
|
||||
|
||||
inline float getTension() const
|
||||
{
|
||||
return m_tension;
|
||||
}
|
||||
void setTension( QString _new_tension );
|
||||
|
||||
TimePos timeMapLength() const;
|
||||
void updateLength();
|
||||
|
||||
TimePos putValue(
|
||||
const TimePos & time,
|
||||
const float value,
|
||||
const bool quantPos = true,
|
||||
const bool ignoreSurroundingPoints = true
|
||||
);
|
||||
|
||||
TimePos putValues(
|
||||
const TimePos & time,
|
||||
const float inValue,
|
||||
const float outValue,
|
||||
const bool quantPos = true,
|
||||
const bool ignoreSurroundingPoints = true
|
||||
);
|
||||
|
||||
void removeNode(const TimePos & time);
|
||||
void removeNodes(const int tick0, const int tick1);
|
||||
|
||||
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,
|
||||
const float value,
|
||||
const bool quantPos = true,
|
||||
const bool controlKey = false );
|
||||
|
||||
void applyDragValue();
|
||||
|
||||
|
||||
bool isDragging() const
|
||||
{
|
||||
return m_dragging;
|
||||
}
|
||||
|
||||
inline const timeMap & getTimeMap() const
|
||||
{
|
||||
return m_timeMap;
|
||||
}
|
||||
|
||||
inline timeMap & getTimeMap()
|
||||
{
|
||||
return m_timeMap;
|
||||
}
|
||||
|
||||
inline float getMin() const
|
||||
{
|
||||
return firstObject()->minValue<float>();
|
||||
}
|
||||
|
||||
inline float getMax() const
|
||||
{
|
||||
return firstObject()->maxValue<float>();
|
||||
}
|
||||
|
||||
inline bool hasAutomation() const
|
||||
{
|
||||
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;
|
||||
|
||||
QString name() const;
|
||||
|
||||
// settings-management
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
|
||||
static const QString classNodeName() { return "automationclip"; }
|
||||
QString nodeName() const override { return classNodeName(); }
|
||||
|
||||
gui::ClipView * createView( gui::TrackView * _tv ) override;
|
||||
|
||||
|
||||
static bool isAutomated( const AutomatableModel * _m );
|
||||
static std::vector<AutomationClip*> clipsForModel(const AutomatableModel* _m);
|
||||
static AutomationClip * globalAutomationClip( AutomatableModel * _m );
|
||||
static void resolveAllIDs();
|
||||
|
||||
bool isRecording() const { return m_isRecording; }
|
||||
void setRecording( const bool b ) { m_isRecording = b; }
|
||||
|
||||
static int quantization() { return s_quantization; }
|
||||
static void setQuantization(int q) { s_quantization = q; }
|
||||
|
||||
public slots:
|
||||
void clear();
|
||||
void objectDestroyed( lmms::jo_id_t );
|
||||
void flipY( int min, int max );
|
||||
void flipY();
|
||||
void flipX( int length = -1 );
|
||||
|
||||
private:
|
||||
void cleanObjects();
|
||||
void generateTangents();
|
||||
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))
|
||||
mutable QRecursiveMutex m_clipMutex;
|
||||
#else
|
||||
mutable QMutex m_clipMutex;
|
||||
#endif
|
||||
|
||||
AutomationTrack * m_autoTrack;
|
||||
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;
|
||||
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;
|
||||
|
||||
static int s_quantization;
|
||||
|
||||
static const float DEFAULT_MIN_VALUE;
|
||||
static const float DEFAULT_MAX_VALUE;
|
||||
|
||||
friend class gui::AutomationClipView;
|
||||
friend class AutomationNode;
|
||||
friend class gui::AutomationEditor;
|
||||
|
||||
} ;
|
||||
|
||||
//Short-hand functions to access node values in an automation clip;
|
||||
// replacement for CPP macros with the same purpose; could be refactored
|
||||
// further in the future.
|
||||
inline float INVAL(AutomationClip::TimemapIterator it)
|
||||
{
|
||||
return it->getInValue();
|
||||
}
|
||||
|
||||
inline float OUTVAL(AutomationClip::TimemapIterator it)
|
||||
{
|
||||
return it->getOutValue();
|
||||
}
|
||||
|
||||
inline float OFFSET(AutomationClip::TimemapIterator it)
|
||||
{
|
||||
return it->getValueOffset();
|
||||
}
|
||||
|
||||
inline float INTAN(AutomationClip::TimemapIterator it)
|
||||
{
|
||||
return it->getInTangent();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_AUTOMATION_CLIP_H
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* AutomationPatternView.h - declaration of class AutomationPatternView
|
||||
* AutomationClipView.h - declaration of class AutomationClipView
|
||||
*
|
||||
* Copyright (c) 2008-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -22,28 +22,33 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATION_PATTERN_VIEW_H
|
||||
#define AUTOMATION_PATTERN_VIEW_H
|
||||
#ifndef LMMS_GUI_AUTOMATION_CLIP_VIEW_H
|
||||
#define LMMS_GUI_AUTOMATION_CLIP_VIEW_H
|
||||
|
||||
#include <QStaticText>
|
||||
|
||||
#include "AutomationPattern.h"
|
||||
#include "Song.h"
|
||||
#include "SongEditor.h"
|
||||
#include "TrackContentObjectView.h"
|
||||
#include "ClipView.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AutomationClip;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
class AutomationPatternView : public TrackContentObjectView
|
||||
class AutomationClipView : public ClipView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
AutomationPatternView( AutomationPattern * _pat, TrackView * _parent );
|
||||
virtual ~AutomationPatternView();
|
||||
AutomationClipView( AutomationClip * _clip, TrackView * _parent );
|
||||
~AutomationClipView() override = default;
|
||||
|
||||
public slots:
|
||||
/// Opens this view's pattern in the global automation editor
|
||||
/// Opens this view's clip in the global automation editor
|
||||
void openInAutomationEditor();
|
||||
void update() override;
|
||||
|
||||
@@ -65,15 +70,16 @@ protected:
|
||||
|
||||
|
||||
private:
|
||||
AutomationPattern * m_pat;
|
||||
AutomationClip * m_clip;
|
||||
QPixmap m_paintPixmap;
|
||||
|
||||
QStaticText m_staticTextName;
|
||||
|
||||
static QPixmap * s_pat_rec;
|
||||
|
||||
void scaleTimemapToFit( float oldMin, float oldMax );
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GUI_AUTOMATION_CLIP_VIEW_H
|
||||
@@ -23,28 +23,36 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATION_EDITOR_H
|
||||
#define AUTOMATION_EDITOR_H
|
||||
#ifndef LMMS_GUI_AUTOMATION_EDITOR_H
|
||||
#define LMMS_GUI_AUTOMATION_EDITOR_H
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include <QVector>
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
#include <array>
|
||||
|
||||
#include "Editor.h"
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "TimePos.h"
|
||||
#include "AutomationPattern.h"
|
||||
#include "AutomationClip.h"
|
||||
#include "ComboBoxModel.h"
|
||||
#include "Knob.h"
|
||||
#include "Editor.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "MidiClip.h"
|
||||
#include "SampleClip.h"
|
||||
#include "TimePos.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
class QPainter;
|
||||
class QPixmap;
|
||||
class QScrollBar;
|
||||
|
||||
class ComboBox;
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class NotePlayHandle;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class Knob;
|
||||
class ComboBox;
|
||||
class TimeLineWidget;
|
||||
|
||||
|
||||
@@ -52,25 +60,32 @@ class TimeLineWidget;
|
||||
class AutomationEditor : public QWidget, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor barLineColor READ barLineColor WRITE setBarLineColor)
|
||||
Q_PROPERTY(QColor beatLineColor READ beatLineColor WRITE setBeatLineColor)
|
||||
Q_PROPERTY(QColor lineColor READ lineColor WRITE setLineColor)
|
||||
Q_PROPERTY(QColor vertexColor READ vertexColor WRITE setVertexColor)
|
||||
Q_PROPERTY(QBrush scaleColor READ scaleColor WRITE setScaleColor)
|
||||
Q_PROPERTY(QBrush graphColor READ graphColor WRITE setGraphColor)
|
||||
Q_PROPERTY(QColor crossColor READ crossColor WRITE setCrossColor)
|
||||
Q_PROPERTY(QColor backgroundShade READ backgroundShade WRITE setBackgroundShade)
|
||||
Q_PROPERTY(QColor barLineColor MEMBER m_barLineColor)
|
||||
Q_PROPERTY(QColor beatLineColor MEMBER m_beatLineColor)
|
||||
Q_PROPERTY(QColor lineColor MEMBER m_lineColor)
|
||||
Q_PROPERTY(QColor 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 setCurrentPattern(AutomationPattern * new_pattern);
|
||||
void setCurrentClip(AutomationClip * new_clip);
|
||||
void setGhostMidiClip(MidiClip* newMidiClip);
|
||||
void setGhostSample(SampleClip* newSample);
|
||||
|
||||
inline const AutomationPattern * currentPattern() const
|
||||
inline const AutomationClip * currentClip() const
|
||||
{
|
||||
return m_pattern;
|
||||
return m_clip;
|
||||
}
|
||||
|
||||
inline bool validPattern() const
|
||||
inline bool validClip() const
|
||||
{
|
||||
return m_pattern != nullptr && m_pattern->hasAutomation();
|
||||
return m_clip != nullptr;
|
||||
}
|
||||
|
||||
void saveSettings(QDomDocument & doc, QDomElement & parent) override;
|
||||
@@ -80,43 +95,26 @@ public:
|
||||
return "automationeditor";
|
||||
}
|
||||
|
||||
// qproperty access methods
|
||||
QColor barLineColor() const;
|
||||
void setBarLineColor(const QColor & c);
|
||||
QColor beatLineColor() const;
|
||||
void setBeatLineColor(const QColor & c);
|
||||
QColor lineColor() const;
|
||||
void setLineColor(const QColor & c);
|
||||
QBrush graphColor() const;
|
||||
void setGraphColor(const QBrush & c);
|
||||
QColor vertexColor() const;
|
||||
void setVertexColor(const QColor & c);
|
||||
QBrush scaleColor() const;
|
||||
void setScaleColor(const QBrush & c);
|
||||
QColor crossColor() const;
|
||||
void setCrossColor(const QColor & c);
|
||||
QColor backgroundShade() const;
|
||||
void setBackgroundShade(const QColor & c);
|
||||
|
||||
enum EditModes
|
||||
enum class EditMode
|
||||
{
|
||||
DRAW,
|
||||
ERASE,
|
||||
SELECT,
|
||||
MOVE
|
||||
Draw,
|
||||
Erase,
|
||||
DrawOutValues,
|
||||
EditTangents
|
||||
};
|
||||
|
||||
public slots:
|
||||
void update();
|
||||
void updateAfterPatternChange();
|
||||
void updateAfterClipChange();
|
||||
|
||||
|
||||
protected:
|
||||
typedef AutomationPattern::timeMap timeMap;
|
||||
using timeMap = AutomationClip::timeMap;
|
||||
|
||||
void keyPressEvent(QKeyEvent * ke) override;
|
||||
void leaveEvent(QEvent * e) override;
|
||||
void mousePressEvent(QMouseEvent * mouseEvent) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent * mouseEvent) override;
|
||||
void mouseReleaseEvent(QMouseEvent * mouseEvent) override;
|
||||
void mouseMoveEvent(QMouseEvent * mouseEvent) override;
|
||||
void paintEvent(QPaintEvent * pe) override;
|
||||
@@ -126,13 +124,19 @@ protected:
|
||||
float getLevel( int y );
|
||||
int xCoordOfTick( int tick );
|
||||
float yCoordOfLevel( float level );
|
||||
inline void drawLevelTick( QPainter & p, int tick, float value);// bool is_selected ); //NEEDS Change in CSS
|
||||
void removeSelection();
|
||||
void selectAll();
|
||||
void getSelectedValues(timeMap & selected_values );
|
||||
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 );
|
||||
void removePoints( int x0, int x1 );
|
||||
bool fineTuneValue(timeMap::iterator node, bool editingOutValue);
|
||||
|
||||
protected slots:
|
||||
void play();
|
||||
@@ -141,34 +145,46 @@ 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(AutomationPattern::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();
|
||||
|
||||
void copySelectedValues();
|
||||
void cutSelectedValues();
|
||||
void pasteValues();
|
||||
void deleteSelectedValues();
|
||||
|
||||
void updatePosition( const TimePos & t );
|
||||
void updatePosition( const lmms::TimePos & t );
|
||||
|
||||
void zoomingXChanged();
|
||||
void zoomingYChanged();
|
||||
|
||||
/// Updates the pattern's quantization using the current user selected value.
|
||||
/// 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,
|
||||
SELECT_VALUES,
|
||||
MOVE_SELECTION
|
||||
None,
|
||||
MoveValue,
|
||||
EraseValues,
|
||||
MoveOutValue,
|
||||
ResetOutValues,
|
||||
DrawLine,
|
||||
MoveTangent,
|
||||
ResetTangents
|
||||
} ;
|
||||
|
||||
// some constants...
|
||||
@@ -181,27 +197,33 @@ 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 & );
|
||||
virtual ~AutomationEditor();
|
||||
~AutomationEditor() override;
|
||||
|
||||
static QPixmap * s_toolDraw;
|
||||
static QPixmap * s_toolErase;
|
||||
static QPixmap * s_toolSelect;
|
||||
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<double> m_zoomXLevels;
|
||||
static const std::array<float, 7> m_zoomXLevels;
|
||||
|
||||
FloatModel * m_tensionModel;
|
||||
|
||||
QMutex m_patternMutex;
|
||||
AutomationPattern * m_pattern;
|
||||
AutomationClip * m_clip;
|
||||
float m_minLevel;
|
||||
float m_maxLevel;
|
||||
float m_step;
|
||||
@@ -209,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();
|
||||
|
||||
@@ -217,15 +243,8 @@ private:
|
||||
|
||||
TimePos m_currentPosition;
|
||||
|
||||
Actions m_action;
|
||||
Action m_action;
|
||||
|
||||
tick_t m_selectStartTick;
|
||||
tick_t m_selectedTick;
|
||||
float m_selectStartLevel;
|
||||
float m_selectedLevels;
|
||||
|
||||
float m_moveStartLevel;
|
||||
tick_t m_moveStartTick;
|
||||
int m_moveXOffset;
|
||||
|
||||
float m_drawLastLevel;
|
||||
@@ -235,11 +254,15 @@ private:
|
||||
int m_y_delta;
|
||||
bool m_y_auto;
|
||||
|
||||
timeMap m_valuesToCopy;
|
||||
timeMap m_selValuesForMove;
|
||||
// Time position (key) of automation node whose outValue is being dragged
|
||||
int m_draggedOutValueKey;
|
||||
|
||||
// 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;
|
||||
|
||||
EditModes m_editMode;
|
||||
EditMode m_editMode;
|
||||
|
||||
bool m_mouseDownLeft;
|
||||
bool m_mouseDownRight; //true if right click is being held down
|
||||
@@ -249,23 +272,29 @@ private:
|
||||
|
||||
void drawCross(QPainter & p );
|
||||
void drawAutomationPoint( QPainter & p, timeMap::iterator it );
|
||||
bool inBBEditor();
|
||||
void drawAutomationTangents(QPainter& p, timeMap::iterator it);
|
||||
bool inPatternEditor();
|
||||
|
||||
QColor m_barLineColor;
|
||||
QColor m_beatLineColor;
|
||||
QColor m_lineColor;
|
||||
QBrush m_graphColor;
|
||||
QColor m_vertexColor;
|
||||
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;
|
||||
|
||||
|
||||
signals:
|
||||
void currentPatternChanged();
|
||||
void positionChanged( const TimePos & );
|
||||
void currentClipChanged();
|
||||
void positionChanged( const lmms::TimePos & );
|
||||
} ;
|
||||
|
||||
|
||||
@@ -279,25 +308,28 @@ class AutomationEditorWindow : public Editor
|
||||
static const int INITIAL_HEIGHT = 480;
|
||||
public:
|
||||
AutomationEditorWindow();
|
||||
~AutomationEditorWindow();
|
||||
~AutomationEditorWindow() override = default;
|
||||
|
||||
void setCurrentPattern(AutomationPattern* pattern);
|
||||
const AutomationPattern* currentPattern();
|
||||
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;
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
|
||||
void open(AutomationPattern* pattern);
|
||||
void open(AutomationClip* clip);
|
||||
|
||||
AutomationEditor* m_editor;
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
public slots:
|
||||
void clearCurrentPattern();
|
||||
void clearCurrentClip();
|
||||
|
||||
signals:
|
||||
void currentPatternChanged();
|
||||
void currentClipChanged();
|
||||
|
||||
protected:
|
||||
void focusInEvent(QFocusEvent * event) override;
|
||||
@@ -308,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;
|
||||
@@ -322,7 +367,12 @@ private:
|
||||
ComboBox * m_zoomingXComboBox;
|
||||
ComboBox * m_zoomingYComboBox;
|
||||
ComboBox * m_quantizeComboBox;
|
||||
|
||||
QPushButton* m_resetGhostNotes;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GUI_AUTOMATION_EDITOR_H
|
||||
|
||||
180
include/AutomationNode.h
Normal file
180
include/AutomationNode.h
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* AutomationNode.h - Declaration of class AutomationNode, which contains
|
||||
* all information about an automation node
|
||||
*
|
||||
* Copyright (c) 2020 Ian Caio <iancaio_dev/at/hotmail.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_AUTOMATION_NODE_H
|
||||
#define LMMS_AUTOMATION_NODE_H
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AutomationClip;
|
||||
|
||||
|
||||
// Note: We use the default copy-assignment on the AutomationClip constructor. It's
|
||||
// fine for now as we don't have dynamic allocated members, but if any are added we should
|
||||
// have an user-defined one to perform a deep-copy.
|
||||
class AutomationNode
|
||||
{
|
||||
public:
|
||||
AutomationNode(); // Dummy constructor for the QMap
|
||||
AutomationNode(AutomationClip* clip, float value, int pos);
|
||||
AutomationNode(AutomationClip* clip, float inValue, float outValue, int pos);
|
||||
|
||||
AutomationNode& operator+=(float f)
|
||||
{
|
||||
m_inValue += f;
|
||||
m_outValue += f;
|
||||
return *this;
|
||||
}
|
||||
AutomationNode& operator-=(float f)
|
||||
{
|
||||
m_inValue -= f;
|
||||
m_outValue -= f;
|
||||
return *this;
|
||||
}
|
||||
AutomationNode& operator*=(float f)
|
||||
{
|
||||
m_inValue *= f;
|
||||
m_outValue *= f;
|
||||
return *this;
|
||||
}
|
||||
AutomationNode& operator/=(float f)
|
||||
{
|
||||
m_inValue /= f;
|
||||
m_outValue /= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const float getInValue() const
|
||||
{
|
||||
return m_inValue;
|
||||
}
|
||||
void setInValue(float value);
|
||||
|
||||
inline const float getOutValue() const
|
||||
{
|
||||
return m_outValue;
|
||||
}
|
||||
void setOutValue(float value);
|
||||
void resetOutValue();
|
||||
|
||||
/**
|
||||
* @brief Gets the offset between inValue and outValue
|
||||
* @return Float representing the offset between inValue and outValue
|
||||
*/
|
||||
inline const float getValueOffset() const
|
||||
{
|
||||
return m_outValue - m_inValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the tangent of the left side of the node
|
||||
* @return Float with the tangent from the inValue side
|
||||
*/
|
||||
inline const float getInTangent() const
|
||||
{
|
||||
return m_inTangent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the tangent of the left side of the node
|
||||
* @param Float with the tangent for the inValue side
|
||||
*/
|
||||
inline void setInTangent(float tangent)
|
||||
{
|
||||
m_inTangent = tangent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the tangent of the right side of the node
|
||||
* @return Float with the tangent from the outValue side
|
||||
*/
|
||||
inline const float getOutTangent() const
|
||||
{
|
||||
return m_outTangent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the tangent of the right side of the node
|
||||
* @param Float with the tangent for the outValue side
|
||||
*/
|
||||
inline void setOutTangent(float tangent)
|
||||
{
|
||||
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
|
||||
* set to
|
||||
*/
|
||||
inline void setClip(AutomationClip* clip)
|
||||
{
|
||||
m_clip = clip;
|
||||
}
|
||||
|
||||
private:
|
||||
// Clip that this node belongs to
|
||||
AutomationClip* m_clip;
|
||||
|
||||
// Time position of this node (matches the timeMap key)
|
||||
int m_pos;
|
||||
|
||||
// Values of this node
|
||||
float m_inValue;
|
||||
float m_outValue;
|
||||
|
||||
// Slope at each point for calculating spline
|
||||
// We might have discrete jumps between curves, so we possibly have
|
||||
// two different tangents for each side of the curve. If inValue and
|
||||
// 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 // LMMS_AUTOMATION_NODE_H
|
||||
@@ -1,201 +0,0 @@
|
||||
/*
|
||||
* AutomationPattern.h - declaration of class AutomationPattern, which contains
|
||||
* all information about an automation pattern
|
||||
*
|
||||
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
*
|
||||
* 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 AUTOMATION_PATTERN_H
|
||||
#define AUTOMATION_PATTERN_H
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
#include "TrackContentObject.h"
|
||||
|
||||
|
||||
class AutomationTrack;
|
||||
class TimePos;
|
||||
|
||||
|
||||
|
||||
class LMMS_EXPORT AutomationPattern : public TrackContentObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ProgressionTypes
|
||||
{
|
||||
DiscreteProgression,
|
||||
LinearProgression,
|
||||
CubicHermiteProgression
|
||||
} ;
|
||||
|
||||
typedef QMap<int, float> timeMap;
|
||||
typedef QVector<QPointer<AutomatableModel> > objectVector;
|
||||
|
||||
AutomationPattern( AutomationTrack * _auto_track );
|
||||
AutomationPattern( const AutomationPattern & _pat_to_copy );
|
||||
virtual ~AutomationPattern() = default;
|
||||
|
||||
bool addObject( AutomatableModel * _obj, bool _search_dup = true );
|
||||
|
||||
const AutomatableModel * firstObject() const;
|
||||
const objectVector& objects() const;
|
||||
|
||||
// progression-type stuff
|
||||
inline ProgressionTypes progressionType() const
|
||||
{
|
||||
return m_progressionType;
|
||||
}
|
||||
void setProgressionType( ProgressionTypes _new_progression_type );
|
||||
|
||||
inline float getTension() const
|
||||
{
|
||||
return m_tension;
|
||||
}
|
||||
void setTension( QString _new_tension );
|
||||
|
||||
TimePos timeMapLength() const;
|
||||
void updateLength();
|
||||
|
||||
TimePos putValue( const TimePos & time,
|
||||
const float value,
|
||||
const bool quantPos = true,
|
||||
const bool ignoreSurroundingPoints = true );
|
||||
|
||||
void removeValue( const TimePos & time );
|
||||
|
||||
void recordValue(TimePos time, float value);
|
||||
|
||||
TimePos setDragValue( const TimePos & time,
|
||||
const float value,
|
||||
const bool quantPos = true,
|
||||
const bool controlKey = false );
|
||||
|
||||
void applyDragValue();
|
||||
|
||||
|
||||
bool isDragging() const
|
||||
{
|
||||
return m_dragging;
|
||||
}
|
||||
|
||||
inline const timeMap & getTimeMap() const
|
||||
{
|
||||
return m_timeMap;
|
||||
}
|
||||
|
||||
inline timeMap & getTimeMap()
|
||||
{
|
||||
return m_timeMap;
|
||||
}
|
||||
|
||||
inline const timeMap & getTangents() const
|
||||
{
|
||||
return m_tangents;
|
||||
}
|
||||
|
||||
inline timeMap & getTangents()
|
||||
{
|
||||
return m_tangents;
|
||||
}
|
||||
|
||||
inline float getMin() const
|
||||
{
|
||||
return firstObject()->minValue<float>();
|
||||
}
|
||||
|
||||
inline float getMax() const
|
||||
{
|
||||
return firstObject()->maxValue<float>();
|
||||
}
|
||||
|
||||
inline bool hasAutomation() const
|
||||
{
|
||||
return m_timeMap.isEmpty() == false;
|
||||
}
|
||||
|
||||
float valueAt( const TimePos & _time ) const;
|
||||
float *valuesAfter( const TimePos & _time ) const;
|
||||
|
||||
const QString name() const;
|
||||
|
||||
// settings-management
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
|
||||
static const QString classNodeName() { return "automationpattern"; }
|
||||
QString nodeName() const override { return classNodeName(); }
|
||||
|
||||
TrackContentObjectView * createView( TrackView * _tv ) override;
|
||||
|
||||
|
||||
static bool isAutomated( const AutomatableModel * _m );
|
||||
static QVector<AutomationPattern *> patternsForModel( const AutomatableModel * _m );
|
||||
static AutomationPattern * globalAutomationPattern( AutomatableModel * _m );
|
||||
static void resolveAllIDs();
|
||||
|
||||
bool isRecording() const { return m_isRecording; }
|
||||
void setRecording( const bool b ) { m_isRecording = b; }
|
||||
|
||||
static int quantization() { return s_quantization; }
|
||||
static void setQuantization(int q) { s_quantization = q; }
|
||||
|
||||
public slots:
|
||||
void clear();
|
||||
void objectDestroyed( jo_id_t );
|
||||
void flipY( int min, int max );
|
||||
void flipY();
|
||||
void flipX( int length = -1 );
|
||||
|
||||
private:
|
||||
void cleanObjects();
|
||||
void generateTangents();
|
||||
void generateTangents( timeMap::const_iterator it, int numToGenerate );
|
||||
float valueAt( timeMap::const_iterator v, int offset ) const;
|
||||
|
||||
AutomationTrack * m_autoTrack;
|
||||
QVector<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.
|
||||
timeMap m_tangents; // slope at each point for calculating spline
|
||||
float m_tension;
|
||||
bool m_hasAutomation;
|
||||
ProgressionTypes m_progressionType;
|
||||
|
||||
bool m_dragging;
|
||||
|
||||
bool m_isRecording;
|
||||
float m_lastRecordedValue;
|
||||
|
||||
static int s_quantization;
|
||||
|
||||
static const float DEFAULT_MIN_VALUE;
|
||||
static const float DEFAULT_MAX_VALUE;
|
||||
|
||||
friend class AutomationPatternView;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -24,33 +24,33 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATION_TRACK_H
|
||||
#define AUTOMATION_TRACK_H
|
||||
#ifndef LMMS_AUTOMATION_TRACK_H
|
||||
#define LMMS_AUTOMATION_TRACK_H
|
||||
|
||||
#include "Track.h"
|
||||
#include "TrackView.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AutomationTrack : public Track
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AutomationTrack( TrackContainer* tc, bool _hidden = false );
|
||||
virtual ~AutomationTrack() = default;
|
||||
~AutomationTrack() override = default;
|
||||
|
||||
virtual bool play( const TimePos & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _tco_num = -1 ) override;
|
||||
bool play( const TimePos & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _clip_num = -1 ) override;
|
||||
|
||||
QString nodeName() const override
|
||||
{
|
||||
return "automationtrack";
|
||||
}
|
||||
|
||||
TrackView * createView( TrackContainerView* ) override;
|
||||
TrackContentObject* createTCO(const TimePos & pos) override;
|
||||
gui::TrackView * createView( gui::TrackContainerView* ) override;
|
||||
Clip* createClip(const TimePos & pos) override;
|
||||
|
||||
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent ) override;
|
||||
void saveTrackSpecificSettings(QDomDocument& doc, QDomElement& parent, bool presetMode) override;
|
||||
void loadTrackSpecificSettings( const QDomElement & _this ) override;
|
||||
|
||||
private:
|
||||
@@ -59,17 +59,6 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
class AutomationTrackView : public TrackView
|
||||
{
|
||||
public:
|
||||
AutomationTrackView( AutomationTrack* at, TrackContainerView* tcv );
|
||||
virtual ~AutomationTrackView() = default;
|
||||
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_AUTOMATION_TRACK_H
|
||||
|
||||
55
include/AutomationTrackView.h
Normal file
55
include/AutomationTrackView.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* AutomationTrackView.h - declaration of class AutomationTrackView
|
||||
*
|
||||
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
*
|
||||
* 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_AUTOMATION_TRACK_VIEW_H
|
||||
#define LMMS_GUI_AUTOMATION_TRACK_VIEW_H
|
||||
|
||||
#include "TrackView.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AutomationTrack;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
class AutomationTrackView : public TrackView
|
||||
{
|
||||
public:
|
||||
AutomationTrackView( AutomationTrack* at, TrackContainerView* tcv );
|
||||
~AutomationTrackView() override = default;
|
||||
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GUI_AUTOMATION_TRACK_VIEW_H
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* BBTrack.h - class BBTrack, a wrapper for using bbEditor
|
||||
* (which is a singleton-class) as track
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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 BB_TRACK_H
|
||||
#define BB_TRACK_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMap>
|
||||
#include <QStaticText>
|
||||
|
||||
#include "TrackContentObjectView.h"
|
||||
#include "Track.h"
|
||||
#include "TrackView.h"
|
||||
|
||||
class TrackLabelButton;
|
||||
class TrackContainer;
|
||||
|
||||
|
||||
class BBTCO : public TrackContentObject
|
||||
{
|
||||
public:
|
||||
BBTCO( Track * _track );
|
||||
virtual ~BBTCO() = default;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
inline QString nodeName() const override
|
||||
{
|
||||
return( "bbtco" );
|
||||
}
|
||||
|
||||
int bbTrackIndex();
|
||||
|
||||
TrackContentObjectView * createView( TrackView * _tv ) override;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
friend class BBTCOView;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
class BBTCOView : public TrackContentObjectView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BBTCOView( TrackContentObject * _tco, TrackView * _tv );
|
||||
virtual ~BBTCOView() = default;
|
||||
|
||||
|
||||
public slots:
|
||||
void update() override;
|
||||
|
||||
protected slots:
|
||||
void openInBBEditor();
|
||||
void resetName();
|
||||
void changeName();
|
||||
|
||||
|
||||
protected:
|
||||
void paintEvent( QPaintEvent * pe ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent * _me ) override;
|
||||
void constructContextMenu( QMenu * ) override;
|
||||
|
||||
|
||||
private:
|
||||
BBTCO * m_bbTCO;
|
||||
QPixmap m_paintPixmap;
|
||||
|
||||
QStaticText m_staticTextName;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
class LMMS_EXPORT BBTrack : public Track
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BBTrack( TrackContainer* tc );
|
||||
virtual ~BBTrack();
|
||||
|
||||
virtual bool play( const TimePos & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _tco_num = -1 ) override;
|
||||
TrackView * createView( TrackContainerView* tcv ) override;
|
||||
TrackContentObject* createTCO(const TimePos & pos) override;
|
||||
|
||||
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent ) override;
|
||||
void loadTrackSpecificSettings( const QDomElement & _this ) override;
|
||||
|
||||
static BBTrack * findBBTrack( int _bb_num );
|
||||
static void swapBBTracks( Track * _track1, Track * _track2 );
|
||||
|
||||
int index()
|
||||
{
|
||||
return s_infoMap[this];
|
||||
}
|
||||
|
||||
bool automationDisabled( Track * _track )
|
||||
{
|
||||
return( m_disabledTracks.contains( _track ) );
|
||||
}
|
||||
void disableAutomation( Track * _track )
|
||||
{
|
||||
m_disabledTracks.append( _track );
|
||||
}
|
||||
void enableAutomation( Track * _track )
|
||||
{
|
||||
m_disabledTracks.removeAll( _track );
|
||||
}
|
||||
|
||||
protected:
|
||||
inline QString nodeName() const override
|
||||
{
|
||||
return( "bbtrack" );
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QList<Track *> m_disabledTracks;
|
||||
|
||||
typedef QMap<BBTrack *, int> infoMap;
|
||||
static infoMap s_infoMap;
|
||||
|
||||
friend class BBTrackView;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
class BBTrackView : public TrackView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BBTrackView( BBTrack* bbt, TrackContainerView* tcv );
|
||||
virtual ~BBTrackView();
|
||||
|
||||
bool close() override;
|
||||
|
||||
const BBTrack * getBBTrack() const
|
||||
{
|
||||
return( m_bbTrack );
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
void clickedTrackLabel();
|
||||
|
||||
|
||||
private:
|
||||
BBTrack * m_bbTrack;
|
||||
TrackLabelButton * m_trackLabel;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* BBTrackContainer.h - model-component of BB-Editor
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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 BB_TRACK_CONTAINER_H
|
||||
#define BB_TRACK_CONTAINER_H
|
||||
|
||||
#include "TrackContainer.h"
|
||||
#include "ComboBoxModel.h"
|
||||
|
||||
|
||||
class LMMS_EXPORT BBTrackContainer : public TrackContainer
|
||||
{
|
||||
Q_OBJECT
|
||||
mapPropertyFromModel(int,currentBB,setCurrentBB,m_bbComboBoxModel);
|
||||
public:
|
||||
BBTrackContainer();
|
||||
virtual ~BBTrackContainer();
|
||||
|
||||
virtual bool play(TimePos start, const fpp_t frames, const f_cnt_t frameBase, int tcoNum = -1);
|
||||
|
||||
void updateAfterTrackAdd() override;
|
||||
|
||||
inline QString nodeName() const override
|
||||
{
|
||||
return "bbtrackcontainer";
|
||||
}
|
||||
|
||||
bar_t lengthOfBB(int bb) const;
|
||||
inline bar_t lengthOfCurrentBB()
|
||||
{
|
||||
return lengthOfBB(currentBB());
|
||||
}
|
||||
int numOfBBs() const;
|
||||
void removeBB(int bb);
|
||||
|
||||
void swapBB(int bb1, int bb2);
|
||||
|
||||
void updateBBTrack(TrackContentObject * tco);
|
||||
void fixIncorrectPositions();
|
||||
void createTCOsForBB(int bb);
|
||||
|
||||
AutomatedValueMap automatedValuesAt(TimePos time, int tcoNum) const override;
|
||||
|
||||
public slots:
|
||||
void play();
|
||||
void stop();
|
||||
void updateComboBox();
|
||||
void currentBBChanged();
|
||||
|
||||
|
||||
private:
|
||||
ComboBoxModel m_bbComboBoxModel;
|
||||
|
||||
|
||||
friend class BBEditor;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -23,8 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BANDLIMITEDWAVE_H
|
||||
#define BANDLIMITEDWAVE_H
|
||||
#ifndef LMMS_BANDLIMITEDWAVE_H
|
||||
#define LMMS_BANDLIMITEDWAVE_H
|
||||
|
||||
class QDataStream;
|
||||
class QString;
|
||||
@@ -34,14 +34,17 @@ class QString;
|
||||
#include "lmms_basics.h"
|
||||
#include "lmms_math.h"
|
||||
#include "Engine.h"
|
||||
#include "Mixer.h"
|
||||
#include "AudioEngine.h"
|
||||
|
||||
#define MAXLEN 11
|
||||
#define MIPMAPSIZE 2 << ( MAXLEN + 1 )
|
||||
#define MIPMAPSIZE3 3 << ( MAXLEN + 1 )
|
||||
#define MAXTBL 23
|
||||
#define MINTLEN 2 << 0
|
||||
#define MAXTLEN 3 << MAXLEN
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
constexpr int MAXLEN = 11;
|
||||
constexpr int MIPMAPSIZE = 2 << ( MAXLEN + 1 );
|
||||
constexpr int MIPMAPSIZE3 = 3 << ( MAXLEN + 1 );
|
||||
constexpr int MAXTBL = 23;
|
||||
constexpr int MINTLEN = 2 << 0;
|
||||
constexpr int MAXTLEN = 3 << MAXLEN;
|
||||
|
||||
// table for table sizes
|
||||
const int TLENS[MAXTBL+1] = { 2 << 0, 3 << 0, 2 << 1, 3 << 1,
|
||||
@@ -51,29 +54,30 @@ const int TLENS[MAXTBL+1] = { 2 << 0, 3 << 0, 2 << 1, 3 << 1,
|
||||
2 << 8, 3 << 8, 2 << 9, 3 << 9,
|
||||
2 << 10, 3 << 10, 2 << 11, 3 << 11 };
|
||||
|
||||
typedef struct
|
||||
struct WaveMipMap
|
||||
{
|
||||
public:
|
||||
inline sample_t sampleAt( int table, int ph )
|
||||
inline sample_t sampleAt(int table, int ph)
|
||||
{
|
||||
if( table % 2 == 0 )
|
||||
{ return m_data[ TLENS[ table ] + ph ]; }
|
||||
if (table % 2 == 0) { return m_data[TLENS[table] + ph]; }
|
||||
else
|
||||
{ return m_data3[ TLENS[ table ] + ph ]; }
|
||||
{
|
||||
return m_data3[TLENS[table] + ph];
|
||||
}
|
||||
}
|
||||
inline void setSampleAt( int table, int ph, sample_t sample )
|
||||
inline void setSampleAt(int table, int ph, sample_t sample)
|
||||
{
|
||||
if( table % 2 == 0 )
|
||||
{ m_data[ TLENS[ table ] + ph ] = sample; }
|
||||
if (table % 2 == 0) { m_data[TLENS[table] + ph] = sample; }
|
||||
else
|
||||
{ m_data3[ TLENS[ table ] + ph ] = sample; }
|
||||
{
|
||||
m_data3[TLENS[table] + ph] = sample;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
sample_t m_data [ MIPMAPSIZE ];
|
||||
sample_t m_data3 [ MIPMAPSIZE3 ];
|
||||
|
||||
} WaveMipMap;
|
||||
|
||||
sample_t m_data[MIPMAPSIZE];
|
||||
sample_t m_data3[MIPMAPSIZE3];
|
||||
};
|
||||
|
||||
QDataStream& operator<< ( QDataStream &out, WaveMipMap &waveMipMap );
|
||||
|
||||
@@ -85,24 +89,25 @@ 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() {};
|
||||
virtual ~BandLimitedWave() {};
|
||||
BandLimitedWave() = default;
|
||||
virtual ~BandLimitedWave() = default;
|
||||
|
||||
/*! \brief This method converts frequency to wavelength. The oscillate function takes wavelength as argument so
|
||||
* use this to convert your note frequency to wavelength before using it.
|
||||
*/
|
||||
static inline float freqToLen( float f )
|
||||
{
|
||||
return freqToLen( f, Engine::mixer()->processingSampleRate() );
|
||||
return freqToLen( f, Engine::audioEngine()->outputSampleRate() );
|
||||
}
|
||||
|
||||
/*! \brief This method converts frequency to wavelength, but you can use any custom sample rate with it.
|
||||
@@ -123,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;
|
||||
@@ -135,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 );
|
||||
*/
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
@@ -163,10 +169,11 @@ public:
|
||||
|
||||
static bool s_wavesGenerated;
|
||||
|
||||
static WaveMipMap s_waveforms [NumBLWaveforms];
|
||||
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,34 +28,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BASIC_FILTERS_H
|
||||
#define BASIC_FILTERS_H
|
||||
#ifndef LMMS_BASIC_FILTERS_H
|
||||
#define LMMS_BASIC_FILTERS_H
|
||||
|
||||
#ifndef __USE_XOPEN
|
||||
#define __USE_XOPEN
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <array>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "lmms_constants.h"
|
||||
#include "interpolation.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
template<ch_cnt_t CHANNELS=DEFAULT_CHANNELS> class BasicFilters;
|
||||
|
||||
template<ch_cnt_t CHANNELS>
|
||||
class LinkwitzRiley
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
LinkwitzRiley( float sampleRate )
|
||||
{
|
||||
m_sampleRate = sampleRate;
|
||||
clearHistory();
|
||||
}
|
||||
virtual ~LinkwitzRiley() {}
|
||||
virtual ~LinkwitzRiley() = default;
|
||||
|
||||
inline void clearHistory()
|
||||
{
|
||||
@@ -135,21 +136,25 @@ private:
|
||||
double m_a, m_a0, m_a1, m_a2;
|
||||
double m_b1, m_b2, m_b3, m_b4;
|
||||
|
||||
typedef double frame[CHANNELS];
|
||||
using frame = std::array<double, CHANNELS>;
|
||||
frame m_z1, m_z2, m_z3, m_z4;
|
||||
};
|
||||
typedef LinkwitzRiley<2> StereoLinkwitzRiley;
|
||||
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();
|
||||
}
|
||||
virtual ~BiQuad() {}
|
||||
virtual ~BiQuad() = default;
|
||||
|
||||
inline void setCoeffs( float a1, float a2, float b0, float b1, float b2 )
|
||||
{
|
||||
@@ -181,12 +186,11 @@ private:
|
||||
|
||||
friend class BasicFilters<CHANNELS>; // needed for subfilter stuff in BasicFilters
|
||||
};
|
||||
typedef BiQuad<2> StereoBiQuad;
|
||||
using StereoBiQuad = BiQuad<2>;
|
||||
|
||||
template<ch_cnt_t CHANNELS>
|
||||
class OnePole
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
OnePole()
|
||||
{
|
||||
@@ -197,7 +201,7 @@ public:
|
||||
m_z1[i] = 0.0;
|
||||
}
|
||||
}
|
||||
virtual ~OnePole() {}
|
||||
virtual ~OnePole() = default;
|
||||
|
||||
inline void setCoeffs( float a0, float b1 )
|
||||
{
|
||||
@@ -207,7 +211,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;
|
||||
}
|
||||
|
||||
@@ -215,14 +219,13 @@ private:
|
||||
float m_a0, m_b1;
|
||||
float m_z1 [CHANNELS];
|
||||
};
|
||||
typedef OnePole<2> StereoOnePole;
|
||||
using StereoOnePole = OnePole<2>;
|
||||
|
||||
template<ch_cnt_t CHANNELS>
|
||||
class BasicFilters
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
enum FilterTypes
|
||||
enum class FilterType
|
||||
{
|
||||
LowPass,
|
||||
HiPass,
|
||||
@@ -245,8 +248,7 @@ public:
|
||||
Highpass_SV,
|
||||
Notch_SV,
|
||||
FastFormant,
|
||||
Tripole,
|
||||
NumFilters
|
||||
Tripole
|
||||
};
|
||||
|
||||
static inline float minFreq()
|
||||
@@ -259,21 +261,21 @@ 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;
|
||||
if( m_subFilter == NULL )
|
||||
m_type = _idx == FilterType::DoubleLowPass
|
||||
? FilterType::LowPass
|
||||
: FilterType::Moog;
|
||||
if( m_subFilter == nullptr )
|
||||
{
|
||||
m_subFilter = new BasicFilters<CHANNELS>(
|
||||
static_cast<sample_rate_t>(
|
||||
@@ -286,7 +288,7 @@ public:
|
||||
m_doubleFilter( false ),
|
||||
m_sampleRate( (float) _sample_rate ),
|
||||
m_sampleRatio( 1.0f / m_sampleRate ),
|
||||
m_subFilter( NULL )
|
||||
m_subFilter( nullptr )
|
||||
{
|
||||
clearHistory();
|
||||
}
|
||||
@@ -327,33 +329,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];
|
||||
@@ -366,27 +374,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];
|
||||
@@ -402,8 +406,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;
|
||||
|
||||
@@ -419,15 +423,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];
|
||||
@@ -438,10 +441,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 */
|
||||
@@ -449,7 +451,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];
|
||||
}
|
||||
|
||||
@@ -463,22 +465,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;
|
||||
@@ -487,45 +489,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;
|
||||
@@ -534,16 +536,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;
|
||||
@@ -552,91 +554,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;
|
||||
@@ -646,39 +646,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;
|
||||
@@ -686,7 +686,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:
|
||||
@@ -707,16 +707,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 );
|
||||
|
||||
@@ -729,10 +729,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 },
|
||||
@@ -755,7 +755,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];
|
||||
@@ -766,11 +766,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;
|
||||
@@ -785,9 +785,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;
|
||||
@@ -796,20 +796,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 );
|
||||
@@ -823,38 +823,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;
|
||||
@@ -886,7 +886,7 @@ private:
|
||||
// coeffs for Lowpass_SV (state-variant lowpass)
|
||||
float m_svf1, m_svf2, m_svq;
|
||||
|
||||
typedef sample_t frame[CHANNELS];
|
||||
using frame = std::array<sample_t, CHANNELS>;
|
||||
|
||||
// in/out history for moog-filter
|
||||
frame m_y1, m_y2, m_y3, m_y4, m_oldx, m_oldy1, m_oldy2, m_oldy3;
|
||||
@@ -903,7 +903,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;
|
||||
@@ -913,4 +913,6 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_BASIC_FILTERS_H
|
||||
|
||||
@@ -28,11 +28,22 @@
|
||||
#include "lmms_export.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class SampleFrame;
|
||||
|
||||
/// Legacy interface for buffer re-use. Uses MemoryPool internally now.
|
||||
class LMMS_EXPORT BufferPool
|
||||
{
|
||||
public:
|
||||
static void init( fpp_t framesPerPeriod );
|
||||
static sampleFrame * acquire();
|
||||
static void release( sampleFrame * buf );
|
||||
static void init( fpp_t fpp );
|
||||
static SampleFrame* acquire();
|
||||
static void release( SampleFrame* buf );
|
||||
|
||||
private:
|
||||
static fpp_t s_framesPerPeriod;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
@@ -23,23 +23,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_GUI_CPU_LOAD_WIDGET_H
|
||||
#define LMMS_GUI_CPU_LOAD_WIDGET_H
|
||||
|
||||
#ifndef CPULOAD_WIDGET_H
|
||||
#define CPULOAD_WIDGET_H
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
#include <algorithm>
|
||||
#include <QTimer>
|
||||
#include <QPixmap>
|
||||
#include <QWidget>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
class CPULoadWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int stepSize MEMBER m_stepSize)
|
||||
public:
|
||||
CPULoadWidget( QWidget * _parent );
|
||||
virtual ~CPULoadWidget();
|
||||
~CPULoadWidget() override = default;
|
||||
|
||||
|
||||
protected:
|
||||
@@ -51,6 +56,8 @@ protected slots:
|
||||
|
||||
|
||||
private:
|
||||
int stepSize() const { return std::max(1, m_stepSize); }
|
||||
|
||||
int m_currentLoad;
|
||||
|
||||
QPixmap m_temp;
|
||||
@@ -61,7 +68,11 @@ private:
|
||||
|
||||
QTimer m_updateTimer;
|
||||
|
||||
int m_stepSize = 1;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_CPU_LOAD_WIDGET_H
|
||||
|
||||
@@ -22,14 +22,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CAPTION_MENU_H
|
||||
#define CAPTION_MENU_H
|
||||
#ifndef LMMS_GUI_CAPTION_MENU_H
|
||||
#define LMMS_GUI_CAPTION_MENU_H
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
#include "lmms_export.h"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief A context menu with a caption
|
||||
///
|
||||
@@ -38,10 +40,10 @@ class LMMS_EXPORT CaptionMenu : public QMenu
|
||||
Q_OBJECT
|
||||
public:
|
||||
CaptionMenu( const QString & _title, QWidget * _parent = 0 );
|
||||
virtual ~CaptionMenu();
|
||||
~CaptionMenu() override = default;
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_CAPTION_MENU_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* TrackConteintObject.h - declaration of TrackContentObject class
|
||||
* TrackConteintObject.h - declaration of Clip class
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -22,30 +22,39 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRACK_CONTENT_OBJECT_H
|
||||
#define TRACK_CONTENT_OBJECT_H
|
||||
#ifndef LMMS_CLIP_H
|
||||
#define LMMS_CLIP_H
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <QColor>
|
||||
|
||||
#include "AutomatableModel.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class Track;
|
||||
class TrackContentObjectView;
|
||||
class TrackContainer;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class ClipView;
|
||||
class TrackView;
|
||||
|
||||
} // namespace gui
|
||||
|
||||
class LMMS_EXPORT TrackContentObject : public Model, public JournallingObject
|
||||
|
||||
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:
|
||||
TrackContentObject( Track * track );
|
||||
virtual ~TrackContentObject();
|
||||
Clip( Track * track );
|
||||
~Clip() override;
|
||||
|
||||
inline Track * getTrack() const
|
||||
{
|
||||
@@ -85,6 +94,12 @@ public:
|
||||
return m_length;
|
||||
}
|
||||
|
||||
/*! \brief Specify whether or not a TCO automatically resizes.
|
||||
*
|
||||
* If a TCO does automatically resize, it cannot be manually
|
||||
* resized by clicking and dragging its edge.
|
||||
*
|
||||
*/
|
||||
inline void setAutoResize( const bool r )
|
||||
{
|
||||
m_autoResize = r;
|
||||
@@ -95,29 +110,13 @@ 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 );
|
||||
|
||||
virtual TrackContentObjectView * createView( TrackView * tv ) = 0;
|
||||
virtual gui::ClipView * createView( gui::TrackView * tv ) = 0;
|
||||
|
||||
inline void selectViewOnCreate( bool select )
|
||||
{
|
||||
@@ -130,15 +129,13 @@ public:
|
||||
}
|
||||
|
||||
/// Returns true if and only if a->startPosition() < b->startPosition()
|
||||
static bool comparePosition(const TrackContentObject* a, const TrackContentObject* b);
|
||||
static bool comparePosition(const Clip* a, const Clip* b);
|
||||
|
||||
TimePos startTimeOffset() const;
|
||||
void setStartTimeOffset( const TimePos &startTimeOffset );
|
||||
|
||||
void updateColor();
|
||||
|
||||
// Will copy the state of a TCO to another TCO
|
||||
static void copyStateTo( TrackContentObject *src, TrackContentObject *dst );
|
||||
// Will copy the state of a clip to another clip
|
||||
static void copyStateTo( Clip *src, Clip *dst );
|
||||
|
||||
public slots:
|
||||
void toggleMute();
|
||||
@@ -147,18 +144,11 @@ public slots:
|
||||
signals:
|
||||
void lengthChanged();
|
||||
void positionChanged();
|
||||
void destroyedTCO();
|
||||
void trackColorChanged();
|
||||
void destroyedClip();
|
||||
void colorChanged();
|
||||
|
||||
|
||||
private:
|
||||
enum Actions
|
||||
{
|
||||
NoAction,
|
||||
Move,
|
||||
Resize
|
||||
} ;
|
||||
|
||||
Track * m_track;
|
||||
QString m_name;
|
||||
|
||||
@@ -172,12 +162,13 @@ private:
|
||||
|
||||
bool m_selectViewOnCreate;
|
||||
|
||||
QColor m_color;
|
||||
bool m_useCustomClipColor;
|
||||
std::optional<QColor> m_color;
|
||||
|
||||
friend class TrackContentObjectView;
|
||||
friend class ClipView;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_CLIP_H
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* TrackContentObjectView.h - declaration of TrackContentObjectView class
|
||||
* ClipView.h - declaration of ClipView class
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -22,27 +22,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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 <QtCore/QVector>
|
||||
#include <QVector>
|
||||
|
||||
#include "ModelView.h"
|
||||
#include "Rubberband.h"
|
||||
#include "TrackContentObject.h"
|
||||
#include "Clip.h"
|
||||
|
||||
|
||||
class QMenu;
|
||||
class QContextMenuEvent;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class DataFile;
|
||||
class Clip;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class TextFloat;
|
||||
class TrackContentObject;
|
||||
class TrackView;
|
||||
|
||||
|
||||
class TrackContentObjectView : public selectableObject, public ModelView
|
||||
class ClipView : public selectableObject, public ModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -53,21 +61,24 @@ class TrackContentObjectView : public selectableObject, public ModelView
|
||||
Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor )
|
||||
Q_PROPERTY( QColor textBackgroundColor READ textBackgroundColor WRITE setTextBackgroundColor )
|
||||
Q_PROPERTY( QColor textShadowColor READ textShadowColor WRITE setTextShadowColor )
|
||||
Q_PROPERTY( QColor BBPatternBackground READ BBPatternBackground WRITE setBBPatternBackground )
|
||||
Q_PROPERTY( QColor patternClipBackground READ patternClipBackground WRITE setPatternClipBackground )
|
||||
Q_PROPERTY( bool gradient READ gradient WRITE setGradient )
|
||||
// We have to use a QSize here because using QPoint isn't supported.
|
||||
// width -> x, height -> y
|
||||
Q_PROPERTY( QSize mouseHotspotHand WRITE setMouseHotspotHand )
|
||||
Q_PROPERTY( QSize mouseHotspotHand MEMBER m_mouseHotspotHand )
|
||||
Q_PROPERTY( QSize mouseHotspotKnife MEMBER m_mouseHotspotKnife )
|
||||
|
||||
public:
|
||||
TrackContentObjectView( TrackContentObject * tco, TrackView * tv );
|
||||
virtual ~TrackContentObjectView();
|
||||
const static int BORDER_WIDTH = 2;
|
||||
|
||||
bool fixedTCOs();
|
||||
ClipView( Clip * clip, TrackView * tv );
|
||||
~ClipView() override;
|
||||
|
||||
inline TrackContentObject * getTrackContentObject()
|
||||
bool fixedClips();
|
||||
|
||||
inline Clip * getClip()
|
||||
{
|
||||
return m_tco;
|
||||
return m_clip;
|
||||
}
|
||||
|
||||
inline TrackView * getTrackView()
|
||||
@@ -82,7 +93,7 @@ public:
|
||||
QColor textColor() const;
|
||||
QColor textBackgroundColor() const;
|
||||
QColor textShadowColor() const;
|
||||
QColor BBPatternBackground() const;
|
||||
QColor patternClipBackground() const;
|
||||
bool gradient() const;
|
||||
void setMutedColor( const QColor & c );
|
||||
void setMutedBackgroundColor( const QColor & c );
|
||||
@@ -90,48 +101,63 @@ public:
|
||||
void setTextColor( const QColor & c );
|
||||
void setTextBackgroundColor( const QColor & c );
|
||||
void setTextShadowColor( const QColor & c );
|
||||
void setBBPatternBackground( const QColor & c );
|
||||
void setPatternClipBackground(const QColor& c);
|
||||
void setGradient( const bool & b );
|
||||
void setMouseHotspotHand(const QSize & s);
|
||||
|
||||
// access needsUpdate member variable
|
||||
bool needsUpdate();
|
||||
void setNeedsUpdate( bool b );
|
||||
|
||||
// Method to get a QVector of TCOs to be affected by a context menu action
|
||||
QVector<TrackContentObjectView *> getClickedTCOs();
|
||||
// Method to get a QVector of Clips to be affected by a context menu action
|
||||
QVector<ClipView *> getClickedClips();
|
||||
|
||||
// Methods to remove, copy, cut, paste and mute a QVector of TCO views
|
||||
void copy( QVector<TrackContentObjectView *> tcovs );
|
||||
void cut( QVector<TrackContentObjectView *> tcovs );
|
||||
// Methods to remove, copy, cut, paste and mute a QVector of Clip views
|
||||
void copy( QVector<ClipView *> clipvs );
|
||||
void cut( QVector<ClipView *> clipvs );
|
||||
void paste();
|
||||
// remove and toggleMute are static because they don't depend
|
||||
// being called from a particular TCO view, but can be called anywhere as long
|
||||
// as a valid TCO view list is given, while copy/cut require an instance for
|
||||
// being called from a particular Clip view, but can be called anywhere as long
|
||||
// as a valid Clip view list is given, while copy/cut require an instance for
|
||||
// some metadata to be written to the clipboard.
|
||||
static void remove( QVector<TrackContentObjectView *> tcovs );
|
||||
static void toggleMute( QVector<TrackContentObjectView *> tcovs );
|
||||
static void remove( QVector<ClipView *> clipvs );
|
||||
static void toggleMute( QVector<ClipView *> clipvs );
|
||||
static void mergeClips(QVector<ClipView*> clipvs);
|
||||
|
||||
// Returns true if selection can be merged and false if not
|
||||
static bool canMergeSelection(QVector<ClipView*> clipvs);
|
||||
|
||||
QColor getColorForDisplay( QColor );
|
||||
|
||||
void inline setMarkerPos(int x) { m_markerPos = x; }
|
||||
void inline setMarkerEnabled(bool e) { m_marker = e; }
|
||||
|
||||
public slots:
|
||||
virtual bool close();
|
||||
void remove();
|
||||
void update() override;
|
||||
|
||||
void changeClipColor();
|
||||
void useTrackColor();
|
||||
void selectColor();
|
||||
void randomizeColor();
|
||||
void resetColor();
|
||||
|
||||
protected:
|
||||
enum ContextMenuAction
|
||||
enum class ContextMenuAction
|
||||
{
|
||||
Remove,
|
||||
Cut,
|
||||
Copy,
|
||||
Paste,
|
||||
Mute
|
||||
Mute,
|
||||
Merge
|
||||
};
|
||||
|
||||
TrackView * m_trackView;
|
||||
TimePos m_initialClipPos;
|
||||
TimePos m_initialClipEnd;
|
||||
|
||||
bool m_marker = false;
|
||||
int m_markerPos = 0;
|
||||
|
||||
virtual void constructContextMenu( QMenu * )
|
||||
{
|
||||
}
|
||||
@@ -140,7 +166,6 @@ protected:
|
||||
void contextMenuAction( ContextMenuAction action );
|
||||
void dragEnterEvent( QDragEnterEvent * dee ) override;
|
||||
void dropEvent( QDropEvent * de ) override;
|
||||
void leaveEvent( QEvent * e ) override;
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
void mouseMoveEvent( QMouseEvent * me ) override;
|
||||
void mouseReleaseEvent( QMouseEvent * me ) override;
|
||||
@@ -150,13 +175,17 @@ protected:
|
||||
selectableObject::resizeEvent( re );
|
||||
}
|
||||
|
||||
bool unquantizedModHeld( QMouseEvent * me );
|
||||
TimePos quantizeSplitPos( TimePos, bool shiftMode );
|
||||
|
||||
float pixelsPerBar();
|
||||
|
||||
|
||||
DataFile createTCODataFiles(const QVector<TrackContentObjectView *> & tcos) const;
|
||||
DataFile createClipDataFiles(const QVector<ClipView *> & clips) const;
|
||||
|
||||
virtual void paintTextLabel(QString const & text, QPainter & painter);
|
||||
|
||||
auto hasCustomColor() const -> bool;
|
||||
|
||||
protected slots:
|
||||
void updateLength();
|
||||
@@ -164,26 +193,24 @@ protected slots:
|
||||
|
||||
|
||||
private:
|
||||
enum Actions
|
||||
enum class Action
|
||||
{
|
||||
NoAction,
|
||||
None,
|
||||
Move,
|
||||
MoveSelection,
|
||||
Resize,
|
||||
ResizeLeft,
|
||||
Split,
|
||||
CopySelection,
|
||||
ToggleSelected
|
||||
} ;
|
||||
|
||||
static TextFloat * s_textFloat;
|
||||
|
||||
TrackContentObject * m_tco;
|
||||
TrackView * m_trackView;
|
||||
Actions m_action;
|
||||
Clip * m_clip;
|
||||
Action m_action;
|
||||
QPoint m_initialMousePos;
|
||||
QPoint m_initialMouseGlobalPos;
|
||||
TimePos m_initialTCOPos;
|
||||
TimePos m_initialTCOEnd;
|
||||
QVector<TimePos> m_initialOffsets;
|
||||
|
||||
TextFloat * m_hint;
|
||||
@@ -195,9 +222,12 @@ private:
|
||||
QColor m_textColor;
|
||||
QColor m_textBackgroundColor;
|
||||
QColor m_textShadowColor;
|
||||
QColor m_BBPatternBackground;
|
||||
QColor m_patternClipBackground;
|
||||
bool m_gradient;
|
||||
QSize m_mouseHotspotHand; // QSize must be used because QPoint isn't supported by property system
|
||||
QSize m_mouseHotspotHand; // QSize must be used because QPoint
|
||||
QSize m_mouseHotspotKnife; // isn't supported by property system
|
||||
QCursor m_cursorHand;
|
||||
QCursor m_cursorKnife;
|
||||
bool m_cursorSetYet;
|
||||
|
||||
bool m_needsUpdate;
|
||||
@@ -205,14 +235,23 @@ private:
|
||||
{
|
||||
m_initialMousePos = pos;
|
||||
m_initialMouseGlobalPos = mapToGlobal( pos );
|
||||
m_initialTCOPos = m_tco->startPosition();
|
||||
m_initialTCOEnd = m_initialTCOPos + m_tco->length();
|
||||
m_initialClipPos = m_clip->startPosition();
|
||||
m_initialClipEnd = m_initialClipPos + m_clip->length();
|
||||
}
|
||||
void setInitialOffsets();
|
||||
|
||||
bool mouseMovedDistance( QMouseEvent * me, int distance );
|
||||
TimePos draggedTCOPos( QMouseEvent * me );
|
||||
TimePos draggedClipPos( QMouseEvent * me );
|
||||
int knifeMarkerPos( QMouseEvent * me );
|
||||
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);
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GUI_CLIP_VIEW_H
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Clipboard.h - the clipboard for patterns, notes etc.
|
||||
* Clipboard.h - the clipboard for clips, notes etc.
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -22,15 +22,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CLIPBOARD_H
|
||||
#define CLIPBOARD_H
|
||||
#ifndef LMMS_CLIPBOARD_H
|
||||
#define LMMS_CLIPBOARD_H
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QDomElement>
|
||||
#include <QMap>
|
||||
|
||||
#include "lmms_export.h"
|
||||
|
||||
namespace Clipboard
|
||||
class QMimeData;
|
||||
|
||||
namespace lmms::Clipboard
|
||||
{
|
||||
|
||||
enum class MimeType
|
||||
{
|
||||
StringPair,
|
||||
@@ -42,7 +46,7 @@ namespace 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
|
||||
@@ -63,6 +67,7 @@ namespace Clipboard
|
||||
break;
|
||||
}
|
||||
}
|
||||
} ;
|
||||
|
||||
#endif
|
||||
} // namespace lmms::Clipboard
|
||||
|
||||
#endif // LMMS_CLIPBOARD_H
|
||||
|
||||
@@ -21,19 +21,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_GUI_COLOR_CHOOSER_H
|
||||
#define LMMS_GUI_COLOR_CHOOSER_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <QColor>
|
||||
#include <QColorDialog>
|
||||
#include <QKeyEvent>
|
||||
#include <QVector>
|
||||
|
||||
class ColorChooser: public QColorDialog
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
class ColorChooser : public QColorDialog
|
||||
{
|
||||
public:
|
||||
ColorChooser(const QColor &initial, QWidget *parent): QColorDialog(initial, parent) {};
|
||||
ColorChooser(QWidget *parent): QColorDialog(parent) {};
|
||||
//! For getting a color without having to initialise a color dialog
|
||||
ColorChooser() {};
|
||||
ColorChooser() = default;
|
||||
enum class Palette {Default, Track, Mixer};
|
||||
//! Set global palette via array, checking bounds
|
||||
void setPalette (QVector<QColor>);
|
||||
@@ -57,3 +64,8 @@ private:
|
||||
//! Generate a nice palette, with adjustable value
|
||||
static QVector<QColor> nicePalette (int);
|
||||
};
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#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>
|
||||
@@ -32,12 +31,15 @@
|
||||
#include "ComboBoxModel.h"
|
||||
#include "AutomatableModelView.h"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class LMMS_EXPORT ComboBox : public QWidget, public IntModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComboBox( QWidget* parent = NULL, const QString& name = QString() );
|
||||
virtual ~ComboBox();
|
||||
ComboBox( QWidget* parent = nullptr, const QString& name = QString() );
|
||||
~ComboBox() override = default;
|
||||
|
||||
ComboBoxModel* model()
|
||||
{
|
||||
@@ -64,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;
|
||||
|
||||
@@ -78,4 +80,6 @@ private slots:
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
} // namespace lmms::gui
|
||||
|
||||
#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>
|
||||
@@ -32,26 +32,25 @@
|
||||
#include "AutomatableModel.h"
|
||||
#include "embed.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class LMMS_EXPORT ComboBoxModel : public IntModel
|
||||
{
|
||||
Q_OBJECT
|
||||
MODEL_IS_VISITABLE
|
||||
public:
|
||||
ComboBoxModel( Model* parent = NULL,
|
||||
ComboBoxModel( Model* parent = nullptr,
|
||||
const QString& displayName = QString(),
|
||||
bool isDefaultConstructed = false ) :
|
||||
IntModel( 0, 0, 0, parent, displayName, isDefaultConstructed )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ComboBoxModel()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void addItem( QString item, std::unique_ptr<PixmapLoader> loader = nullptr );
|
||||
|
||||
void replaceItem(std::size_t index, QString item, std::unique_ptr<PixmapLoader> loader = nullptr);
|
||||
|
||||
void clear();
|
||||
|
||||
int findText( const QString& txt ) const;
|
||||
@@ -68,12 +67,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
|
||||
@@ -83,11 +82,12 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
typedef std::pair<QString, std::unique_ptr<PixmapLoader> > Item;
|
||||
using Item = std::pair<QString, std::unique_ptr<PixmapLoader>>;
|
||||
|
||||
std::vector<Item> m_items;
|
||||
|
||||
} ;
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif
|
||||
#endif // LMMS_COMBOBOX_MODEL_H
|
||||
|
||||
@@ -22,22 +22,25 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CONFIG_MGR_H
|
||||
#define CONFIG_MGR_H
|
||||
#ifndef LMMS_CONFIG_MANAGER_H
|
||||
#define LMMS_CONFIG_MANAGER_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QPair>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QObject>
|
||||
#include <QMap>
|
||||
#include <QPair>
|
||||
#include <QStringList>
|
||||
#include <QObject>
|
||||
|
||||
#include <vector>
|
||||
#include "lmms_export.h"
|
||||
|
||||
|
||||
class LmmsCore;
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
|
||||
class Engine;
|
||||
|
||||
const QString PROJECTS_PATH = "projects/";
|
||||
const QString TEMPLATE_PATH = "templates/";
|
||||
@@ -60,7 +63,7 @@ class LMMS_EXPORT ConfigManager : public QObject
|
||||
public:
|
||||
static inline ConfigManager * inst()
|
||||
{
|
||||
if(s_instanceOfMe == NULL )
|
||||
if(s_instanceOfMe == nullptr )
|
||||
{
|
||||
s_instanceOfMe = new ConfigManager();
|
||||
}
|
||||
@@ -227,6 +230,7 @@ public:
|
||||
|
||||
QString defaultVersion() const;
|
||||
|
||||
static bool enableBlockedPlugins();
|
||||
|
||||
static QStringList availableVstEmbedMethods();
|
||||
QString vstEmbedMethod() const;
|
||||
@@ -236,11 +240,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);
|
||||
@@ -270,10 +271,11 @@ private:
|
||||
|
||||
ConfigManager();
|
||||
ConfigManager(const ConfigManager & _c);
|
||||
~ConfigManager();
|
||||
~ConfigManager() override;
|
||||
|
||||
void upgrade_1_1_90();
|
||||
void upgrade_1_1_91();
|
||||
void upgrade_1_2_2();
|
||||
void upgrade();
|
||||
|
||||
// List of all upgrade methods
|
||||
@@ -298,11 +300,15 @@ private:
|
||||
unsigned int m_configVersion;
|
||||
QStringList m_recentlyOpenedProjects;
|
||||
|
||||
typedef QVector<QPair<QString, QString> > stringPairVector;
|
||||
typedef QMap<QString, stringPairVector> settingsMap;
|
||||
using stringPairVector = std::vector<QPair<QString, QString>>;
|
||||
using settingsMap = QMap<QString, stringPairVector>;
|
||||
settingsMap m_settings;
|
||||
|
||||
|
||||
friend class LmmsCore;
|
||||
friend class Engine;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_CONFIG_MANAGER_H
|
||||
|
||||
@@ -70,15 +70,21 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONTROLLAYOUT_H
|
||||
#define CONTROLLAYOUT_H
|
||||
#ifndef LMMS_GUI_CONTROL_LAYOUT_H
|
||||
#define LMMS_GUI_CONTROL_LAYOUT_H
|
||||
|
||||
#include <QLayout>
|
||||
#include <QMultiMap>
|
||||
#include <QStyle>
|
||||
|
||||
class QLayoutItem;
|
||||
class QRect;
|
||||
class QString;
|
||||
class QLineEdit;
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
/**
|
||||
Layout for controls (models)
|
||||
@@ -128,9 +134,11 @@ private:
|
||||
// relevant dimension is width, as later, heightForWidth() will be called
|
||||
// 400 looks good and is ~4 knobs in a row
|
||||
constexpr const static int m_minWidth = 400;
|
||||
class QLineEdit* m_searchBar;
|
||||
QLineEdit* m_searchBar;
|
||||
//! name of search bar, must be ASCII sorted before any alpha numerics
|
||||
static constexpr const char* s_searchBarName = "!!searchBar!!";
|
||||
};
|
||||
|
||||
#endif // CONTROLLAYOUT_H
|
||||
} // namespace lmms::gui
|
||||
|
||||
#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"
|
||||
@@ -33,34 +32,41 @@
|
||||
#include "JournallingObject.h"
|
||||
#include "ValueBuffer.h"
|
||||
|
||||
class ControllerDialog;
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class Controller;
|
||||
class ControllerConnection;
|
||||
|
||||
typedef QVector<Controller *> ControllerVector;
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class ControllerDialog;
|
||||
|
||||
} // namespace gui
|
||||
|
||||
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 );
|
||||
|
||||
virtual ~Controller();
|
||||
~Controller() override;
|
||||
|
||||
virtual float currentValue( int _offset );
|
||||
// The per-controller get-value-in-buffers function
|
||||
@@ -76,7 +82,7 @@ public:
|
||||
m_sampleExact = _exact;
|
||||
}
|
||||
|
||||
inline ControllerTypes type() const
|
||||
inline ControllerType type() const
|
||||
{
|
||||
return( m_type );
|
||||
}
|
||||
@@ -87,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;
|
||||
}
|
||||
@@ -105,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()
|
||||
@@ -132,7 +138,7 @@ public:
|
||||
bool hasModel( const Model * m ) const;
|
||||
|
||||
public slots:
|
||||
virtual ControllerDialog * createDialog( QWidget * _parent );
|
||||
virtual gui::ControllerDialog * createDialog( QWidget * _parent );
|
||||
|
||||
virtual void setName( const QString & _new_name )
|
||||
{
|
||||
@@ -158,7 +164,7 @@ protected:
|
||||
int m_connectionCount;
|
||||
|
||||
QString m_name;
|
||||
ControllerTypes m_type;
|
||||
ControllerType m_type;
|
||||
|
||||
static ControllerVector s_controllers;
|
||||
|
||||
@@ -166,12 +172,14 @@ protected:
|
||||
|
||||
|
||||
signals:
|
||||
// The value changed while the mixer isn't running (i.e: MIDI CC)
|
||||
// The value changed while the audio engine isn't running (i.e: MIDI CC)
|
||||
void valueChanged();
|
||||
|
||||
friend class ControllerDialog;
|
||||
friend class gui::ControllerDialog;
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_CONTROLLER_H
|
||||
|
||||
@@ -26,31 +26,38 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_CONTROLLER_CONNECTION_H
|
||||
#define LMMS_CONTROLLER_CONNECTION_H
|
||||
|
||||
#ifndef CONTROLLER_CONNECTION_H
|
||||
#define CONTROLLER_CONNECTION_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVector>
|
||||
#include <QObject>
|
||||
|
||||
#include "Controller.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "ValueBuffer.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class ControllerConnection;
|
||||
|
||||
typedef QVector<ControllerConnection *> ControllerConnectionVector;
|
||||
namespace gui
|
||||
{
|
||||
class ControllerConnectionDialog;
|
||||
}
|
||||
|
||||
using ControllerConnectionVector = std::vector<ControllerConnection*>;
|
||||
|
||||
class LMMS_EXPORT ControllerConnection : public QObject, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
ControllerConnection( Controller * _controller );
|
||||
ControllerConnection(Controller * _controller);
|
||||
ControllerConnection( int _controllerId );
|
||||
|
||||
virtual ~ControllerConnection();
|
||||
~ControllerConnection() override;
|
||||
|
||||
inline Controller * getController()
|
||||
{
|
||||
@@ -98,7 +105,6 @@ public:
|
||||
return classNodeName();
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
void deleteConnection();
|
||||
|
||||
@@ -113,11 +119,13 @@ protected:
|
||||
static ControllerConnectionVector s_connections;
|
||||
|
||||
signals:
|
||||
// The value changed while the mixer isn't running (i.e: MIDI CC)
|
||||
// The value changed while the audio engine isn't running (i.e: MIDI CC)
|
||||
void valueChanged();
|
||||
|
||||
friend class ControllerConnectionDialog;
|
||||
friend class gui::ControllerConnectionDialog;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#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>
|
||||
@@ -38,7 +37,15 @@
|
||||
class QLineEdit;
|
||||
class QListView;
|
||||
class QScrollArea;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AutoDetectMidiController;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class ComboBox;
|
||||
class GroupBox;
|
||||
class TabWidget;
|
||||
@@ -47,14 +54,13 @@ class LedCheckBox;
|
||||
class MidiPortMenu;
|
||||
|
||||
|
||||
|
||||
class ControllerConnectionDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ControllerConnectionDialog( QWidget * _parent,
|
||||
const AutomatableModel * _target_model );
|
||||
virtual ~ControllerConnectionDialog();
|
||||
~ControllerConnectionDialog() override;
|
||||
|
||||
Controller * chosenController()
|
||||
{
|
||||
@@ -99,4 +105,9 @@ private:
|
||||
AutoDetectMidiController * m_midiController;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GUI_CONTROLLER_CONNECTION_DIALOG_H
|
||||
|
||||
@@ -23,15 +23,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_DIALOG_H
|
||||
#define CONTROLLER_DIALOG_H
|
||||
#ifndef LMMS_GUI_CONTROLLER_DIALOG_H
|
||||
#define LMMS_GUI_CONTROLLER_DIALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "ModelView.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class Controller;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class ControllerDialog : public QWidget, public ModelView
|
||||
{
|
||||
@@ -39,7 +44,7 @@ class ControllerDialog : public QWidget, public ModelView
|
||||
public:
|
||||
ControllerDialog( Controller * _controller, QWidget * _parent );
|
||||
|
||||
virtual ~ControllerDialog();
|
||||
~ControllerDialog() override = default;
|
||||
|
||||
|
||||
signals:
|
||||
@@ -51,4 +56,9 @@ protected:
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#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>
|
||||
@@ -36,16 +36,24 @@ class QPushButton;
|
||||
class QScrollArea;
|
||||
class QVBoxLayout;
|
||||
|
||||
class ControllerView;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class Controller;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class ControllerView;
|
||||
|
||||
|
||||
class ControllerRackView : public QWidget, public SerializingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ControllerRackView();
|
||||
virtual ~ControllerRackView();
|
||||
~ControllerRackView() override = default;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
@@ -57,9 +65,11 @@ public:
|
||||
|
||||
|
||||
public slots:
|
||||
void deleteController( ControllerView * _view );
|
||||
void onControllerAdded( Controller * );
|
||||
void onControllerRemoved( Controller * );
|
||||
void deleteController(ControllerView* view);
|
||||
void moveUp(ControllerView* view);
|
||||
void moveDown(ControllerView* view);
|
||||
void addController(Controller* controller);
|
||||
void removeController(Controller* controller);
|
||||
|
||||
protected:
|
||||
void closeEvent( QCloseEvent * _ce ) override;
|
||||
@@ -80,4 +90,8 @@ private:
|
||||
int m_nextIndex;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#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>
|
||||
|
||||
@@ -36,6 +36,10 @@ class QLabel;
|
||||
class QPushButton;
|
||||
class QMdiSubWindow;
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
class LedCheckBox;
|
||||
|
||||
|
||||
@@ -44,7 +48,7 @@ class ControllerView : public QFrame, public ModelView
|
||||
Q_OBJECT
|
||||
public:
|
||||
ControllerView( Controller * _controller, QWidget * _parent );
|
||||
virtual ~ControllerView();
|
||||
~ControllerView() override;
|
||||
|
||||
inline Controller * getController()
|
||||
{
|
||||
@@ -59,12 +63,16 @@ public:
|
||||
|
||||
public slots:
|
||||
void editControls();
|
||||
void deleteController();
|
||||
void removeController();
|
||||
void closeControls();
|
||||
void renameController();
|
||||
void moveUp();
|
||||
void moveDown();
|
||||
|
||||
signals:
|
||||
void deleteController( ControllerView * _view );
|
||||
void movedUp(ControllerView* view);
|
||||
void movedDown(ControllerView* view);
|
||||
void removedController(ControllerView* view);
|
||||
|
||||
|
||||
protected:
|
||||
@@ -81,4 +89,7 @@ private:
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_CONTROLLER_VIEW_H
|
||||
|
||||
@@ -22,11 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONTROLS_H
|
||||
#define CONTROLS_H
|
||||
|
||||
|
||||
#include "Model.h"
|
||||
#ifndef LMMS_GUI_CONTROLS_H
|
||||
#define LMMS_GUI_CONTROLS_H
|
||||
|
||||
// headers only required for covariance
|
||||
#include "AutomatableModel.h"
|
||||
@@ -35,8 +32,20 @@
|
||||
|
||||
class QString;
|
||||
class QWidget;
|
||||
class QLabel;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AutomatableModel;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class AutomatableModelView;
|
||||
class Knob;
|
||||
class ComboBox;
|
||||
class LedCheckBox;
|
||||
|
||||
/**
|
||||
These classes provide
|
||||
@@ -53,15 +62,15 @@ public:
|
||||
|
||||
virtual void setModel(AutomatableModel* model) = 0;
|
||||
virtual AutomatableModel* model() = 0;
|
||||
virtual class AutomatableModelView* modelView() = 0;
|
||||
virtual AutomatableModelView* modelView() = 0;
|
||||
|
||||
virtual ~Control();
|
||||
virtual ~Control() = default;
|
||||
};
|
||||
|
||||
|
||||
class KnobControl : public Control
|
||||
{
|
||||
class Knob* m_knob;
|
||||
Knob* m_knob;
|
||||
|
||||
public:
|
||||
void setText(const QString& text) override;
|
||||
@@ -69,18 +78,18 @@ public:
|
||||
|
||||
void setModel(AutomatableModel* model) override;
|
||||
FloatModel* model() override;
|
||||
class AutomatableModelView* modelView() override;
|
||||
AutomatableModelView* modelView() override;
|
||||
|
||||
KnobControl(QWidget* parent = nullptr);
|
||||
~KnobControl() override;
|
||||
~KnobControl() override = default;
|
||||
};
|
||||
|
||||
|
||||
class ComboControl : public Control
|
||||
{
|
||||
QWidget* m_widget;
|
||||
class ComboBox* m_combo;
|
||||
class QLabel* m_label;
|
||||
ComboBox* m_combo;
|
||||
QLabel* m_label;
|
||||
|
||||
public:
|
||||
void setText(const QString& text) override;
|
||||
@@ -88,10 +97,10 @@ public:
|
||||
|
||||
void setModel(AutomatableModel* model) override;
|
||||
ComboBoxModel* model() override;
|
||||
class AutomatableModelView* modelView() override;
|
||||
AutomatableModelView* modelView() override;
|
||||
|
||||
ComboControl(QWidget* parent = nullptr);
|
||||
~ComboControl() override;
|
||||
~ComboControl() override = default;
|
||||
};
|
||||
|
||||
|
||||
@@ -105,17 +114,17 @@ public:
|
||||
|
||||
void setModel(AutomatableModel* model) override;
|
||||
IntModel* model() override;
|
||||
class AutomatableModelView* modelView() override;
|
||||
AutomatableModelView* modelView() override;
|
||||
|
||||
LcdControl(int numDigits, QWidget* parent = nullptr);
|
||||
~LcdControl() override;
|
||||
~LcdControl() override = default;
|
||||
};
|
||||
|
||||
|
||||
class CheckControl : public Control
|
||||
{
|
||||
QWidget* m_widget;
|
||||
class LedCheckBox* m_checkBox;
|
||||
LedCheckBox* m_checkBox;
|
||||
QLabel* m_label;
|
||||
|
||||
public:
|
||||
@@ -123,12 +132,16 @@ public:
|
||||
QWidget* topWidget() override;
|
||||
|
||||
void setModel(AutomatableModel* model) override;
|
||||
BoolModel *model() override;
|
||||
class AutomatableModelView* modelView() override;
|
||||
BoolModel* model() override;
|
||||
AutomatableModelView* modelView() override;
|
||||
|
||||
CheckControl(QWidget* parent = nullptr);
|
||||
~CheckControl() override;
|
||||
~CheckControl() override = default;
|
||||
};
|
||||
|
||||
|
||||
#endif // CONTROLS_H
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GUI_CONTROLS_H
|
||||
|
||||
@@ -1,17 +1,44 @@
|
||||
/* 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"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
class LMMS_EXPORT CustomTextKnob : public Knob
|
||||
{
|
||||
protected:
|
||||
inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible
|
||||
public:
|
||||
CustomTextKnob( knobTypes _knob_num, QWidget * _parent = NULL, const QString & _name = QString(), const QString & _value_text = QString() );
|
||||
CustomTextKnob( KnobType _knob_num, QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() );
|
||||
|
||||
CustomTextKnob( QWidget * _parent = NULL, const QString & _name = QString(), const QString & _value_text = QString() ); //!< default ctor
|
||||
CustomTextKnob( QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() ); //!< default ctor
|
||||
|
||||
CustomTextKnob( const Knob& other ) = delete;
|
||||
|
||||
@@ -21,10 +48,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
virtual QString displayValue() const;
|
||||
QString displayValue() const override;
|
||||
|
||||
protected:
|
||||
QString m_value_text;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_CUSTOM_TEXT_KNOB_H
|
||||
|
||||
@@ -23,28 +23,32 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_DATA_FILE_H
|
||||
#define LMMS_DATA_FILE_H
|
||||
|
||||
#ifndef DATA_FILE_H
|
||||
#define DATA_FILE_H
|
||||
|
||||
#include <map>
|
||||
#include <QDomDocument>
|
||||
#include <vector>
|
||||
|
||||
#include "lmms_export.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "ProjectVersion.h"
|
||||
|
||||
class QTextStream;
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
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,
|
||||
@@ -52,15 +56,14 @@ public:
|
||||
ClipboardData,
|
||||
JournalData,
|
||||
EffectSettings,
|
||||
TypeCount
|
||||
MidiClip
|
||||
} ;
|
||||
typedef Types Type;
|
||||
|
||||
DataFile( const QString& fileName );
|
||||
DataFile( const QByteArray& data );
|
||||
DataFile( Type type );
|
||||
|
||||
virtual ~DataFile();
|
||||
virtual ~DataFile() = default;
|
||||
|
||||
///
|
||||
/// \brief validate
|
||||
@@ -71,7 +74,9 @@ public:
|
||||
QString nameWithExtension( const QString& fn ) const;
|
||||
|
||||
void write( QTextStream& strm );
|
||||
bool writeFile( const QString& fn );
|
||||
bool writeFile(const QString& fn, bool withResources = false);
|
||||
bool copyResources(const QString& resourcesDir); //!< Copies resources to the resourcesDir and changes the DataFile to use local paths to them
|
||||
bool hasLocalPlugins(QDomElement parent = QDomElement(), bool firstCall = true) const;
|
||||
|
||||
QDomElement& content()
|
||||
{
|
||||
@@ -96,6 +101,8 @@ private:
|
||||
|
||||
void cleanMetaNodes( QDomElement de );
|
||||
|
||||
void mapSrcAttributeInElementsWithResources(const QMap<QString, QString>& map);
|
||||
|
||||
// helper upgrade routines
|
||||
void upgrade_0_2_1_20070501();
|
||||
void upgrade_0_2_1_20070508();
|
||||
@@ -115,30 +122,40 @@ private:
|
||||
void upgrade_1_2_0_rc3();
|
||||
void upgrade_1_3_0();
|
||||
void upgrade_noHiddenClipNames();
|
||||
void upgrade_automationNodes();
|
||||
void upgrade_extendedNoteRange();
|
||||
void upgrade_defaultTripleOscillatorHQ();
|
||||
void upgrade_mixerRename();
|
||||
void upgrade_bbTcoRename();
|
||||
void upgrade_sampleAndHold();
|
||||
void upgrade_midiCCIndexing();
|
||||
void upgrade_loopsRename();
|
||||
void upgrade_noteTypes();
|
||||
void upgrade_fixCMTDelays();
|
||||
void upgrade_fixBassLoopsTypo();
|
||||
void findProblematicLadspaPlugins();
|
||||
|
||||
// List of all upgrade methods
|
||||
static const std::vector<UpgradeMethod> UPGRADE_METHODS;
|
||||
// List of ProjectVersions for the legacyFileVersion method
|
||||
static const std::vector<ProjectVersion> UPGRADE_VERSIONS;
|
||||
|
||||
// Map with DOM elements that access resources (for making bundles)
|
||||
using ResourcesMap = std::map<QString, std::vector<QString>>;
|
||||
static const ResourcesMap ELEMENTS_WITH_RESOURCES;
|
||||
|
||||
void upgrade();
|
||||
|
||||
void loadData( const QByteArray & _data, const QString & _sourceFile );
|
||||
|
||||
|
||||
struct LMMS_EXPORT typeDescStruct
|
||||
{
|
||||
Type m_type;
|
||||
QString m_name;
|
||||
} ;
|
||||
static typeDescStruct s_types[TypeCount];
|
||||
|
||||
QString m_fileName; //!< The origin file name or "" if this DataFile didn't originate from a file
|
||||
QDomElement m_content;
|
||||
QDomElement m_head;
|
||||
Type m_type;
|
||||
unsigned int m_fileVersion;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_DATA_FILE_H
|
||||
|
||||
@@ -22,15 +22,16 @@
|
||||
* 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
|
||||
{
|
||||
|
||||
// brief usage
|
||||
|
||||
@@ -63,7 +64,7 @@ template<ch_cnt_t CHANNELS>
|
||||
class CombFeedback
|
||||
{
|
||||
public:
|
||||
typedef double frame[CHANNELS];
|
||||
using frame = std::array<double, CHANNELS>;
|
||||
|
||||
CombFeedback( int maxDelay ) :
|
||||
m_size( maxDelay ),
|
||||
@@ -72,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;
|
||||
@@ -134,7 +135,7 @@ private:
|
||||
template<ch_cnt_t CHANNELS>
|
||||
class CombFeedfwd
|
||||
{
|
||||
typedef double frame[CHANNELS];
|
||||
using frame = std::array<double, CHANNELS>;
|
||||
|
||||
CombFeedfwd( int maxDelay ) :
|
||||
m_size( maxDelay ),
|
||||
@@ -143,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;
|
||||
@@ -205,7 +206,7 @@ private:
|
||||
template<ch_cnt_t CHANNELS>
|
||||
class CombFeedbackDualtap
|
||||
{
|
||||
typedef double frame[CHANNELS];
|
||||
using frame = std::array<double, CHANNELS>;
|
||||
|
||||
CombFeedbackDualtap( int maxDelay ) :
|
||||
m_size( maxDelay ),
|
||||
@@ -214,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;
|
||||
@@ -286,7 +287,7 @@ template<ch_cnt_t CHANNELS>
|
||||
class AllpassDelay
|
||||
{
|
||||
public:
|
||||
typedef double frame[CHANNELS];
|
||||
using frame = std::array<double, CHANNELS>;
|
||||
|
||||
AllpassDelay( int maxDelay ) :
|
||||
m_size( maxDelay ),
|
||||
@@ -295,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;
|
||||
@@ -355,9 +356,11 @@ private:
|
||||
};
|
||||
|
||||
// convenience typedefs for stereo effects
|
||||
typedef CombFeedback<2> StereoCombFeedback;
|
||||
typedef CombFeedfwd<2> StereoCombFeedfwd;
|
||||
typedef CombFeedbackDualtap<2> StereoCombFeedbackDualtap;
|
||||
typedef AllpassDelay<2> StereoAllpassDelay;
|
||||
using StereoCombFeedback = CombFeedback<2>;
|
||||
using StereoCombFeedfwd = CombFeedfwd<2>;
|
||||
using StereoCombFeedbackDualtap = CombFeedbackDualtap<2>;
|
||||
using StereoAllpassDelay = AllpassDelay<2>;
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_DELAY_H
|
||||
|
||||
@@ -24,12 +24,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DEPRECATIONHELPER_H
|
||||
#define DEPRECATIONHELPER_H
|
||||
#ifndef LMMS_DEPRECATIONHELPER_H
|
||||
#define LMMS_DEPRECATIONHELPER_H
|
||||
|
||||
#include <QFontMetrics>
|
||||
#include <QWheelEvent>
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief horizontalAdvance is a backwards-compatible adapter for
|
||||
* QFontMetrics::horizontalAdvance and width functions.
|
||||
@@ -60,4 +63,7 @@ inline QPoint position(QWheelEvent *wheelEvent)
|
||||
return wheelEvent->pos();
|
||||
#endif
|
||||
}
|
||||
#endif // DEPRECATIONHELPER_H
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_DEPRECATIONHELPER_H
|
||||
|
||||
@@ -23,25 +23,24 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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
|
||||
{
|
||||
|
||||
class DetuningHelper : public InlineAutomation
|
||||
{
|
||||
Q_OBJECT
|
||||
MM_OPERATORS
|
||||
public:
|
||||
DetuningHelper() :
|
||||
InlineAutomation()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DetuningHelper()
|
||||
{
|
||||
}
|
||||
~DetuningHelper() override = default;
|
||||
|
||||
float defaultValue() const override
|
||||
{
|
||||
@@ -61,4 +60,6 @@ public:
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_DETUNING_HELPER_H
|
||||
|
||||
@@ -23,32 +23,37 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DRUMSYNTH_H__
|
||||
#define _DRUMSYNTH_H__
|
||||
#ifndef LMMS_DRUM_SYNTH_H
|
||||
#define LMMS_DRUM_SYNTH_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
|
||||
class QString;
|
||||
|
||||
class DrumSynth {
|
||||
public:
|
||||
DrumSynth() {};
|
||||
int GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sample_rate_t Fs);
|
||||
namespace lmms {
|
||||
|
||||
private:
|
||||
float LoudestEnv(void);
|
||||
int LongestEnv(void);
|
||||
void UpdateEnv(int e, long t);
|
||||
void GetEnv(int env, const char *sec, const char *key, QString ini);
|
||||
class DrumSynth
|
||||
{
|
||||
public:
|
||||
DrumSynth() = default;
|
||||
int GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sample_rate_t Fs);
|
||||
|
||||
float waveform(float ph, int form);
|
||||
private:
|
||||
float LoudestEnv();
|
||||
int LongestEnv();
|
||||
void UpdateEnv(int e, long t);
|
||||
void GetEnv(int env, const char* sec, const char* key, QString ini);
|
||||
|
||||
int GetPrivateProfileString(const char *sec, const char *key, const char *def, char *buffer, int size, QString file);
|
||||
int GetPrivateProfileInt(const char *sec, const char *key, int def, QString file);
|
||||
float GetPrivateProfileFloat(const char *sec, const char *key, float def, QString file);
|
||||
float waveform(float ph, int form);
|
||||
|
||||
int GetPrivateProfileString(
|
||||
const char* sec, const char* key, const char* def, char* buffer, int size, QString file);
|
||||
int GetPrivateProfileInt(const char* sec, const char* key, int def, QString file);
|
||||
float GetPrivateProfileFloat(const char* sec, const char* key, float def, QString file);
|
||||
};
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_DRUM_SYNTH_H
|
||||
|
||||
@@ -22,23 +22,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#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"
|
||||
#include "lmms_basics.h"
|
||||
#include "SampleFrame.h"
|
||||
|
||||
|
||||
namespace DspEffectLibrary
|
||||
namespace lmms::DspEffectLibrary
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class MonoBase
|
||||
{
|
||||
public:
|
||||
typedef class MonoBypass bypassType;
|
||||
using bypassType = class MonoBypass;
|
||||
|
||||
static void process( sample_t * * _buf, const f_cnt_t _frames )
|
||||
{
|
||||
@@ -53,7 +52,7 @@ namespace DspEffectLibrary
|
||||
class StereoBase
|
||||
{
|
||||
public:
|
||||
typedef class StereoBypass bypassType;
|
||||
using bypassType = class StereoBypass;
|
||||
|
||||
static void process( sample_t * * _buf, const f_cnt_t _frames )
|
||||
{
|
||||
@@ -81,6 +80,17 @@ namespace DspEffectLibrary
|
||||
{
|
||||
}
|
||||
|
||||
void setGain(float gain)
|
||||
{
|
||||
leftFX().setGain(gain);
|
||||
rightFX().setGain(gain);
|
||||
}
|
||||
|
||||
void nextSample(SampleFrame & in)
|
||||
{
|
||||
nextSample(in.left(), in.right());
|
||||
}
|
||||
|
||||
void nextSample( sample_t& inLeft, sample_t& inRight )
|
||||
{
|
||||
inLeft = m_leftFX.nextSample( inLeft );
|
||||
@@ -164,7 +174,7 @@ namespace DspEffectLibrary
|
||||
class Chain : public FX0::bypassType
|
||||
{
|
||||
public:
|
||||
typedef typename FX0::sample_t sample_t;
|
||||
using sample_t = typename FX0::sample_t;
|
||||
Chain( const FX0& fx0, const FX1& fx1 = FX1() ) :
|
||||
m_FX0( fx0 ),
|
||||
m_FX1( fx1 )
|
||||
@@ -188,7 +198,7 @@ namespace 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 +209,7 @@ namespace 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 ),
|
||||
@@ -329,7 +339,6 @@ namespace DspEffectLibrary
|
||||
|
||||
} ;
|
||||
|
||||
} ;
|
||||
} // namespace lmms::DspEffectLibrary
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_DSPEFFECTLIBRARY_H
|
||||
|
||||
@@ -22,13 +22,23 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DUMMY_EFFECT_H
|
||||
#define DUMMY_EFFECT_H
|
||||
#ifndef LMMS_DUMMY_EFFECT_H
|
||||
#define LMMS_DUMMY_EFFECT_H
|
||||
|
||||
#include <QDomElement>
|
||||
|
||||
#include "Effect.h"
|
||||
#include "EffectControls.h"
|
||||
#include "EffectControlDialog.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class Knob;
|
||||
|
||||
|
||||
class DummyEffectControlDialog : public EffectControlDialog
|
||||
{
|
||||
@@ -40,6 +50,7 @@ public:
|
||||
|
||||
} ;
|
||||
|
||||
} // namespace gui
|
||||
|
||||
class DummyEffectControls : public EffectControls
|
||||
{
|
||||
@@ -49,9 +60,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DummyEffectControls()
|
||||
{
|
||||
}
|
||||
~DummyEffectControls() override = default;
|
||||
|
||||
int controlCount() override
|
||||
{
|
||||
@@ -71,9 +80,9 @@ public:
|
||||
return "DummyControls";
|
||||
}
|
||||
|
||||
EffectControlDialog * createView() override
|
||||
gui::EffectControlDialog * createView() override
|
||||
{
|
||||
return new DummyEffectControlDialog( this );
|
||||
return new gui::DummyEffectControlDialog( this );
|
||||
}
|
||||
} ;
|
||||
|
||||
@@ -84,25 +93,24 @@ class DummyEffect : public Effect
|
||||
Q_OBJECT
|
||||
public:
|
||||
DummyEffect( Model * _parent, const QDomElement& originalPluginData ) :
|
||||
Effect( NULL, _parent, NULL ),
|
||||
Effect( nullptr, _parent, nullptr ),
|
||||
m_controls( this ),
|
||||
m_originalPluginData( originalPluginData )
|
||||
{
|
||||
setName();
|
||||
setDontRun(true);
|
||||
}
|
||||
|
||||
virtual ~DummyEffect()
|
||||
{
|
||||
}
|
||||
~DummyEffect() override = default;
|
||||
|
||||
EffectControls * controls() override
|
||||
{
|
||||
return &m_controls;
|
||||
}
|
||||
|
||||
bool processAudioBuffer( sampleFrame *, const fpp_t ) override
|
||||
ProcessStatus processImpl(SampleFrame*, const fpp_t) override
|
||||
{
|
||||
return false;
|
||||
return ProcessStatus::Sleep;
|
||||
}
|
||||
|
||||
const QDomElement& originalPluginData() const
|
||||
@@ -140,4 +148,6 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_DUMMY_EFFECT_H
|
||||
|
||||
@@ -23,34 +23,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DUMMY_INSTRUMENT_H
|
||||
#define DUMMY_INSTRUMENT_H
|
||||
#ifndef LMMS_DUMMY_INSTRUMENT_H
|
||||
#define LMMS_DUMMY_INSTRUMENT_H
|
||||
|
||||
#include "Instrument.h"
|
||||
#include "InstrumentView.h"
|
||||
#include "Engine.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
|
||||
#include "Mixer.h"
|
||||
#include "AudioEngine.h"
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
|
||||
class DummyInstrument : public Instrument
|
||||
{
|
||||
public:
|
||||
DummyInstrument( InstrumentTrack * _instrument_track ) :
|
||||
Instrument( _instrument_track, NULL )
|
||||
Instrument( _instrument_track, nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DummyInstrument()
|
||||
{
|
||||
}
|
||||
~DummyInstrument() override = default;
|
||||
|
||||
void playNote( NotePlayHandle *, sampleFrame * buffer ) override
|
||||
void playNote( NotePlayHandle*, SampleFrame* buffer ) override
|
||||
{
|
||||
memset( buffer, 0, sizeof( sampleFrame ) *
|
||||
Engine::mixer()->framesPerPeriod() );
|
||||
zeroSampleFrames(buffer, Engine::audioEngine()->framesPerPeriod());
|
||||
}
|
||||
|
||||
void saveSettings( QDomDocument &, QDomElement & ) override
|
||||
@@ -66,11 +67,13 @@ public:
|
||||
return "dummyinstrument";
|
||||
}
|
||||
|
||||
PluginView * instantiateView( QWidget * _parent ) override
|
||||
gui::PluginView * instantiateView( QWidget * _parent ) override
|
||||
{
|
||||
return new InstrumentViewFixedSize( this, _parent );
|
||||
return new gui::InstrumentViewFixedSize( this, _parent );
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_DUMMY_INSTRUMENT_H
|
||||
|
||||
@@ -23,24 +23,25 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DUMMY_PLUGIN_H
|
||||
#define DUMMY_PLUGIN_H
|
||||
#ifndef LMMS_DUMMY_PLUGIN_H
|
||||
#define LMMS_DUMMY_PLUGIN_H
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "PluginView.h"
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class DummyPlugin : public Plugin
|
||||
{
|
||||
public:
|
||||
DummyPlugin() :
|
||||
Plugin( NULL, NULL )
|
||||
Plugin( nullptr, nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DummyPlugin()
|
||||
{
|
||||
}
|
||||
~DummyPlugin() override = default;
|
||||
|
||||
void saveSettings( QDomDocument &, QDomElement & ) override
|
||||
{
|
||||
@@ -57,12 +58,14 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
PluginView * instantiateView( QWidget * _parent ) override
|
||||
gui::PluginView * instantiateView( QWidget * _parent ) override
|
||||
{
|
||||
return new PluginView( this, _parent );
|
||||
return new gui::PluginView( this, _parent );
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_DUMMY_PLUGIN_H
|
||||
|
||||
@@ -22,20 +22,23 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EDITOR_COMMON_H
|
||||
#define EDITOR_COMMON_H
|
||||
#ifndef LMMS_GUI_EDITOR_H
|
||||
#define LMMS_GUI_EDITOR_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QToolBar>
|
||||
|
||||
class QAction;
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
static const int Quantizations[] = {
|
||||
1, 2, 4, 8, 16, 32, 64,
|
||||
3, 6, 12, 24, 48, 96, 192
|
||||
};
|
||||
|
||||
|
||||
class QAction;
|
||||
|
||||
class DropToolBar;
|
||||
|
||||
/// \brief Superclass for editors with a toolbar.
|
||||
@@ -78,7 +81,7 @@ protected:
|
||||
/// \param record If set true, the editor's toolbar will contain record
|
||||
/// buttons in addition to the play and stop buttons.
|
||||
Editor(bool record = false, bool record_step = false);
|
||||
virtual ~Editor();
|
||||
~Editor() override = default;
|
||||
|
||||
|
||||
DropToolBar* m_toolBar;
|
||||
@@ -108,4 +111,6 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_EDITOR_H
|
||||
|
||||
131
include/Effect.h
131
include/Effect.h
@@ -23,29 +23,37 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_H
|
||||
#define EFFECT_H
|
||||
#ifndef LMMS_EFFECT_H
|
||||
#define LMMS_EFFECT_H
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "Engine.h"
|
||||
#include "Mixer.h"
|
||||
#include "AudioEngine.h"
|
||||
#include "AutomatableModel.h"
|
||||
#include "TempoSyncKnobModel.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class EffectChain;
|
||||
class EffectControls;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class EffectView;
|
||||
|
||||
} // namespace gui
|
||||
|
||||
|
||||
class LMMS_EXPORT Effect : public Plugin
|
||||
{
|
||||
MM_OPERATORS
|
||||
Q_OBJECT
|
||||
public:
|
||||
Effect( const Plugin::Descriptor * _desc,
|
||||
Model * _parent,
|
||||
const Descriptor::SubPluginFeatures::Key * _key );
|
||||
virtual ~Effect();
|
||||
~Effect() override;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
@@ -55,9 +63,8 @@ public:
|
||||
return "effect";
|
||||
}
|
||||
|
||||
|
||||
virtual bool processAudioBuffer( sampleFrame * _buf,
|
||||
const fpp_t _frames ) = 0;
|
||||
//! Returns true if audio was processed and should continue being processed
|
||||
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames);
|
||||
|
||||
inline ch_cnt_t processorCount() const
|
||||
{
|
||||
@@ -103,8 +110,8 @@ public:
|
||||
|
||||
inline f_cnt_t timeout() const
|
||||
{
|
||||
const float samples = Engine::mixer()->processingSampleRate() * m_autoQuitModel.value() / 1000.0f;
|
||||
return 1 + ( static_cast<int>( samples ) / Engine::mixer()->framesPerPeriod() );
|
||||
const float samples = Engine::audioEngine()->outputSampleRate() * m_autoQuitModel.value() / 1000.0f;
|
||||
return 1 + ( static_cast<int>( samples ) / Engine::audioEngine()->framesPerPeriod() );
|
||||
}
|
||||
|
||||
inline float wetLevel() const
|
||||
@@ -147,6 +154,11 @@ public:
|
||||
{
|
||||
m_noRun = _state;
|
||||
}
|
||||
|
||||
inline TempoSyncKnobModel* autoQuitModel()
|
||||
{
|
||||
return &m_autoQuitModel;
|
||||
}
|
||||
|
||||
EffectChain * effectChain() const
|
||||
{
|
||||
@@ -161,46 +173,71 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
Effects should call this at the end of audio processing
|
||||
enum class ProcessStatus
|
||||
{
|
||||
//! Unconditionally continue processing
|
||||
Continue,
|
||||
|
||||
//! Calculate the RMS out sum and call `checkGate` to determine whether to stop processing
|
||||
ContinueIfNotQuiet,
|
||||
|
||||
//! Do not continue processing
|
||||
Sleep
|
||||
};
|
||||
|
||||
/**
|
||||
* The main audio processing method that runs when plugin is not asleep
|
||||
*/
|
||||
virtual ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) = 0;
|
||||
|
||||
/**
|
||||
* Optional method that runs when plugin is sleeping (not enabled,
|
||||
* not running, not in the Okay state, or in the Don't Run state)
|
||||
*/
|
||||
virtual void processBypassedImpl() {}
|
||||
|
||||
|
||||
gui::PluginView* instantiateView( QWidget * ) override;
|
||||
|
||||
// some effects might not be capable of higher sample-rates so they can
|
||||
// sample it down before processing and back after processing
|
||||
inline void sampleDown( const SampleFrame* _src_buf,
|
||||
SampleFrame* _dst_buf,
|
||||
sample_rate_t _dst_sr )
|
||||
{
|
||||
resample( 0, _src_buf,
|
||||
Engine::audioEngine()->outputSampleRate(),
|
||||
_dst_buf, _dst_sr,
|
||||
Engine::audioEngine()->framesPerPeriod() );
|
||||
}
|
||||
|
||||
inline void sampleBack( const SampleFrame* _src_buf,
|
||||
SampleFrame* _dst_buf,
|
||||
sample_rate_t _src_sr )
|
||||
{
|
||||
resample( 1, _src_buf, _src_sr, _dst_buf,
|
||||
Engine::audioEngine()->outputSampleRate(),
|
||||
Engine::audioEngine()->framesPerPeriod() * _src_sr /
|
||||
Engine::audioEngine()->outputSampleRate() );
|
||||
}
|
||||
void reinitSRC();
|
||||
|
||||
virtual void onEnabledChanged() {}
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
If the setting "Keep effects running even without input" is disabled,
|
||||
after "decay" ms of a signal below "gate", the effect is turned off
|
||||
and won't be processed again until it receives new audio input
|
||||
*/
|
||||
void checkGate( double _out_sum );
|
||||
|
||||
PluginView * instantiateView( QWidget * ) override;
|
||||
|
||||
// some effects might not be capable of higher sample-rates so they can
|
||||
// sample it down before processing and back after processing
|
||||
inline void sampleDown( const sampleFrame * _src_buf,
|
||||
sampleFrame * _dst_buf,
|
||||
sample_rate_t _dst_sr )
|
||||
{
|
||||
resample( 0, _src_buf,
|
||||
Engine::mixer()->processingSampleRate(),
|
||||
_dst_buf, _dst_sr,
|
||||
Engine::mixer()->framesPerPeriod() );
|
||||
}
|
||||
|
||||
inline void sampleBack( const sampleFrame * _src_buf,
|
||||
sampleFrame * _dst_buf,
|
||||
sample_rate_t _src_sr )
|
||||
{
|
||||
resample( 1, _src_buf, _src_sr, _dst_buf,
|
||||
Engine::mixer()->processingSampleRate(),
|
||||
Engine::mixer()->framesPerPeriod() * _src_sr /
|
||||
Engine::mixer()->processingSampleRate() );
|
||||
}
|
||||
void reinitSRC();
|
||||
void checkGate(double outSum);
|
||||
|
||||
|
||||
private:
|
||||
EffectChain * m_parent;
|
||||
void resample( int _i, const sampleFrame * _src_buf,
|
||||
void resample( int _i, const SampleFrame* _src_buf,
|
||||
sample_rate_t _src_sr,
|
||||
sampleFrame * _dst_buf, sample_rate_t _dst_sr,
|
||||
SampleFrame* _dst_buf, sample_rate_t _dst_sr,
|
||||
const f_cnt_t _frames );
|
||||
|
||||
ch_cnt_t m_processors;
|
||||
@@ -221,14 +258,14 @@ private:
|
||||
SRC_STATE * m_srcState[2];
|
||||
|
||||
|
||||
friend class EffectView;
|
||||
friend class gui::EffectView;
|
||||
friend class EffectChain;
|
||||
|
||||
} ;
|
||||
|
||||
using EffectKey = Effect::Descriptor::SubPluginFeatures::Key;
|
||||
using EffectKeyList = Effect::Descriptor::SubPluginFeatures::KeyList;
|
||||
|
||||
typedef Effect::Descriptor::SubPluginFeatures::Key EffectKey;
|
||||
typedef Effect::Descriptor::SubPluginFeatures::KeyList EffectKeyList;
|
||||
} // namespace lmms
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_EFFECT_H
|
||||
|
||||
@@ -23,14 +23,25 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_CHAIN_H
|
||||
#define EFFECT_CHAIN_H
|
||||
#ifndef LMMS_EFFECT_CHAIN_H
|
||||
#define LMMS_EFFECT_CHAIN_H
|
||||
|
||||
#include "Model.h"
|
||||
#include "SerializingObject.h"
|
||||
#include "AutomatableModel.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class Effect;
|
||||
class SampleFrame;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class EffectRackView;
|
||||
|
||||
} // namespace gui
|
||||
|
||||
|
||||
class LMMS_EXPORT EffectChain : public Model, public SerializingObject
|
||||
@@ -38,7 +49,7 @@ class LMMS_EXPORT EffectChain : public Model, public SerializingObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectChain( Model * _parent );
|
||||
virtual ~EffectChain();
|
||||
~EffectChain() override;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
@@ -52,20 +63,20 @@ public:
|
||||
void removeEffect( Effect * _effect );
|
||||
void moveDown( Effect * _effect );
|
||||
void moveUp( Effect * _effect );
|
||||
bool processAudioBuffer( sampleFrame * _buf, const fpp_t _frames, bool hasInputNoise );
|
||||
bool processAudioBuffer( SampleFrame* _buf, const fpp_t _frames, bool hasInputNoise );
|
||||
void startRunning();
|
||||
|
||||
void clear();
|
||||
|
||||
|
||||
private:
|
||||
typedef QVector<Effect *> EffectList;
|
||||
using EffectList = std::vector<Effect*>;
|
||||
EffectList m_effects;
|
||||
|
||||
BoolModel m_enabledModel;
|
||||
|
||||
|
||||
friend class EffectRackView;
|
||||
friend class gui::EffectRackView;
|
||||
|
||||
|
||||
signals:
|
||||
@@ -73,5 +84,6 @@ signals:
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_EFFECT_CHAIN_H
|
||||
|
||||
@@ -23,22 +23,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
#include "ModelView.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class EffectControls;
|
||||
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class LMMS_EXPORT EffectControlDialog : public QWidget, public ModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectControlDialog( EffectControls * _controls );
|
||||
virtual ~EffectControlDialog();
|
||||
~EffectControlDialog() override = default;
|
||||
|
||||
virtual bool isResizable() const {return false;}
|
||||
|
||||
@@ -54,4 +60,8 @@ protected:
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GUI_EFFECT_CONTROL_DIALOG_H
|
||||
|
||||
@@ -22,15 +22,23 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_CONTROLS_H
|
||||
#define EFFECT_CONTROLS_H
|
||||
#ifndef LMMS_EFFECT_CONTROLS_H
|
||||
#define LMMS_EFFECT_CONTROLS_H
|
||||
|
||||
#include "Model.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "Effect.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class EffectControlDialog;
|
||||
|
||||
} // namespace gui
|
||||
|
||||
class EffectControls : public JournallingObject, public Model
|
||||
{
|
||||
@@ -43,12 +51,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~EffectControls()
|
||||
{
|
||||
}
|
||||
~EffectControls() override = default;
|
||||
|
||||
virtual int controlCount() = 0;
|
||||
virtual EffectControlDialog * createView() = 0;
|
||||
virtual gui::EffectControlDialog * createView() = 0;
|
||||
|
||||
|
||||
void setViewVisible( bool _visible )
|
||||
@@ -73,4 +79,7 @@ private:
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#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>
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
class QScrollArea;
|
||||
class QVBoxLayout;
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class EffectView;
|
||||
class GroupBox;
|
||||
|
||||
@@ -43,17 +46,16 @@ class EffectRackView : public QWidget, public ModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectRackView( EffectChain* model, QWidget* parent = NULL );
|
||||
virtual ~EffectRackView();
|
||||
EffectRackView( EffectChain* model, QWidget* parent = nullptr );
|
||||
~EffectRackView() override;
|
||||
|
||||
static constexpr int DEFAULT_WIDTH = 245;
|
||||
|
||||
public slots:
|
||||
void clearViews();
|
||||
void moveUp( EffectView* view );
|
||||
void moveDown( EffectView* view );
|
||||
void deletePlugin( EffectView* view );
|
||||
|
||||
void moveUp(EffectView* view);
|
||||
void moveDown(EffectView* view);
|
||||
void deletePlugin(EffectView* view);
|
||||
|
||||
private slots:
|
||||
virtual void update();
|
||||
@@ -62,6 +64,8 @@ private slots:
|
||||
|
||||
private:
|
||||
void modelChanged() override;
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override { return sizeHint(); }
|
||||
|
||||
inline EffectChain* fxChain()
|
||||
{
|
||||
@@ -83,4 +87,6 @@ private:
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
} // namespace lmms::gui
|
||||
|
||||
#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,49 +23,98 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_SELECT_DIALOG_H
|
||||
#define EFFECT_SELECT_DIALOG_H
|
||||
#ifndef LMMS_GUI_EFFECT_SELECT_DIALOG_H
|
||||
#define LMMS_GUI_EFFECT_SELECT_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStandardItemModel>
|
||||
|
||||
#include "EffectChain.h"
|
||||
#include "Effect.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QHeaderView>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
#include <QRegularExpression>
|
||||
#include <QScrollArea>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTableView>
|
||||
|
||||
namespace Ui { class EffectSelectDialog; }
|
||||
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 );
|
||||
virtual ~EffectSelectDialog();
|
||||
|
||||
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,18 +23,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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;
|
||||
class QMdiSubWindow;
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class EffectControlDialog;
|
||||
class Knob;
|
||||
class LedCheckBox;
|
||||
@@ -46,7 +50,7 @@ class EffectView : public PluginView
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectView( Effect * _model, QWidget * _parent );
|
||||
virtual ~EffectView();
|
||||
~EffectView() override;
|
||||
|
||||
inline Effect * effect()
|
||||
{
|
||||
@@ -58,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();
|
||||
@@ -68,10 +77,9 @@ public slots:
|
||||
|
||||
|
||||
signals:
|
||||
void moveUp( EffectView * _plugin );
|
||||
void moveDown( EffectView * _plugin );
|
||||
void deletePlugin( EffectView * _plugin );
|
||||
|
||||
void movedUp(EffectView* view);
|
||||
void movedDown(EffectView* view);
|
||||
void deletedPlugin(EffectView* view);
|
||||
|
||||
protected:
|
||||
void contextMenuEvent( QContextMenuEvent * _me ) override;
|
||||
@@ -87,7 +95,13 @@ private:
|
||||
Knob * m_gate;
|
||||
QMdiSubWindow * m_subWindow;
|
||||
EffectControlDialog * m_controlView;
|
||||
|
||||
bool m_dragging;
|
||||
QGraphicsOpacityEffect* m_opacityEffect;
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_EFFECT_VIEW_H
|
||||
|
||||
@@ -22,39 +22,33 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_ENGINE_H
|
||||
#define LMMS_ENGINE_H
|
||||
|
||||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
#include "lmms_export.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
class BBTrackContainer;
|
||||
class FxMixer;
|
||||
class ProjectJournal;
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class AudioEngine;
|
||||
class Mixer;
|
||||
class PatternStore;
|
||||
class ProjectJournal;
|
||||
class Song;
|
||||
class Ladspa2LMMS;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class GuiApplication;
|
||||
}
|
||||
|
||||
// Note: This class is called 'LmmsCore' instead of 'Engine' because of naming
|
||||
// conflicts caused by ZynAddSubFX. See https://github.com/LMMS/lmms/issues/2269
|
||||
// and https://github.com/LMMS/lmms/pull/2118 for more details.
|
||||
//
|
||||
// The workaround was to rename Lmms' Engine so that it has a different symbol
|
||||
// name in the object files, but typedef it back to 'Engine' and keep it inside
|
||||
// of Engine.h so that the rest of the codebase can be oblivious to this issue
|
||||
// (and it could be fixed without changing every single file).
|
||||
|
||||
class LmmsCore;
|
||||
typedef LmmsCore Engine;
|
||||
|
||||
class LMMS_EXPORT LmmsCore : public QObject
|
||||
class LMMS_EXPORT Engine : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -62,14 +56,14 @@ public:
|
||||
static void destroy();
|
||||
|
||||
// core
|
||||
static Mixer *mixer()
|
||||
static AudioEngine *audioEngine()
|
||||
{
|
||||
return s_mixer;
|
||||
return s_audioEngine;
|
||||
}
|
||||
|
||||
static FxMixer * fxMixer()
|
||||
static Mixer * mixer()
|
||||
{
|
||||
return s_fxMixer;
|
||||
return s_mixer;
|
||||
}
|
||||
|
||||
static Song * getSong()
|
||||
@@ -77,9 +71,9 @@ public:
|
||||
return s_song;
|
||||
}
|
||||
|
||||
static BBTrackContainer * getBBTrackContainer()
|
||||
static PatternStore * patternStore()
|
||||
{
|
||||
return s_bbTrackContainer;
|
||||
return s_patternStore;
|
||||
}
|
||||
|
||||
static ProjectJournal * projectJournal()
|
||||
@@ -87,8 +81,6 @@ public:
|
||||
return s_projectJournal;
|
||||
}
|
||||
|
||||
static bool ignorePluginBlacklist();
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
static class Lv2Manager * getLv2Manager()
|
||||
{
|
||||
@@ -110,11 +102,11 @@ public:
|
||||
|
||||
static void updateFramesPerTick();
|
||||
|
||||
static inline LmmsCore * inst()
|
||||
static inline Engine * inst()
|
||||
{
|
||||
if( s_instanceOfMe == NULL )
|
||||
if( s_instanceOfMe == nullptr )
|
||||
{
|
||||
s_instanceOfMe = new LmmsCore();
|
||||
s_instanceOfMe = new Engine();
|
||||
}
|
||||
return s_instanceOfMe;
|
||||
}
|
||||
@@ -130,34 +122,35 @@ private:
|
||||
// small helper function which sets the pointer to NULL before actually deleting
|
||||
// the object it refers to
|
||||
template<class T>
|
||||
static inline void deleteHelper( T * * ptr )
|
||||
static inline void deleteHelper(T** ptr)
|
||||
{
|
||||
T * tmp = *ptr;
|
||||
*ptr = NULL;
|
||||
T* tmp = *ptr;
|
||||
*ptr = nullptr;
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
static float s_framesPerTick;
|
||||
|
||||
// core
|
||||
static Mixer *s_mixer;
|
||||
static FxMixer * s_fxMixer;
|
||||
static AudioEngine *s_audioEngine;
|
||||
static Mixer * s_mixer;
|
||||
static Song * s_song;
|
||||
static BBTrackContainer * s_bbTrackContainer;
|
||||
static PatternStore * s_patternStore;
|
||||
static ProjectJournal * s_projectJournal;
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
static class Lv2Manager* s_lv2Manager;
|
||||
#endif
|
||||
static Ladspa2LMMS * s_ladspaManager;
|
||||
static Ladspa2LMMS* s_ladspaManager;
|
||||
static void* s_dndPluginKey;
|
||||
|
||||
// even though most methods are static, an instance is needed for Qt slots/signals
|
||||
static LmmsCore * s_instanceOfMe;
|
||||
static Engine* s_instanceOfMe;
|
||||
|
||||
friend class GuiApplication;
|
||||
friend class gui::GuiApplication;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#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 <QtCore/QVector>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "JournallingObject.h"
|
||||
#include "AutomatableModel.h"
|
||||
@@ -33,6 +34,15 @@
|
||||
#include "TempoSyncKnobModel.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class EnvelopeAndLfoView;
|
||||
|
||||
}
|
||||
|
||||
class LMMS_EXPORT EnvelopeAndLfoParameters : public Model, public JournallingObject
|
||||
{
|
||||
@@ -41,13 +51,9 @@ public:
|
||||
class LfoInstances
|
||||
{
|
||||
public:
|
||||
LfoInstances()
|
||||
{
|
||||
}
|
||||
LfoInstances() = default;
|
||||
|
||||
~LfoInstances()
|
||||
{
|
||||
}
|
||||
~LfoInstances() = default;
|
||||
|
||||
inline bool isEmpty() const
|
||||
{
|
||||
@@ -62,14 +68,25 @@ public:
|
||||
|
||||
private:
|
||||
QMutex m_lfoListMutex;
|
||||
typedef QList<EnvelopeAndLfoParameters *> LfoList;
|
||||
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 );
|
||||
virtual ~EnvelopeAndLfoParameters();
|
||||
~EnvelopeAndLfoParameters() override;
|
||||
|
||||
static inline float expKnobVal( float _val )
|
||||
{
|
||||
@@ -108,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();
|
||||
@@ -162,25 +201,18 @@ 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();
|
||||
|
||||
|
||||
friend class EnvelopeAndLfoView;
|
||||
friend class gui::EnvelopeAndLfoView;
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_ENVELOPE_AND_LFO_PARAMETERS_H
|
||||
|
||||
@@ -23,23 +23,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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
|
||||
{
|
||||
|
||||
class EnvelopeAndLfoParameters;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class automatableButtonGroup;
|
||||
class Knob;
|
||||
class LedCheckBox;
|
||||
class PixmapButton;
|
||||
class TempoSyncKnob;
|
||||
class EnvelopeGraph;
|
||||
class LfoGraph;
|
||||
|
||||
|
||||
|
||||
@@ -48,7 +53,7 @@ class EnvelopeAndLfoView : public QWidget, public ModelView
|
||||
Q_OBJECT
|
||||
public:
|
||||
EnvelopeAndLfoView( QWidget * _parent );
|
||||
virtual ~EnvelopeAndLfoView();
|
||||
~EnvelopeAndLfoView() override;
|
||||
|
||||
|
||||
protected:
|
||||
@@ -56,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:
|
||||
@@ -65,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;
|
||||
@@ -81,6 +81,7 @@ private:
|
||||
Knob * m_amountKnob;
|
||||
|
||||
// LFO stuff
|
||||
LfoGraph* m_lfoGraph;
|
||||
Knob * m_lfoPredelayKnob;
|
||||
Knob * m_lfoAttackKnob;
|
||||
TempoSyncKnob * m_lfoSpeedKnob;
|
||||
@@ -90,8 +91,10 @@ private:
|
||||
|
||||
LedCheckBox * m_x100Cb;
|
||||
LedCheckBox * m_controlEnvAmountCb;
|
||||
|
||||
float m_randomGraph;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#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,24 +23,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EXPORT_FILTER_H
|
||||
#define EXPORT_FILTER_H
|
||||
#ifndef LMMS_EXPORT_FILTER_H
|
||||
#define LMMS_EXPORT_FILTER_H
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QFile>
|
||||
|
||||
#include "TrackContainer.h"
|
||||
#include "Plugin.h"
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
|
||||
class LMMS_EXPORT ExportFilter : public Plugin
|
||||
{
|
||||
public:
|
||||
ExportFilter( const Descriptor * _descriptor ) : Plugin( _descriptor, NULL ) {}
|
||||
virtual ~ExportFilter() {}
|
||||
ExportFilter( const Descriptor * _descriptor ) : Plugin( _descriptor, nullptr ) {}
|
||||
~ExportFilter() override = default;
|
||||
|
||||
|
||||
virtual bool tryExport(const TrackContainer::TrackList &tracks,
|
||||
const TrackContainer::TrackList &tracksBB,
|
||||
const TrackContainer::TrackList &patternTracks,
|
||||
int tempo, int masterPitch, const QString &filename ) = 0;
|
||||
protected:
|
||||
|
||||
@@ -63,4 +67,6 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#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>
|
||||
@@ -34,6 +33,10 @@
|
||||
#include "ProjectRenderer.h"
|
||||
#include "RenderManager.h"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
class ExportProjectDialog : public QDialog, public Ui::ExportProjectDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -41,12 +44,12 @@ public:
|
||||
ExportProjectDialog( const QString & _file_name, QWidget * _parent, bool multi_export );
|
||||
|
||||
protected:
|
||||
void reject( void ) override;
|
||||
void reject() override;
|
||||
void closeEvent( QCloseEvent * _ce ) override;
|
||||
|
||||
|
||||
private slots:
|
||||
void startBtnClicked( void );
|
||||
void startBtnClicked();
|
||||
void updateTitleBar( int );
|
||||
void accept() override;
|
||||
void startExport();
|
||||
@@ -59,8 +62,11 @@ private:
|
||||
QString m_fileExtension;
|
||||
bool m_multiExport;
|
||||
|
||||
ProjectRenderer::ExportFileFormats m_ft;
|
||||
ProjectRenderer::ExportFileFormat m_ft;
|
||||
std::unique_ptr<RenderManager> m_renderManager;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_EXPORT_PROJECT_DIALOG_H
|
||||
|
||||
@@ -22,15 +22,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FADE_BUTTON_H
|
||||
#define FADE_BUTTON_H
|
||||
#ifndef LMMS_GUI_FADE_BUTTON_H
|
||||
#define LMMS_GUI_FADE_BUTTON_H
|
||||
|
||||
#include <QAbstractButton>
|
||||
#include <QColor>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
class FadeButton : public QAbstractButton
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -40,7 +43,7 @@ public:
|
||||
const QColor & _hold_color,
|
||||
QWidget * _parent );
|
||||
|
||||
virtual ~FadeButton();
|
||||
~FadeButton() override = default;
|
||||
void setActiveColor( const QColor & activated_color );
|
||||
|
||||
|
||||
@@ -71,4 +74,6 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_FADE_BUTTON_H
|
||||
|
||||
128
include/Fader.h
128
include/Fader.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Fader.h - fader-widget used in FX-mixer - partly taken from Hydrogen
|
||||
* Fader.h - fader-widget used in Mixer - partly taken from Hydrogen
|
||||
*
|
||||
* Copyright (c) 2008-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -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,29 +53,35 @@
|
||||
|
||||
|
||||
#include "AutomatableModelView.h"
|
||||
#include "embed.h"
|
||||
#include "lmms_math.h"
|
||||
|
||||
class TextFloat;
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
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 );
|
||||
virtual ~Fader() = default;
|
||||
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; }
|
||||
@@ -85,88 +90,77 @@ 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);
|
||||
}
|
||||
|
||||
signals:
|
||||
void peakChanged(float peak);
|
||||
|
||||
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};
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_FADER_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* fifo_buffer.h - FIFO fixed-size buffer
|
||||
* FifoBuffer.h - FIFO fixed-size buffer
|
||||
*
|
||||
* Copyright (c) 2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -22,73 +22,76 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FIFO_BUFFER_H
|
||||
#define FIFO_BUFFER_H
|
||||
#ifndef LMMS_FIFO_BUFFER_H
|
||||
#define LMMS_FIFO_BUFFER_H
|
||||
|
||||
#include <QtCore/QSemaphore>
|
||||
#include <QSemaphore>
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
|
||||
template<typename T>
|
||||
class fifoBuffer
|
||||
class FifoBuffer
|
||||
{
|
||||
public:
|
||||
fifoBuffer( int _size ) :
|
||||
m_reader_sem( _size ),
|
||||
m_writer_sem( _size ),
|
||||
m_reader_index( 0 ),
|
||||
m_writer_index( 0 ),
|
||||
m_size( _size )
|
||||
FifoBuffer(int size) :
|
||||
m_readSem(size),
|
||||
m_writeSem(size),
|
||||
m_readIndex(0),
|
||||
m_writeIndex(0),
|
||||
m_size(size)
|
||||
{
|
||||
m_buffer = new T[_size];
|
||||
m_reader_sem.acquire( _size );
|
||||
m_buffer = new T[size];
|
||||
m_readSem.acquire(size);
|
||||
}
|
||||
|
||||
~fifoBuffer()
|
||||
~FifoBuffer()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
m_reader_sem.release( m_size );
|
||||
m_readSem.release(m_size);
|
||||
}
|
||||
|
||||
void write( T _element )
|
||||
void write(T element)
|
||||
{
|
||||
m_writer_sem.acquire();
|
||||
m_buffer[m_writer_index++] = _element;
|
||||
m_writer_index %= m_size;
|
||||
m_reader_sem.release();
|
||||
m_writeSem.acquire();
|
||||
m_buffer[m_writeIndex++] = element;
|
||||
m_writeIndex %= m_size;
|
||||
m_readSem.release();
|
||||
}
|
||||
|
||||
T read()
|
||||
{
|
||||
m_reader_sem.acquire();
|
||||
T element = m_buffer[m_reader_index++];
|
||||
m_reader_index %= m_size;
|
||||
m_writer_sem.release();
|
||||
return( element );
|
||||
m_readSem.acquire();
|
||||
T element = m_buffer[m_readIndex++];
|
||||
m_readIndex %= m_size;
|
||||
m_writeSem.release();
|
||||
return element;
|
||||
}
|
||||
|
||||
void waitUntilRead()
|
||||
{
|
||||
m_writer_sem.acquire( m_size );
|
||||
m_writer_sem.release( m_size );
|
||||
m_writeSem.acquire(m_size);
|
||||
m_writeSem.release(m_size);
|
||||
}
|
||||
|
||||
bool available()
|
||||
{
|
||||
return( m_reader_sem.available() );
|
||||
return m_readSem.available();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QSemaphore m_reader_sem;
|
||||
QSemaphore m_writer_sem;
|
||||
int m_reader_index;
|
||||
int m_writer_index;
|
||||
QSemaphore m_readSem;
|
||||
QSemaphore m_writeSem;
|
||||
int m_readIndex;
|
||||
int m_writeIndex;
|
||||
int m_size;
|
||||
T * m_buffer;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_FIFO_BUFFER_H
|
||||
@@ -22,28 +22,40 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FILE_BROWSER_H
|
||||
#define FILE_BROWSER_H
|
||||
#ifndef LMMS_GUI_FILE_BROWSER_H
|
||||
#define LMMS_GUI_FILE_BROWSER_H
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QDir>
|
||||
#include <QMutex>
|
||||
#include <QProgressBar>
|
||||
#include <memory>
|
||||
|
||||
#include "FileSearch.h"
|
||||
#include "embed.h"
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
|
||||
#include <QRecursiveMutex>
|
||||
#endif
|
||||
#include <QTreeWidget>
|
||||
|
||||
|
||||
#include "SideBarWidget.h"
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
class FileItem;
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class InstrumentTrack;
|
||||
class FileBrowserTreeWidget;
|
||||
class PlayHandle;
|
||||
class TrackContainer;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class FileItem;
|
||||
class FileBrowserTreeWidget;
|
||||
|
||||
class FileBrowser : public SideBarWidget
|
||||
{
|
||||
@@ -59,17 +71,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 = "");
|
||||
|
||||
virtual ~FileBrowser() = default;
|
||||
~FileBrowser() override = default;
|
||||
|
||||
static QStringList excludedPaths()
|
||||
{
|
||||
static auto s_excludedPaths = QStringList{
|
||||
#ifdef LMMS_BUILD_LINUX
|
||||
"/bin", "/boot", "/dev", "/etc", "/proc", "/run", "/sbin",
|
||||
"/sys"
|
||||
#endif
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
"C:\\Windows"
|
||||
#endif
|
||||
};
|
||||
return s_excludedPaths;
|
||||
}
|
||||
static QDir::Filters dirFilters() { return QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden; }
|
||||
static QDir::SortFlags sortFlags() { return QDir::LocaleAware | QDir::DirsFirst | QDir::Name | QDir::IgnoreCase; }
|
||||
|
||||
private slots:
|
||||
void reloadTree( void );
|
||||
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 reloadTree();
|
||||
void expandItems(const QList<QString>& expandedDirs, QTreeWidgetItem* item = nullptr);
|
||||
void giveFocusToFilter();
|
||||
|
||||
private:
|
||||
@@ -77,21 +103,40 @@ private:
|
||||
|
||||
void addItems( const QString & path );
|
||||
|
||||
void saveDirectoriesStates();
|
||||
void restoreDirectoriesStates();
|
||||
|
||||
void foundSearchMatch(FileSearch* search, const QString& match);
|
||||
void searchCompleted(FileSearch* search);
|
||||
void onSearch(const QString& filter);
|
||||
void displaySearch(bool on);
|
||||
|
||||
void addContentCheckBox();
|
||||
|
||||
FileBrowserTreeWidget * m_fileBrowserTreeWidget;
|
||||
FileBrowserTreeWidget * m_searchTreeWidget;
|
||||
|
||||
QLineEdit * m_filterEdit;
|
||||
|
||||
std::shared_ptr<FileSearch> 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;
|
||||
QCheckBox* m_showHiddenContent = nullptr;
|
||||
|
||||
QBoxLayout *filterWidgetLayout = nullptr;
|
||||
QBoxLayout *hiddenWidgetLayout = nullptr;
|
||||
QBoxLayout *outerLayout = nullptr;
|
||||
QString m_userDir;
|
||||
QString m_factoryDir;
|
||||
QList<QString> m_savedExpandedDirs;
|
||||
QString m_previousFilterValue;
|
||||
} ;
|
||||
|
||||
|
||||
@@ -102,13 +147,12 @@ class FileBrowserTreeWidget : public QTreeWidget
|
||||
Q_OBJECT
|
||||
public:
|
||||
FileBrowserTreeWidget( QWidget * parent );
|
||||
virtual ~FileBrowserTreeWidget() = default;
|
||||
~FileBrowserTreeWidget() override = default;
|
||||
|
||||
//! This method returns a QList with paths (QString's) of all directories
|
||||
//! that are expanded in the tree.
|
||||
QList<QString> expandedDirs( QTreeWidgetItem * item = nullptr ) const;
|
||||
|
||||
|
||||
protected:
|
||||
void contextMenuEvent( QContextMenuEvent * e ) override;
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
@@ -135,31 +179,34 @@ private:
|
||||
|
||||
//! This should only be accessed or modified when m_pphMutex is held
|
||||
PlayHandle* m_previewPlayHandle;
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
|
||||
QRecursiveMutex m_pphMutex;
|
||||
#else
|
||||
QMutex m_pphMutex;
|
||||
#endif
|
||||
|
||||
QList<QAction*> getContextActions(FileItem* item, bool songEditor);
|
||||
|
||||
|
||||
private slots:
|
||||
void activateListItem( QTreeWidgetItem * item, int column );
|
||||
void openInNewInstrumentTrack( FileItem* item, bool songEditor );
|
||||
bool openInNewSampleTrack( FileItem* item );
|
||||
void sendToActiveInstrumentTrack( FileItem* item );
|
||||
void openInNewInstrumentTrack( lmms::gui::FileItem* item, bool songEditor );
|
||||
bool openInNewSampleTrack( lmms::gui::FileItem* item );
|
||||
void sendToActiveInstrumentTrack( lmms::gui::FileItem* item );
|
||||
void updateDirectory( QTreeWidgetItem * item );
|
||||
void openContainingFolder( FileItem* item );
|
||||
void openContainingFolder( lmms::gui::FileItem* item );
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
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( void );
|
||||
void update();
|
||||
|
||||
inline QString fullName( QString path = QString() )
|
||||
{
|
||||
@@ -182,14 +229,12 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void initPixmaps( void );
|
||||
|
||||
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
|
||||
@@ -202,7 +247,7 @@ private:
|
||||
QString m_filter;
|
||||
|
||||
int m_dirCount;
|
||||
|
||||
bool m_disableEntryPopulation = false;
|
||||
} ;
|
||||
|
||||
|
||||
@@ -211,20 +256,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,
|
||||
@@ -243,42 +287,39 @@ public:
|
||||
return QFileInfo(m_path, text(0)).absoluteFilePath();
|
||||
}
|
||||
|
||||
inline FileTypes type( void ) const
|
||||
inline FileType type() const
|
||||
{
|
||||
return( m_type );
|
||||
}
|
||||
|
||||
inline FileHandling handling( void ) const
|
||||
inline FileHandling handling() const
|
||||
{
|
||||
return( m_handling );
|
||||
}
|
||||
|
||||
inline bool isTrack( void ) const
|
||||
inline bool isTrack() const
|
||||
{
|
||||
return m_handling == LoadAsPreset || m_handling == LoadByPlugin;
|
||||
return m_handling == FileHandling::LoadAsPreset || m_handling == FileHandling::LoadByPlugin;
|
||||
}
|
||||
|
||||
QString extension( void );
|
||||
QString extension();
|
||||
static QString extension( const QString & file );
|
||||
static QString defaultFilters();
|
||||
|
||||
|
||||
private:
|
||||
void initPixmaps( void );
|
||||
void determineFileType( void );
|
||||
|
||||
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;
|
||||
void initPixmaps();
|
||||
void determineFileType();
|
||||
|
||||
QString m_path;
|
||||
FileTypes m_type;
|
||||
FileType m_type;
|
||||
FileHandling m_handling;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GUI_FILE_BROWSER_H
|
||||
|
||||
@@ -22,14 +22,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FILEDIALOG_H
|
||||
#define FILEDIALOG_H
|
||||
#ifndef LMMS_GUI_FILE_DIALOG_H
|
||||
#define LMMS_GUI_FILE_DIALOG_H
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "lmms_export.h"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
class LMMS_EXPORT FileDialog : public QFileDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -50,4 +53,7 @@ public:
|
||||
void clearSelection();
|
||||
};
|
||||
|
||||
#endif // FILEDIALOG_HPP
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_FILE_DIALOG_H
|
||||
|
||||
73
include/FileSearch.h
Normal file
73
include/FileSearch.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* FileSearch.h - File system search task
|
||||
*
|
||||
* Copyright (c) 2024 saker
|
||||
*
|
||||
* 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_SEARCH_H
|
||||
#define LMMS_FILE_SEARCH_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QObject>
|
||||
#include <atomic>
|
||||
|
||||
namespace lmms {
|
||||
//! A Qt object that encapsulates the operation of searching the file system.
|
||||
class FileSearch : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
//! Number of milliseconds the search waits before signaling a matching result.
|
||||
static constexpr int MillisecondsBetweenResults = 1;
|
||||
|
||||
//! Create a `FileSearch` object that uses the specified string filter `filter` and extension filters in
|
||||
//! `extensions` to search within the given `paths`.
|
||||
//! `excludedPaths`, `dirFilters`, and `sortFlags` can optionally be specified to exclude certain directories, filter
|
||||
//! out certain types of entries, and sort the matches.
|
||||
FileSearch(const QString& filter, const QStringList& paths, const QStringList& extensions,
|
||||
const QStringList& excludedPaths = {}, QDir::Filters dirFilters = QDir::Filters{},
|
||||
QDir::SortFlags sortFlags = QDir::SortFlags{});
|
||||
|
||||
//! Execute the search, emitting the `foundResult` signal when matches are found.
|
||||
void operator()();
|
||||
|
||||
//! Cancel the search.
|
||||
void cancel();
|
||||
|
||||
signals:
|
||||
//! Emitted when a result is found when searching the file system.
|
||||
void foundMatch(FileSearch* search, const QString& match);
|
||||
|
||||
//! Emitted when the search completes.
|
||||
void searchCompleted(FileSearch* search);
|
||||
|
||||
private:
|
||||
static auto isPathExcluded(const QString& path) -> bool;
|
||||
QString m_filter;
|
||||
QStringList m_paths;
|
||||
QStringList m_extensions;
|
||||
QStringList m_excludedPaths;
|
||||
QDir::Filters m_dirFilters;
|
||||
QDir::SortFlags m_sortFlags;
|
||||
std::atomic<bool> m_cancel = false;
|
||||
};
|
||||
} // namespace lmms
|
||||
#endif // LMMS_FILE_SEARCH_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
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* ToolTip.h - namespace toolTip, a tooltip-wrapper for LMMS
|
||||
* FontHelper.h - Header function to help with fonts
|
||||
*
|
||||
* Copyright (c) 2005-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -22,21 +22,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_FONT_HELPER_H
|
||||
#define LMMS_FONT_HELPER_H
|
||||
|
||||
#ifndef TOOLTIP_H
|
||||
#define TOOLTIP_H
|
||||
#include <QApplication>
|
||||
#include <QFont>
|
||||
|
||||
#include <qstring.h>
|
||||
constexpr int DEFAULT_FONT_SIZE = 12;
|
||||
constexpr int SMALL_FONT_SIZE = 10;
|
||||
constexpr int LARGE_FONT_SIZE = 14;
|
||||
|
||||
#include "lmms_export.h"
|
||||
|
||||
class QWidget;
|
||||
|
||||
|
||||
struct ToolTip
|
||||
namespace lmms::gui
|
||||
{
|
||||
static void LMMS_EXPORT add( QWidget * _w, const QString & _txt );
|
||||
} ;
|
||||
|
||||
// Convenience method to set the font size in pixels
|
||||
inline QFont adjustedToPixelSize(QFont font, int size)
|
||||
{
|
||||
font.setPixelSize(size);
|
||||
return font;
|
||||
}
|
||||
|
||||
#endif
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_FONT_HELPER_H
|
||||
119
include/FxLine.h
119
include/FxLine.h
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* FxLine.h - FX line widget
|
||||
*
|
||||
* Copyright (c) 2009 Andrew Kelley <superjoe30/at/gmail/dot/com>
|
||||
* Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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 FX_LINE_H
|
||||
#define FX_LINE_H
|
||||
|
||||
#include <QColorDialog>
|
||||
#include <QGraphicsView>
|
||||
#include <QLineEdit>
|
||||
#include <QWidget>
|
||||
|
||||
#include "ColorChooser.h"
|
||||
#include "Knob.h"
|
||||
#include "LcdWidget.h"
|
||||
#include "SendButtonIndicator.h"
|
||||
|
||||
|
||||
|
||||
class FxMixerView;
|
||||
class SendButtonIndicator;
|
||||
|
||||
class FxLine : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_PROPERTY( QBrush backgroundActive READ backgroundActive WRITE setBackgroundActive )
|
||||
Q_PROPERTY( QColor strokeOuterActive READ strokeOuterActive WRITE setStrokeOuterActive )
|
||||
Q_PROPERTY( QColor strokeOuterInactive READ strokeOuterInactive WRITE setStrokeOuterInactive )
|
||||
Q_PROPERTY( QColor strokeInnerActive READ strokeInnerActive WRITE setStrokeInnerActive )
|
||||
Q_PROPERTY( QColor strokeInnerInactive READ strokeInnerInactive WRITE setStrokeInnerInactive )
|
||||
FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex);
|
||||
~FxLine();
|
||||
|
||||
void paintEvent( QPaintEvent * ) override;
|
||||
void mousePressEvent( QMouseEvent * ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent * ) override;
|
||||
void contextMenuEvent( QContextMenuEvent * ) override;
|
||||
|
||||
inline int channelIndex() { return m_channelIndex; }
|
||||
void setChannelIndex(int index);
|
||||
|
||||
Knob * m_sendKnob;
|
||||
SendButtonIndicator * m_sendBtn;
|
||||
|
||||
QBrush backgroundActive() const;
|
||||
void setBackgroundActive( const QBrush & c );
|
||||
|
||||
QColor strokeOuterActive() const;
|
||||
void setStrokeOuterActive( const QColor & c );
|
||||
|
||||
QColor strokeOuterInactive() const;
|
||||
void setStrokeOuterInactive( const QColor & c );
|
||||
|
||||
QColor strokeInnerActive() const;
|
||||
void setStrokeInnerActive( const QColor & c );
|
||||
|
||||
QColor strokeInnerInactive() const;
|
||||
void setStrokeInnerInactive( const QColor & c );
|
||||
|
||||
static const int FxLineHeight;
|
||||
|
||||
bool eventFilter (QObject *dist, QEvent *event) override;
|
||||
|
||||
private:
|
||||
void drawFxLine( QPainter* p, const FxLine *fxLine, bool isActive, bool sendToThis, bool receiveFromThis );
|
||||
QString elideName( const QString & name );
|
||||
|
||||
FxMixerView * m_mv;
|
||||
LcdWidget* m_lcd;
|
||||
int m_channelIndex;
|
||||
QBrush m_backgroundActive;
|
||||
QColor m_strokeOuterActive;
|
||||
QColor m_strokeOuterInactive;
|
||||
QColor m_strokeInnerActive;
|
||||
QColor m_strokeInnerInactive;
|
||||
static QPixmap * s_sendBgArrow;
|
||||
static QPixmap * s_receiveBgArrow;
|
||||
bool m_inRename;
|
||||
QLineEdit * m_renameLineEdit;
|
||||
QGraphicsView * m_view;
|
||||
|
||||
public slots:
|
||||
void renameChannel();
|
||||
void resetColor();
|
||||
void changeColor();
|
||||
void randomColor();
|
||||
|
||||
private slots:
|
||||
void renameFinished();
|
||||
void removeChannel();
|
||||
void removeUnusedChannels();
|
||||
void moveChannelLeft();
|
||||
void moveChannelRight();
|
||||
};
|
||||
|
||||
|
||||
#endif // FXLINE_H
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
* FxMixer.h - effect-mixer for LMMS
|
||||
*
|
||||
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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 FX_MIXER_H
|
||||
#define FX_MIXER_H
|
||||
|
||||
#include "Model.h"
|
||||
#include "EffectChain.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "ThreadableJob.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <QColor>
|
||||
|
||||
class FxRoute;
|
||||
typedef QVector<FxRoute *> FxRouteVector;
|
||||
|
||||
class FxChannel : public ThreadableJob
|
||||
{
|
||||
public:
|
||||
FxChannel( int idx, Model * _parent );
|
||||
virtual ~FxChannel();
|
||||
|
||||
EffectChain m_fxChain;
|
||||
|
||||
// set to true when input fed from mixToChannel or child channel
|
||||
bool m_hasInput;
|
||||
// set to true if any effect in the channel is enabled and running
|
||||
bool m_stillRunning;
|
||||
|
||||
float m_peakLeft;
|
||||
float m_peakRight;
|
||||
sampleFrame * m_buffer;
|
||||
bool m_muteBeforeSolo;
|
||||
BoolModel m_muteModel;
|
||||
BoolModel m_soloModel;
|
||||
FloatModel m_volumeModel;
|
||||
QString m_name;
|
||||
QMutex m_lock;
|
||||
int m_channelIndex; // what channel index are we
|
||||
bool m_queued; // are we queued up for rendering yet?
|
||||
bool m_muted; // are we muted? updated per period so we don't have to call m_muteModel.value() twice
|
||||
|
||||
// pointers to other channels that this one sends to
|
||||
FxRouteVector m_sends;
|
||||
|
||||
// pointers to other channels that send to this one
|
||||
FxRouteVector m_receives;
|
||||
|
||||
bool requiresProcessing() const override { return true; }
|
||||
void unmuteForSolo();
|
||||
|
||||
|
||||
void setColor (QColor newColor)
|
||||
{
|
||||
m_color = newColor;
|
||||
m_hasColor = true;
|
||||
}
|
||||
|
||||
// TODO C++17 and above: use std::optional instead
|
||||
QColor m_color;
|
||||
bool m_hasColor;
|
||||
|
||||
|
||||
std::atomic_int m_dependenciesMet;
|
||||
void incrementDeps();
|
||||
void processed();
|
||||
|
||||
private:
|
||||
void doProcessing() override;
|
||||
};
|
||||
|
||||
|
||||
class FxRoute : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FxRoute( FxChannel * from, FxChannel * to, float amount );
|
||||
virtual ~FxRoute();
|
||||
|
||||
fx_ch_t senderIndex() const
|
||||
{
|
||||
return m_from->m_channelIndex;
|
||||
}
|
||||
|
||||
fx_ch_t receiverIndex() const
|
||||
{
|
||||
return m_to->m_channelIndex;
|
||||
}
|
||||
|
||||
FloatModel * amount()
|
||||
{
|
||||
return &m_amount;
|
||||
}
|
||||
|
||||
FxChannel * sender() const
|
||||
{
|
||||
return m_from;
|
||||
}
|
||||
|
||||
FxChannel * receiver() const
|
||||
{
|
||||
return m_to;
|
||||
}
|
||||
|
||||
void updateName();
|
||||
|
||||
private:
|
||||
FxChannel * m_from;
|
||||
FxChannel * m_to;
|
||||
FloatModel m_amount;
|
||||
};
|
||||
|
||||
|
||||
class LMMS_EXPORT FxMixer : public Model, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FxMixer();
|
||||
virtual ~FxMixer();
|
||||
|
||||
void mixToChannel( const sampleFrame * _buf, fx_ch_t _ch );
|
||||
|
||||
void prepareMasterMix();
|
||||
void masterMix( sampleFrame * _buf );
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
|
||||
QString nodeName() const override
|
||||
{
|
||||
return "fxmixer";
|
||||
}
|
||||
|
||||
FxChannel * effectChannel( int _ch )
|
||||
{
|
||||
return m_fxChannels[_ch];
|
||||
}
|
||||
|
||||
// make the output of channel fromChannel go to the input of channel toChannel
|
||||
// it is safe to call even if the send already exists
|
||||
FxRoute * createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel,
|
||||
float amount = 1.0f);
|
||||
FxRoute * createRoute( FxChannel * from, FxChannel * to, float amount );
|
||||
|
||||
// delete the connection made by createChannelSend
|
||||
void deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel);
|
||||
void deleteChannelSend( FxRoute * route );
|
||||
|
||||
// determine if adding a send from sendFrom to
|
||||
// sendTo would result in an infinite mixer loop.
|
||||
bool isInfiniteLoop(fx_ch_t fromChannel, fx_ch_t toChannel);
|
||||
bool checkInfiniteLoop( FxChannel * from, FxChannel * to );
|
||||
|
||||
// return the FloatModel of fromChannel sending its output to the input of
|
||||
// toChannel. NULL if there is no send.
|
||||
FloatModel * channelSendModel(fx_ch_t fromChannel, fx_ch_t toChannel);
|
||||
|
||||
// add a new channel to the Fx Mixer.
|
||||
// returns the index of the channel that was just added
|
||||
int createChannel();
|
||||
|
||||
// delete a channel from the FX mixer.
|
||||
void deleteChannel(int index);
|
||||
|
||||
// delete all the mixer channels except master and remove all effects
|
||||
void clear();
|
||||
|
||||
// re-arrange channels
|
||||
void moveChannelLeft(int index);
|
||||
void moveChannelRight(int index);
|
||||
|
||||
// reset a channel's name, fx, sends, etc
|
||||
void clearChannel(fx_ch_t channelIndex);
|
||||
|
||||
// rename channels when moving etc. if they still have their original name
|
||||
void validateChannelName( int index, int oldIndex );
|
||||
|
||||
void toggledSolo();
|
||||
void activateSolo();
|
||||
void deactivateSolo();
|
||||
|
||||
inline fx_ch_t numChannels() const
|
||||
{
|
||||
return m_fxChannels.size();
|
||||
}
|
||||
|
||||
FxRouteVector m_fxRoutes;
|
||||
|
||||
private:
|
||||
// the fx channels in the mixer. index 0 is always master.
|
||||
QVector<FxChannel *> m_fxChannels;
|
||||
|
||||
// make sure we have at least num channels
|
||||
void allocateChannelsTo(int num);
|
||||
|
||||
int m_lastSoloed;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -23,9 +23,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GRAPH_H
|
||||
#define GRAPH_H
|
||||
#ifndef LMMS_GUI_GRAPH_H
|
||||
#define LMMS_GUI_GRAPH_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPixmap>
|
||||
@@ -35,20 +34,26 @@
|
||||
#include "ModelView.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
|
||||
class graphModel;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -56,11 +61,11 @@ 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
|
||||
);
|
||||
virtual ~Graph() = default;
|
||||
~Graph() override = default;
|
||||
|
||||
void setForeground( const QPixmap & _pixmap );
|
||||
|
||||
@@ -72,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();
|
||||
@@ -108,7 +113,7 @@ private:
|
||||
QPixmap m_foreground;
|
||||
QColor m_graphColor;
|
||||
|
||||
graphStyle m_graphStyle;
|
||||
Style m_graphStyle;
|
||||
|
||||
bool m_mouseDown;
|
||||
int m_lastCursorX;
|
||||
@@ -116,6 +121,9 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace gui
|
||||
|
||||
|
||||
/**
|
||||
@brief 2 dimensional function plot
|
||||
|
||||
@@ -137,11 +145,11 @@ public:
|
||||
graphModel( float _min,
|
||||
float _max,
|
||||
int _size,
|
||||
:: Model * _parent,
|
||||
Model * _parent,
|
||||
bool _default_constructed = false,
|
||||
float _step = 0.0 );
|
||||
|
||||
virtual ~graphModel() = default;
|
||||
~graphModel() override = default;
|
||||
|
||||
// TODO: saveSettings, loadSettings?
|
||||
|
||||
@@ -187,7 +195,7 @@ public slots:
|
||||
void setWaveToSaw();
|
||||
void setWaveToSquare();
|
||||
void setWaveToNoise();
|
||||
QString setWaveToUser( );
|
||||
QString setWaveToUser();
|
||||
|
||||
void smooth();
|
||||
void smoothNonCyclic();
|
||||
@@ -211,8 +219,11 @@ private:
|
||||
float m_maxValue;
|
||||
float m_step;
|
||||
|
||||
friend class Graph;
|
||||
friend class gui::Graph;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#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>
|
||||
|
||||
@@ -34,13 +33,15 @@
|
||||
|
||||
class QPixmap;
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class GroupBox : public QWidget, public BoolModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GroupBox( const QString & _caption, QWidget * _parent = NULL );
|
||||
virtual ~GroupBox();
|
||||
GroupBox( const QString & _caption, QWidget * _parent = nullptr );
|
||||
~GroupBox() override;
|
||||
|
||||
void modelChanged() override;
|
||||
|
||||
@@ -49,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;
|
||||
@@ -70,6 +86,6 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
|
||||
#endif
|
||||
#endif // LMMS_GUI_GROUP_BOX_H
|
||||
|
||||
@@ -22,21 +22,25 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GUIAPPLICATION_H
|
||||
#define GUIAPPLICATION_H
|
||||
#ifndef LMMS_GUI_GUI_APPLICATION_H
|
||||
#define LMMS_GUI_GUI_APPLICATION_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QObject>
|
||||
|
||||
#include "lmms_export.h"
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
class QLabel;
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class AutomationEditorWindow;
|
||||
class BBEditor;
|
||||
class ControllerRackView;
|
||||
class FxMixerView;
|
||||
class MixerView;
|
||||
class MainWindow;
|
||||
class MicrotunerConfig;
|
||||
class PatternEditorWindow;
|
||||
class PianoRollWindow;
|
||||
class ProjectNotes;
|
||||
class SongEditorWindow;
|
||||
@@ -46,7 +50,7 @@ class LMMS_EXPORT GuiApplication : public QObject
|
||||
Q_OBJECT;
|
||||
public:
|
||||
explicit GuiApplication();
|
||||
~GuiApplication();
|
||||
~GuiApplication() override;
|
||||
|
||||
static GuiApplication* instance();
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
@@ -54,11 +58,12 @@ public:
|
||||
#endif
|
||||
|
||||
MainWindow* mainWindow() { return m_mainWindow; }
|
||||
FxMixerView* fxMixerView() { return m_fxMixerView; }
|
||||
MixerView* mixerView() { return m_mixerView; }
|
||||
SongEditorWindow* songEditor() { return m_songEditor; }
|
||||
BBEditor* getBBEditor() { return m_bbEditor; }
|
||||
PatternEditorWindow* patternEditor() { return m_patternEditor; }
|
||||
PianoRollWindow* pianoRoll() { return m_pianoRoll; }
|
||||
ProjectNotes* getProjectNotes() { return m_projectNotes; }
|
||||
MicrotunerConfig* getMicrotunerConfig() { return m_microtunerConfig; }
|
||||
AutomationEditorWindow* automationEditor() { return m_automationEditor; }
|
||||
ControllerRackView* getControllerRackView() { return m_controllerRackView; }
|
||||
|
||||
@@ -72,16 +77,20 @@ private:
|
||||
static GuiApplication* s_instance;
|
||||
|
||||
MainWindow* m_mainWindow;
|
||||
FxMixerView* m_fxMixerView;
|
||||
MixerView* m_mixerView;
|
||||
SongEditorWindow* m_songEditor;
|
||||
AutomationEditorWindow* m_automationEditor;
|
||||
BBEditor* m_bbEditor;
|
||||
PatternEditorWindow* m_patternEditor;
|
||||
PianoRollWindow* m_pianoRoll;
|
||||
ProjectNotes* m_projectNotes;
|
||||
MicrotunerConfig* m_microtunerConfig;
|
||||
ControllerRackView* m_controllerRackView;
|
||||
QLabel* m_loadingProgressLabel;
|
||||
};
|
||||
|
||||
#define gui GuiApplication::instance()
|
||||
// Short-hand function
|
||||
LMMS_EXPORT GuiApplication* getGUI();
|
||||
|
||||
#endif // GUIAPPLICATION_H
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_GUI_APPLICATION_H
|
||||
|
||||
@@ -23,13 +23,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IMPORT_FILTER_H
|
||||
#define IMPORT_FILTER_H
|
||||
#ifndef LMMS_IMPORT_FILTER_H
|
||||
#define LMMS_IMPORT_FILTER_H
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QFile>
|
||||
|
||||
#include "Plugin.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
|
||||
class TrackContainer;
|
||||
|
||||
@@ -39,7 +42,7 @@ class LMMS_EXPORT ImportFilter : public Plugin
|
||||
public:
|
||||
ImportFilter( const QString & _file_name,
|
||||
const Descriptor * _descriptor );
|
||||
virtual ~ImportFilter();
|
||||
~ImportFilter() override = default;
|
||||
|
||||
|
||||
// tries to import given file to given track-container by having all
|
||||
@@ -109,4 +112,6 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_IMPORT_FILTER_H
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user