Merge branch 'master' into groove

This commit is contained in:
Hyunjin Song
2024-04-16 09:55:07 +09:00
915 changed files with 25961 additions and 17944 deletions

View File

@@ -22,9 +22,8 @@
*
*/
#ifndef ABOUT_DIALOG_H
#define ABOUT_DIALOG_H
#ifndef LMMS_GUI_ABOUT_DIALOG_H
#define LMMS_GUI_ABOUT_DIALOG_H
#include <QDialog>
@@ -42,5 +41,4 @@ public:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_ABOUT_DIALOG_H

View File

@@ -22,9 +22,8 @@
*
*/
#ifndef ACTION_GROUP_H
#define ACTION_GROUP_H
#ifndef LMMS_GUI_ACTION_GROUP_H
#define LMMS_GUI_ACTION_GROUP_H
#include <QActionGroup>
@@ -59,4 +58,4 @@ private:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_ACTION_GROUP_H

388
include/ArrayVector.h Normal file
View 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

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_ALSA_H
#define AUDIO_ALSA_H
#ifndef LMMS_AUDIO_ALSA_H
#define LMMS_AUDIO_ALSA_H
#include "lmmsconfig.h"
@@ -108,4 +108,4 @@ private:
#endif // LMMS_HAVE_ALSA
#endif
#endif // LMMS_AUDIO_ALSA_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_ALSA_SETUP_WIDGET_H
#define AUDIO_ALSA_SETUP_WIDGET_H
#ifndef LMMS_GUI_AUDIO_ALSA_SETUP_WIDGET_H
#define LMMS_GUI_AUDIO_ALSA_SETUP_WIDGET_H
#include "lmmsconfig.h"
@@ -66,4 +66,4 @@ private:
#endif // LMMS_HAVE_ALSA
#endif
#endif // LMMS_GUI_AUDIO_ALSA_SETUP_WIDGET_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_DEVICE_H
#define AUDIO_DEVICE_H
#ifndef LMMS_AUDIO_DEVICE_H
#define LMMS_AUDIO_DEVICE_H
#include <QMutex>
#include <samplerate.h>
@@ -96,11 +96,7 @@ public:
protected:
// subclasses can re-implement this for being used in conjunction with
// processNextBuffer()
virtual void writeBuffer( const surroundSampleFrame * /* _buf*/,
const fpp_t /*_frames*/,
const float /*_master_gain*/ )
{
}
virtual void writeBuffer(const surroundSampleFrame* /* _buf*/, const fpp_t /*_frames*/) {}
// called by according driver for fetching new sound-data
fpp_t getNextBuffer( surroundSampleFrame * _ab );
@@ -109,7 +105,6 @@ protected:
// returns num of bytes in outbuf
int convertToS16( const surroundSampleFrame * _ab,
const fpp_t _frames,
const float _master_gain,
int_sample_t * _output_buffer,
const bool _convert_endian = false );
@@ -160,4 +155,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_AUDIO_DEVICE_H

View File

@@ -2,6 +2,7 @@
* AudioDeviceSetupWidget.h - Base class for audio device setup widgets
*
* Copyright (c) 2004-2015 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2023- Michael Gregorius
*
* This file is part of LMMS - https://lmms.io
*
@@ -22,15 +23,15 @@
*
*/
#ifndef AUDIO_DEVICE_SETUP_WIDGET_H
#define AUDIO_DEVICE_SETUP_WIDGET_H
#ifndef LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H
#define LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H
#include "TabWidget.h"
#include <QGroupBox>
namespace lmms::gui
{
class AudioDeviceSetupWidget : public TabWidget
class AudioDeviceSetupWidget : public QGroupBox
{
Q_OBJECT
public:
@@ -45,4 +46,4 @@ public:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_DUMMY_H
#define AUDIO_DUMMY_H
#ifndef LMMS_AUDIO_DUMMY_H
#define LMMS_AUDIO_DUMMY_H
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
@@ -116,4 +116,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_AUDIO_DUMMY_H

View File

@@ -22,20 +22,19 @@
*
*/
#ifndef AUDIO_ENGINE_H
#define AUDIO_ENGINE_H
#ifndef LMMS_AUDIO_ENGINE_H
#define LMMS_AUDIO_ENGINE_H
#include <QMutex>
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
#include <QRecursiveMutex>
#ifdef __MINGW32__
#include <mingw.mutex.h>
#else
#include <mutex>
#endif
#include <QThread>
#include <QVector>
#include <QWaitCondition>
#include <samplerate.h>
#include <vector>
#include "lmms_basics.h"
#include "LocklessList.h"
@@ -109,27 +108,27 @@ public:
struct qualitySettings
{
enum Mode
enum class Mode
{
Mode_Draft,
Mode_HighQuality,
Mode_FinalMix
Draft,
HighQuality,
FinalMix
} ;
enum Interpolation
enum class Interpolation
{
Interpolation_Linear,
Interpolation_SincFastest,
Interpolation_SincMedium,
Interpolation_SincBest
Linear,
SincFastest,
SincMedium,
SincBest
} ;
enum Oversampling
enum class Oversampling
{
Oversampling_None,
Oversampling_2x,
Oversampling_4x,
Oversampling_8x
None,
X2,
X4,
X8
} ;
Interpolation interpolation;
@@ -139,18 +138,18 @@ public:
{
switch (m)
{
case Mode_Draft:
interpolation = Interpolation_Linear;
oversampling = Oversampling_None;
case Mode::Draft:
interpolation = Interpolation::Linear;
oversampling = Oversampling::None;
break;
case Mode_HighQuality:
case Mode::HighQuality:
interpolation =
Interpolation_SincFastest;
oversampling = Oversampling_2x;
Interpolation::SincFastest;
oversampling = Oversampling::X2;
break;
case Mode_FinalMix:
interpolation = Interpolation_SincBest;
oversampling = Oversampling_8x;
case Mode::FinalMix:
interpolation = Interpolation::SincBest;
oversampling = Oversampling::X8;
break;
}
}
@@ -165,10 +164,10 @@ public:
{
switch( oversampling )
{
case Oversampling_None: return 1;
case Oversampling_2x: return 2;
case Oversampling_4x: return 4;
case Oversampling_8x: return 8;
case Oversampling::None: return 1;
case Oversampling::X2: return 2;
case Oversampling::X4: return 4;
case Oversampling::X8: return 8;
}
return 1;
}
@@ -177,13 +176,13 @@ public:
{
switch( interpolation )
{
case Interpolation_Linear:
case Interpolation::Linear:
return SRC_ZERO_ORDER_HOLD;
case Interpolation_SincFastest:
case Interpolation::SincFastest:
return SRC_SINC_FASTEST;
case Interpolation_SincMedium:
case Interpolation::SincMedium:
return SRC_SINC_MEDIUM_QUALITY;
case Interpolation_SincBest:
case Interpolation::SincBest:
return SRC_SINC_BEST_QUALITY;
}
return SRC_LINEAR;
@@ -197,6 +196,7 @@ public:
// audio-device-stuff
bool renderOnly() const { return m_renderOnly; }
// Returns the current audio device's name. This is not necessarily
// the user's preferred audio device, in case you were thinking that.
inline const QString & audioDevName() const
@@ -255,7 +255,7 @@ public:
return m_playHandles;
}
void removePlayHandlesOfTypes(Track * track, const quint8 types);
void removePlayHandlesOfTypes(Track * track, PlayHandle::Types types);
// methods providing information for other classes
@@ -275,6 +275,11 @@ public:
return m_profiler.cpuLoad();
}
int detailLoad(const AudioEngineProfiler::DetailType type) const
{
return m_profiler.detailLoad(type);
}
const qualitySettings & currentQualitySettings() const
{
return m_qualitySettings;
@@ -401,6 +406,10 @@ private:
AudioDevice * tryAudioDevices();
MidiClient * tryMidiClients();
void renderStageNoteSetup();
void renderStageInstruments();
void renderStageEffects();
void renderStageMix();
const surroundSampleFrame * renderNextBuffer();
@@ -410,13 +419,9 @@ private:
void clearInternal();
//! Called by the audio thread to give control to other threads,
//! such that they can do changes in the model (like e.g. removing effects)
void runChangesInModel();
bool m_renderOnly;
QVector<AudioPort *> m_audioPorts;
std::vector<AudioPort *> m_audioPorts;
fpp_t m_framesPerPeriod;
@@ -430,7 +435,7 @@ private:
surroundSampleFrame * m_outputBufferWrite;
// worker thread stuff
QVector<AudioEngineWorkerThread *> m_workers;
std::vector<AudioEngineWorkerThread *> m_workers;
int m_numWorkers;
// playhandle stuff
@@ -443,8 +448,6 @@ private:
struct qualitySettings m_qualitySettings;
float m_masterGain;
bool m_isProcessing;
// audio device stuff
void doSetAudioDevice( AudioDevice *_dev );
AudioDevice * m_audioDev;
@@ -466,19 +469,7 @@ private:
bool m_clearSignal;
bool m_changesSignal;
unsigned int m_changes;
QMutex m_changesMutex;
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
QRecursiveMutex m_doChangesMutex;
#else
QMutex m_doChangesMutex;
#endif
QMutex m_waitChangesMutex;
QWaitCondition m_changesAudioEngineCondition;
QWaitCondition m_changesRequestCondition;
bool m_waitingForWrite;
std::mutex m_changeMutex;
friend class Engine;
friend class AudioEngineWorkerThread;
@@ -487,4 +478,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_AUDIO_ENGINE_H

View File

@@ -22,9 +22,11 @@
*
*/
#ifndef AUDIO_ENGINE_PROFILER_H
#define AUDIO_ENGINE_PROFILER_H
#ifndef LMMS_AUDIO_ENGINE_PROFILER_H
#define LMMS_AUDIO_ENGINE_PROFILER_H
#include <array>
#include <atomic>
#include <QFile>
#include "lmms_basics.h"
@@ -53,13 +55,57 @@ public:
void setOutputFile( const QString& outputFile );
enum class DetailType {
NoteSetup,
Instruments,
Effects,
Mixing,
Count
};
constexpr static auto DetailCount = static_cast<std::size_t>(DetailType::Count);
int detailLoad(const DetailType type) const
{
return m_detailLoad[static_cast<std::size_t>(type)].load(std::memory_order_relaxed);
}
class Probe
{
public:
Probe(AudioEngineProfiler& profiler, AudioEngineProfiler::DetailType type)
: m_profiler(profiler)
, m_type(type)
{
profiler.startDetail(type);
}
~Probe() { m_profiler.finishDetail(m_type); }
Probe& operator=(const Probe&) = delete;
Probe(const Probe&) = delete;
Probe(Probe&&) = delete;
private:
AudioEngineProfiler &m_profiler;
const AudioEngineProfiler::DetailType m_type;
};
private:
void startDetail(const DetailType type) { m_detailTimer[static_cast<std::size_t>(type)].reset(); }
void finishDetail(const DetailType type)
{
m_detailTime[static_cast<std::size_t>(type)] = m_detailTimer[static_cast<std::size_t>(type)].elapsed();
}
MicroTimer m_periodTimer;
int m_cpuLoad;
std::atomic<float> m_cpuLoad;
QFile m_outputFile;
// Use arrays to avoid dynamic allocations in realtime code
std::array<MicroTimer, DetailCount> m_detailTimer;
std::array<int, DetailCount> m_detailTime{0};
std::array<std::atomic<float>, DetailCount> m_detailLoad{0};
};
} // namespace lmms
#endif
#endif // LMMS_AUDIO_ENGINE_PROFILER_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_ENGINE_WORKER_THREAD_H
#define AUDIO_ENGINE_WORKER_THREAD_H
#ifndef LMMS_AUDIO_ENGINE_WORKER_THREAD_H
#define LMMS_AUDIO_ENGINE_WORKER_THREAD_H
#include <QThread>
@@ -45,7 +45,7 @@ public:
class JobQueue
{
public:
enum OperationMode
enum class OperationMode
{
Static, // no jobs added while processing queue
Dynamic // jobs can be added while processing queue
@@ -57,7 +57,7 @@ public:
m_items(),
m_writeIndex( 0 ),
m_itemsDone( 0 ),
m_opMode( Static )
m_opMode( OperationMode::Static )
{
std::fill(m_items, m_items + JOB_QUEUE_SIZE, nullptr);
}
@@ -83,7 +83,7 @@ public:
virtual void quit();
static void resetJobQueue( JobQueue::OperationMode _opMode =
JobQueue::Static )
JobQueue::OperationMode::Static )
{
globalJobQueue.reset( _opMode );
}
@@ -97,12 +97,12 @@ public:
// to ThreadableJob objects
template<typename T>
static void fillJobQueue( const T & _vec,
JobQueue::OperationMode _opMode = JobQueue::Static )
JobQueue::OperationMode _opMode = JobQueue::OperationMode::Static )
{
resetJobQueue( _opMode );
for( typename T::ConstIterator it = _vec.begin(); it != _vec.end(); ++it )
for (const auto& job : _vec)
{
addJob( *it );
addJob(job);
}
}
@@ -121,4 +121,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_AUDIO_ENGINE_WORKER_THREAD_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef AUDIO_FILE_DEVICE_H
#define AUDIO_FILE_DEVICE_H
#ifndef LMMS_AUDIO_FILE_DEVICE_H
#define LMMS_AUDIO_FILE_DEVICE_H
#include <QFile>
@@ -73,4 +73,4 @@ using AudioFileDeviceInstantiaton
} // namespace lmms
#endif
#endif // LMMS_AUDIO_FILE_DEVICE_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_FILE_FLAC_H
#define AUDIO_FILE_FLAC_H
#ifndef LMMS_AUDIO_FILE_FLAC_H
#define LMMS_AUDIO_FILE_FLAC_H
#include "lmmsconfig.h"
@@ -33,7 +33,7 @@
namespace lmms
{
class AudioFileFlac: public AudioFileDevice
class AudioFileFlac : public AudioFileDevice
{
public:
AudioFileFlac(OutputSettings const& outputSettings,
@@ -65,9 +65,7 @@ private:
SF_INFO m_sfinfo;
SNDFILE* m_sf;
void writeBuffer(surroundSampleFrame const* _ab,
fpp_t const frames,
float master_gain) override;
void writeBuffer(surroundSampleFrame const* _ab, fpp_t const frames) override;
bool startEncoding();
void finishEncoding();
@@ -77,4 +75,4 @@ private:
} // namespace lmms
#endif //AUDIO_FILE_FLAC_H
#endif // LMMS_AUDIO_FILE_FLAC_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef AUDIO_FILE_MP3_H
#define AUDIO_FILE_MP3_H
#ifndef LMMS_AUDIO_FILE_MP3_H
#define LMMS_AUDIO_FILE_MP3_H
#include "lmmsconfig.h"
@@ -58,9 +58,7 @@ public:
}
protected:
void writeBuffer( const surroundSampleFrame * /* _buf*/,
const fpp_t /*_frames*/,
const float /*_master_gain*/ ) override;
void writeBuffer(const surroundSampleFrame* /* _buf*/, const fpp_t /*_frames*/) override;
private:
void flushRemainingBuffers();
@@ -75,4 +73,4 @@ private:
#endif // LMMS_HAVE_MP3LAME
#endif
#endif // LMMS_AUDIO_FILE_MP3_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef AUDIO_FILE_OGG_H
#define AUDIO_FILE_OGG_H
#ifndef LMMS_AUDIO_FILE_OGG_H
#define LMMS_AUDIO_FILE_OGG_H
#include "lmmsconfig.h"
@@ -58,9 +58,7 @@ public:
private:
void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
const float _master_gain ) override;
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
bool startEncoding();
void finishEncoding();
@@ -113,4 +111,4 @@ private:
#endif // LMMS_HAVE_OGGVORBIS
#endif
#endif // LMMS_AUDIO_FILE_OGG_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef AUDIO_FILE_WAVE_H
#define AUDIO_FILE_WAVE_H
#ifndef LMMS_AUDIO_FILE_WAVE_H
#define LMMS_AUDIO_FILE_WAVE_H
#include "lmmsconfig.h"
#include "AudioFileDevice.h"
@@ -56,9 +56,7 @@ public:
private:
void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
float _master_gain ) override;
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
bool startEncoding();
void finishEncoding();
@@ -71,4 +69,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_AUDIO_FILE_WAVE_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_JACK_H
#define AUDIO_JACK_H
#ifndef LMMS_AUDIO_JACK_H
#define LMMS_AUDIO_JACK_H
#include "lmmsconfig.h"
@@ -35,7 +35,7 @@
#endif
#include <atomic>
#include <QVector>
#include <vector>
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
@@ -57,42 +57,37 @@ class AudioJack : public QObject, public AudioDevice
{
Q_OBJECT
public:
AudioJack( bool & _success_ful, AudioEngine* audioEngine );
AudioJack(bool& successful, AudioEngine* audioEngine);
~AudioJack() override;
// this is to allow the jack midi connection to use the same jack client connection
// the jack callback is handled here, we call the midi client so that it can read
// it's midi data during the callback
AudioJack * addMidiClient(MidiJack *midiClient);
AudioJack* addMidiClient(MidiJack* midiClient);
void removeMidiClient() { m_midiClient = nullptr; }
jack_client_t * jackClient() {return m_client;};
jack_client_t* jackClient() { return m_client; };
inline static QString name()
{
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget",
"JACK (JACK Audio Connection Kit)" );
return QT_TRANSLATE_NOOP("AudioDeviceSetupWidget", "JACK (JACK Audio Connection Kit)");
}
class setupWidget : public gui::AudioDeviceSetupWidget
class setupWidget : public gui::AudioDeviceSetupWidget
{
public:
setupWidget( QWidget * _parent );
setupWidget(QWidget* parent);
~setupWidget() override;
void saveSettings() override;
private:
QLineEdit * m_clientName;
gui::LcdSpinBox * m_channels;
} ;
QLineEdit* m_clientName;
gui::LcdSpinBox* m_channels;
};
private slots:
void restartAfterZombified();
private:
bool initJackClient();
@@ -100,48 +95,44 @@ private:
void stopProcessing() override;
void applyQualitySettings() override;
void registerPort( AudioPort * _port ) override;
void unregisterPort( AudioPort * _port ) override;
void renamePort( AudioPort * _port ) override;
void registerPort(AudioPort* port) override;
void unregisterPort(AudioPort* port) override;
void renamePort(AudioPort* port) override;
int processCallback( jack_nframes_t _nframes, void * _udata );
int processCallback(jack_nframes_t nframes);
static int staticProcessCallback( jack_nframes_t _nframes,
void * _udata );
static void shutdownCallback( void * _udata );
static int staticProcessCallback(jack_nframes_t nframes, void* udata);
static void shutdownCallback(void* _udata);
jack_client_t * m_client;
jack_client_t* m_client;
bool m_active;
std::atomic<bool> m_stopped;
std::atomic<MidiJack *> m_midiClient;
QVector<jack_port_t *> m_outputPorts;
jack_default_audio_sample_t * * m_tempOutBufs;
surroundSampleFrame * m_outBuf;
std::atomic<MidiJack*> m_midiClient;
std::vector<jack_port_t*> m_outputPorts;
jack_default_audio_sample_t** m_tempOutBufs;
surroundSampleFrame* m_outBuf;
f_cnt_t m_framesDoneInCurBuf;
f_cnt_t m_framesToDoInCurBuf;
#ifdef AUDIO_PORT_SUPPORT
struct StereoPort
{
jack_port_t * ports[2];
} ;
jack_port_t* ports[2];
};
using JackPortMap = QMap<AudioPort *, StereoPort>;
using JackPortMap = QMap<AudioPort*, StereoPort>;
JackPortMap m_portMap;
#endif
signals:
void zombified();
} ;
};
} // namespace lmms
#endif // LMMS_HAVE_JACK
#endif
#endif // LMMS_AUDIO_JACK_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_OSS_H
#define AUDIO_OSS_H
#ifndef LMMS_AUDIO_OSS_H
#define LMMS_AUDIO_OSS_H
#include "lmmsconfig.h"
@@ -92,4 +92,4 @@ private:
#endif // LMMS_HAVE_OSS
#endif
#endif // LMMS_AUDIO_OSS_H

View File

@@ -22,14 +22,13 @@
*
*/
#ifndef AUDIO_PORT_H
#define AUDIO_PORT_H
#ifndef LMMS_AUDIO_PORT_H
#define LMMS_AUDIO_PORT_H
#include <memory>
#include <QString>
#include <QMutex>
#include "MemoryManager.h"
#include "PlayHandle.h"
namespace lmms
@@ -41,7 +40,6 @@ class BoolModel;
class AudioPort : public ThreadableJob
{
MM_OPERATORS
public:
AudioPort( const QString & _name, bool _has_effect_chain = true,
FloatModel * volumeModel = nullptr, FloatModel * panningModel = nullptr,
@@ -138,4 +136,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_AUDIO_PORT_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_PORTAUDIO_H
#define AUDIO_PORTAUDIO_H
#ifndef LMMS_AUDIO_PORTAUDIO_H
#define LMMS_AUDIO_PORTAUDIO_H
#include <QObject>
@@ -163,4 +163,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_AUDIO_PORTAUDIO_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_PULSEAUDIO_H
#define AUDIO_PULSEAUDIO_H
#ifndef LMMS_AUDIO_PULSEAUDIO_H
#define LMMS_AUDIO_PULSEAUDIO_H
#include "lmmsconfig.h"
@@ -104,4 +104,4 @@ private:
#endif // LMMS_HAVE_PULSEAUDIO
#endif
#endif // LMMS_AUDIO_PULSEAUDIO_H

64
include/AudioResampler.h Normal file
View File

@@ -0,0 +1,64 @@
/*
* AudioResampler.h - wrapper around libsamplerate
*
* Copyright (c) 2023 saker <sakertooth@gmail.com>
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef LMMS_AUDIO_RESAMPLER_H
#define LMMS_AUDIO_RESAMPLER_H
#include <samplerate.h>
#include "lmms_export.h"
namespace lmms {
class LMMS_EXPORT AudioResampler
{
public:
struct ProcessResult
{
int error;
long inputFramesUsed;
long outputFramesGenerated;
};
AudioResampler(int interpolationMode, int channels);
AudioResampler(const AudioResampler&) = delete;
AudioResampler(AudioResampler&&) = delete;
~AudioResampler();
AudioResampler& operator=(const AudioResampler&) = delete;
AudioResampler& operator=(AudioResampler&&) = delete;
auto resample(const float* in, long inputFrames, float* out, long outputFrames, double ratio) -> ProcessResult;
auto interpolationMode() const -> int { return m_interpolationMode; }
auto channels() const -> int { return m_channels; }
private:
int m_interpolationMode = -1;
int m_channels = 0;
int m_error = 0;
SRC_STATE* m_state = nullptr;
};
} // namespace lmms
#endif // LMMS_AUDIO_RESAMPLER_H

View File

@@ -23,11 +23,12 @@
*
*/
#ifndef AUDIO_SAMPLE_RECORDER_H
#define AUDIO_SAMPLE_RECORDER_H
#ifndef LMMS_AUDIO_SAMPLE_RECORDER_H
#define LMMS_AUDIO_SAMPLE_RECORDER_H
#include <QList>
#include <QPair>
#include <memory>
#include "AudioDevice.h"
@@ -44,13 +45,10 @@ public:
~AudioSampleRecorder() override;
f_cnt_t framesRecorded() const;
void createSampleBuffer( SampleBuffer** sampleBuffer );
std::shared_ptr<const SampleBuffer> createSampleBuffer();
private:
void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
const float _master_gain ) override;
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
using BufferList = QList<QPair<sampleFrame*, fpp_t>>;
BufferList m_buffers;
@@ -59,4 +57,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_AUDIO_SAMPLE_RECORDER_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_SDL_H
#define AUDIO_SDL_H
#ifndef LMMS_AUDIO_SDL_H
#define LMMS_AUDIO_SDL_H
#include "lmmsconfig.h"
@@ -115,4 +115,4 @@ private:
#endif // LMMS_HAVE_SDL
#endif
#endif // LMMS_AUDIO_SDL_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef _AUDIO_SNDIO_H
#define _AUDIO_SNDIO_H
#ifndef LMMS_AUDIO_SNDIO_H
#define LMMS_AUDIO_SNDIO_H
#include "lmmsconfig.h"
@@ -87,6 +87,6 @@ private:
} // namespace lmms
#endif // LMMS_HAVE_SNDIO
#endif // LMMS_HAVE_SNDIO
#endif // _AUDIO_SNDIO_H
#endif // LMMS_AUDIO_SNDIO_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUDIO_SOUNDIO_H
#define AUDIO_SOUNDIO_H
#ifndef LMMS_AUDIO_SOUNDIO_H
#define LMMS_AUDIO_SOUNDIO_H
#include <QObject>
@@ -145,4 +145,4 @@ private:
#endif // LMMS_HAVE_SOUNDIO
#endif
#endif // LMMS_AUDIO_SOUNDIO_H

View File

@@ -22,9 +22,8 @@
*
*/
#ifndef AUTOMATABLE_BUTTON_H
#define AUTOMATABLE_BUTTON_H
#ifndef LMMS_GUI_AUTOMATABLE_BUTTON_H
#define LMMS_GUI_AUTOMATABLE_BUTTON_H
#include <QPushButton>
@@ -109,4 +108,4 @@ private:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_AUTOMATABLE_BUTTON_H

View File

@@ -22,17 +22,18 @@
*
*/
#ifndef AUTOMATABLE_MODEL_H
#define AUTOMATABLE_MODEL_H
#ifndef LMMS_AUTOMATABLE_MODEL_H
#define LMMS_AUTOMATABLE_MODEL_H
#include <cmath>
#include <QMap>
#include <QMutex>
#include <QRegularExpression>
#include "JournallingObject.h"
#include "Model.h"
#include "TimePos.h"
#include "ValueBuffer.h"
#include "MemoryManager.h"
#include "ModelVisitor.h"
@@ -76,11 +77,10 @@ class ControllerConnection;
class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
{
Q_OBJECT
MM_OPERATORS
public:
using AutoModelVector = QVector<AutomatableModel*>;
using AutoModelVector = std::vector<AutomatableModel*>;
enum ScaleType
enum class ScaleType
{
Linear,
Logarithmic,
@@ -144,7 +144,7 @@ public:
template<bool>
static bool castValue( const float v )
{
return ( qRound( v ) != 0 );
return (std::round(v) != 0);
}
@@ -231,11 +231,11 @@ public:
}
void setScaleLogarithmic( bool setToTrue = true )
{
setScaleType( setToTrue ? Logarithmic : Linear );
setScaleType( setToTrue ? ScaleType::Logarithmic : ScaleType::Linear );
}
bool isScaleLogarithmic() const
{
return m_scaleType == Logarithmic;
return m_scaleType == ScaleType::Logarithmic;
}
void setStep( const float step );
@@ -507,5 +507,4 @@ using AutomatedValueMap = QMap<AutomatableModel*, float>;
} // namespace lmms
#endif
#endif // LMMS_AUTOMATABLE_MODEL_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef AUTOMATABLE_MODEL_VIEW_H
#define AUTOMATABLE_MODEL_VIEW_H
#ifndef LMMS_GUI_AUTOMATABLE_MODEL_VIEW_H
#define LMMS_GUI_AUTOMATABLE_MODEL_VIEW_H
#include "ModelView.h"
#include "AutomatableModel.h"
@@ -137,5 +137,4 @@ using BoolModelView = TypedModelView<BoolModel>;
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_AUTOMATABLE_MODEL_VIEW_H

View File

@@ -22,9 +22,8 @@
*
*/
#ifndef AUTOMATABLE_SLIDER_H
#define AUTOMATABLE_SLIDER_H
#ifndef LMMS_GUI_AUTOMATABLE_SLIDER_H
#define LMMS_GUI_AUTOMATABLE_SLIDER_H
#include <QSlider>
@@ -77,4 +76,4 @@ using sliderModel = IntModel;
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_AUTOMATABLE_SLIDER_H

View File

@@ -24,8 +24,8 @@
*
*/
#ifndef AUTOMATION_CLIP_H
#define AUTOMATION_CLIP_H
#ifndef LMMS_AUTOMATION_CLIP_H
#define LMMS_AUTOMATION_CLIP_H
#include <QMap>
#include <QPointer>
@@ -46,6 +46,7 @@ class TimePos;
namespace gui
{
class AutomationClipView;
class AutomationEditor;
} // namespace gui
@@ -54,15 +55,15 @@ class LMMS_EXPORT AutomationClip : public Clip
{
Q_OBJECT
public:
enum ProgressionTypes
enum class ProgressionType
{
DiscreteProgression,
LinearProgression,
CubicHermiteProgression
Discrete,
Linear,
CubicHermite
} ;
using timeMap = QMap<int, AutomationNode>;
using objectVector = QVector<QPointer<AutomatableModel>>;
using objectVector = std::vector<QPointer<AutomatableModel>>;
using TimemapIterator = timeMap::const_iterator;
@@ -76,11 +77,11 @@ public:
const objectVector& objects() const;
// progression-type stuff
inline ProgressionTypes progressionType() const
inline ProgressionType progressionType() const
{
return m_progressionType;
}
void setProgressionType( ProgressionTypes _new_progression_type );
void setProgressionType( ProgressionType _new_progression_type );
inline float getTension() const
{
@@ -111,6 +112,13 @@ public:
void resetNodes(const int tick0, const int tick1);
/**
* @brief Resets the tangents from the nodes between the given ticks
* @param Int first tick of the range
* @param Int second tick of the range
*/
void resetTangents(const int tick0, const int tick1);
void recordValue(TimePos time, float value);
TimePos setDragValue( const TimePos & time,
@@ -151,10 +159,21 @@ public:
return m_timeMap.isEmpty() == false;
}
static bool supportsTangentEditing(ProgressionType pType)
{
// Update function if we have new progression types that support tangent editing
return pType == ProgressionType::CubicHermite;
}
inline bool canEditTangents() const
{
return supportsTangentEditing(m_progressionType);
}
float valueAt( const TimePos & _time ) const;
float *valuesAfter( const TimePos & _time ) const;
const QString name() const;
QString name() const;
// settings-management
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
@@ -167,7 +186,7 @@ public:
static bool isAutomated( const AutomatableModel * _m );
static QVector<AutomationClip *> clipsForModel( const AutomatableModel * _m );
static std::vector<AutomationClip*> clipsForModel(const AutomatableModel* _m);
static AutomationClip * globalAutomationClip( AutomatableModel * _m );
static void resolveAllIDs();
@@ -190,6 +209,15 @@ private:
void generateTangents(timeMap::iterator it, int numToGenerate);
float valueAt( timeMap::const_iterator v, int offset ) const;
/**
* @brief
* This function combines the song tracks, pattern store tracks,
* and the global automation track all in one vector.
*
* @return std::vector<Track*>
*/
static std::vector<Track*> combineAllTracks();
// Mutex to make methods involving automation clips thread safe
// Mutable so we can lock it from const objects
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
@@ -199,17 +227,20 @@ private:
#endif
AutomationTrack * m_autoTrack;
QVector<jo_id_t> m_idsToResolve;
std::vector<jo_id_t> m_idsToResolve;
objectVector m_objects;
timeMap m_timeMap; // actual values
timeMap m_oldTimeMap; // old values for storing the values before setDragValue() is called.
float m_tension;
bool m_hasAutomation;
ProgressionTypes m_progressionType;
ProgressionType m_progressionType;
bool m_dragging;
bool m_dragKeepOutValue; // Should we keep the current dragged node's outValue?
float m_dragOutValue; // The outValue of the dragged node's
bool m_dragLockedTan; // If the dragged node has it's tangents locked
float m_dragInTan; // The dragged node's inTangent
float m_dragOutTan; // The dragged node's outTangent
bool m_isRecording;
float m_lastRecordedValue;
@@ -221,6 +252,7 @@ private:
friend class gui::AutomationClipView;
friend class AutomationNode;
friend class gui::AutomationEditor;
} ;
@@ -252,6 +284,11 @@ inline float OUTTAN(AutomationClip::TimemapIterator it)
return it->getOutTangent();
}
inline float LOCKEDTAN(AutomationClip::TimemapIterator it)
{
return it->lockedTangents();
}
inline int POS(AutomationClip::TimemapIterator it)
{
return it.key();
@@ -260,4 +297,4 @@ inline int POS(AutomationClip::TimemapIterator it)
} // namespace lmms
#endif
#endif // LMMS_AUTOMATION_CLIP_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef AUTOMATION_CLIP_VIEW_H
#define AUTOMATION_CLIP_VIEW_H
#ifndef LMMS_GUI_AUTOMATION_CLIP_VIEW_H
#define LMMS_GUI_AUTOMATION_CLIP_VIEW_H
#include <QStaticText>
@@ -74,9 +74,6 @@ private:
QPixmap m_paintPixmap;
QStaticText m_staticTextName;
static QPixmap * s_clip_rec;
void scaleTimemapToFit( float oldMin, float oldMax );
} ;
@@ -85,4 +82,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_GUI_AUTOMATION_CLIP_VIEW_H

View File

@@ -23,18 +23,21 @@
*
*/
#ifndef AUTOMATION_EDITOR_H
#define AUTOMATION_EDITOR_H
#ifndef LMMS_GUI_AUTOMATION_EDITOR_H
#define LMMS_GUI_AUTOMATION_EDITOR_H
#include <QPushButton>
#include <QWidget>
#include <array>
#include "Editor.h"
#include "lmms_basics.h"
#include "JournallingObject.h"
#include "TimePos.h"
#include "AutomationClip.h"
#include "ComboBoxModel.h"
#include "Editor.h"
#include "JournallingObject.h"
#include "MidiClip.h"
#include "SampleClip.h"
#include "TimePos.h"
#include "lmms_basics.h"
class QPainter;
class QPixmap;
@@ -62,12 +65,18 @@ class AutomationEditor : public QWidget, public JournallingObject
Q_PROPERTY(QColor lineColor MEMBER m_lineColor)
Q_PROPERTY(QColor nodeInValueColor MEMBER m_nodeInValueColor)
Q_PROPERTY(QColor nodeOutValueColor MEMBER m_nodeOutValueColor)
Q_PROPERTY(QColor nodeTangentLineColor MEMBER m_nodeTangentLineColor)
Q_PROPERTY(QBrush scaleColor MEMBER m_scaleColor)
Q_PROPERTY(QBrush graphColor MEMBER m_graphColor)
Q_PROPERTY(QColor crossColor MEMBER m_crossColor)
Q_PROPERTY(QColor backgroundShade MEMBER m_backgroundShade)
Q_PROPERTY(QColor ghostNoteColor MEMBER m_ghostNoteColor)
Q_PROPERTY(QColor detuningNoteColor MEMBER m_detuningNoteColor)
Q_PROPERTY(QColor ghostSampleColor MEMBER m_ghostSampleColor)
public:
void setCurrentClip(AutomationClip * new_clip);
void setGhostMidiClip(MidiClip* newMidiClip);
void setGhostSample(SampleClip* newSample);
inline const AutomationClip * currentClip() const
{
@@ -86,11 +95,12 @@ public:
return "automationeditor";
}
enum EditModes
enum class EditMode
{
DRAW,
ERASE,
DRAW_OUTVALUES
Draw,
Erase,
DrawOutValues,
EditTangents
};
public slots:
@@ -117,6 +127,13 @@ protected:
inline void drawLevelTick(QPainter & p, int tick, float value);
timeMap::iterator getNodeAt(int x, int y, bool outValue = false, int r = 5);
/**
* @brief Given a mouse X coordinate, returns a timeMap::iterator that points to
* the closest node.
* @param Int X coordinate
* @return timeMap::iterator with the closest node or timeMap.end() if there are no nodes.
*/
timeMap::iterator getClosestNode(int x);
void drawLine( int x0, float y0, int x1, float y1 );
bool fineTuneValue(timeMap::iterator node, bool editingOutValue);
@@ -128,10 +145,16 @@ protected slots:
void horScrolled( int new_pos );
void verScrolled( int new_pos );
void setEditMode(AutomationEditor::EditModes mode);
void setEditMode(AutomationEditor::EditMode mode);
void setEditMode(int mode);
void setProgressionType(AutomationClip::ProgressionTypes type);
void setProgressionType(AutomationClip::ProgressionType type);
/**
* @brief This method handles the AutomationEditorWindow event of changing
* progression types. After that, it calls updateEditTanButton so the edit
* tangents button is updated accordingly
* @param Int New progression type
*/
void setProgressionType(int type);
void setTension();
@@ -143,16 +166,25 @@ protected slots:
/// Updates the clip's quantization using the current user selected value.
void setQuantization();
void resetGhostNotes()
{
m_ghostNotes = nullptr;
m_ghostSample = nullptr;
update();
}
private:
enum Actions
enum class Action
{
NONE,
MOVE_VALUE,
ERASE_VALUES,
MOVE_OUTVALUE,
RESET_OUTVALUES,
DRAW_LINE
None,
MoveValue,
EraseValues,
MoveOutValue,
ResetOutValues,
DrawLine,
MoveTangent,
ResetTangents
} ;
// some constants...
@@ -165,22 +197,29 @@ private:
static const int VALUES_WIDTH = 64;
static const int NOTE_HEIGHT = 10; // height of individual notes
static const int NOTE_MARGIN = 40; // total border margin for notes
static const int MIN_NOTE_RANGE = 20; // min number of keys for fixed size
static const int SAMPLE_MARGIN = 40;
static constexpr int MAX_SAMPLE_HEIGHT = 400; // constexpr for use in min
AutomationEditor();
AutomationEditor( const AutomationEditor & );
~AutomationEditor() override;
static QPixmap * s_toolDraw;
static QPixmap * s_toolErase;
static QPixmap * s_toolDrawOut;
static QPixmap * s_toolMove;
static QPixmap * s_toolYFlip;
static QPixmap * s_toolXFlip;
QPixmap m_toolDraw = embed::getIconPixmap("edit_draw");
QPixmap m_toolErase = embed::getIconPixmap("edit_erase");
QPixmap m_toolDrawOut = embed::getIconPixmap("edit_draw_outvalue");
QPixmap m_toolEditTangents = embed::getIconPixmap("edit_tangent");
QPixmap m_toolMove = embed::getIconPixmap("edit_move");
QPixmap m_toolYFlip = embed::getIconPixmap("flip_y");
QPixmap m_toolXFlip = embed::getIconPixmap("flip_x");
ComboBoxModel m_zoomingXModel;
ComboBoxModel m_zoomingYModel;
ComboBoxModel m_quantizeModel;
static const QVector<float> m_zoomXLevels;
static const std::array<float, 7> m_zoomXLevels;
FloatModel * m_tensionModel;
@@ -192,6 +231,10 @@ private:
float m_bottomLevel;
float m_topLevel;
MidiClip* m_ghostNotes = nullptr;
QPointer<SampleClip> m_ghostSample = nullptr; // QPointer to set to nullptr on deletion
bool m_renderSample = false;
void centerTopBottomScroll();
void updateTopBottomLevels();
@@ -200,7 +243,7 @@ private:
TimePos m_currentPosition;
Actions m_action;
Action m_action;
int m_moveXOffset;
@@ -214,7 +257,12 @@ private:
// Time position (key) of automation node whose outValue is being dragged
int m_draggedOutValueKey;
EditModes m_editMode;
// The tick from the node whose tangent is being dragged
int m_draggedTangentTick;
// Whether the tangent being dragged is the InTangent or OutTangent
bool m_draggedOutTangent;
EditMode m_editMode;
bool m_mouseDownLeft;
bool m_mouseDownRight; //true if right click is being held down
@@ -224,6 +272,7 @@ private:
void drawCross(QPainter & p );
void drawAutomationPoint( QPainter & p, timeMap::iterator it );
void drawAutomationTangents(QPainter& p, timeMap::iterator it);
bool inPatternEditor();
QColor m_barLineColor;
@@ -232,9 +281,13 @@ private:
QBrush m_graphColor;
QColor m_nodeInValueColor;
QColor m_nodeOutValueColor;
QColor m_nodeTangentLineColor;
QBrush m_scaleColor;
QColor m_crossColor;
QColor m_backgroundShade;
QColor m_ghostNoteColor;
QColor m_detuningNoteColor;
QColor m_ghostSampleColor;
friend class AutomationEditorWindow;
@@ -258,6 +311,9 @@ public:
~AutomationEditorWindow() override = default;
void setCurrentClip(AutomationClip* clip);
void setGhostMidiClip(MidiClip* clip) { m_editor->setGhostMidiClip(clip); };
void setGhostSample(SampleClip* newSample) { m_editor->setGhostSample(newSample); };
const AutomationClip* currentClip();
void dropEvent( QDropEvent * _de ) override;
@@ -284,8 +340,21 @@ protected slots:
private slots:
void updateWindowTitle();
void setProgressionType(int progType);
/**
* @brief The Edit Tangent edit mode should only be available for
* Cubic Hermite progressions, so this method is responsable for disabling it
* for other edit modes and reenabling it when it changes back to the Edit Tangent
* mode.
*/
void updateEditTanButton();
private:
QAction* m_drawAction;
QAction* m_eraseAction;
QAction* m_drawOutAction;
QAction* m_editTanAction;
QAction* m_discreteAction;
QAction* m_linearAction;
QAction* m_cubicHermiteAction;
@@ -298,10 +367,12 @@ private:
ComboBox * m_zoomingXComboBox;
ComboBox * m_zoomingYComboBox;
ComboBox * m_quantizeComboBox;
QPushButton* m_resetGhostNotes;
};
} // namespace gui
} // namespace lmms
#endif
#endif // LMMS_GUI_AUTOMATION_EDITOR_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef AUTOMATION_NODE_H
#define AUTOMATION_NODE_H
#ifndef LMMS_AUTOMATION_NODE_H
#define LMMS_AUTOMATION_NODE_H
namespace lmms
{
@@ -125,6 +125,22 @@ public:
m_outTangent = tangent;
}
/**
* @brief Checks if the tangents from the node are locked
*/
inline const bool lockedTangents() const
{
return m_lockedTangents;
}
/**
* @brief Locks or Unlocks the tangents from this node
*/
inline void setLockedTangents(bool b)
{
m_lockedTangents = b;
}
/**
* @brief Sets the clip this node belongs to
* @param AutomationClip* clip that m_clip will be
@@ -152,8 +168,13 @@ private:
// outValue are equal, inTangent and outTangent are equal too.
float m_inTangent;
float m_outTangent;
// If the tangents were edited manually, this will be true. That way
// the tangents from this node will not be recalculated. It's set back
// to false if the tangents are reset.
bool m_lockedTangents;
};
} // namespace lmms
#endif
#endif // LMMS_AUTOMATION_NODE_H

View File

@@ -24,8 +24,8 @@
*
*/
#ifndef AUTOMATION_TRACK_H
#define AUTOMATION_TRACK_H
#ifndef LMMS_AUTOMATION_TRACK_H
#define LMMS_AUTOMATION_TRACK_H
#include "Track.h"
@@ -62,4 +62,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_AUTOMATION_TRACK_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef AUTOMATION_TRACK_VIEW_H
#define AUTOMATION_TRACK_VIEW_H
#ifndef LMMS_GUI_AUTOMATION_TRACK_VIEW_H
#define LMMS_GUI_AUTOMATION_TRACK_VIEW_H
#include "TrackView.h"
@@ -52,4 +52,4 @@ public:
} // namespace lmms
#endif
#endif // LMMS_GUI_AUTOMATION_TRACK_VIEW_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef BANDLIMITEDWAVE_H
#define BANDLIMITEDWAVE_H
#ifndef LMMS_BANDLIMITEDWAVE_H
#define LMMS_BANDLIMITEDWAVE_H
class QDataStream;
class QString;
@@ -89,14 +89,15 @@ QDataStream& operator>> ( QDataStream &in, WaveMipMap &waveMipMap );
class LMMS_EXPORT BandLimitedWave
{
public:
enum Waveforms
enum class Waveform
{
BLSaw,
BLSquare,
BLTriangle,
BLMoog,
NumBLWaveforms
Count
};
constexpr static auto NumWaveforms = static_cast<std::size_t>(Waveform::Count);
BandLimitedWave() = default;
virtual ~BandLimitedWave() = default;
@@ -127,7 +128,7 @@ public:
* \param _wavelen The wavelength (length of one cycle, ie. the inverse of frequency) of the wanted oscillation, measured in sample frames
* \param _wave The wanted waveform. Options currently are saw, triangle, square and moog saw.
*/
static inline sample_t oscillate( float _ph, float _wavelen, Waveforms _wave )
static inline sample_t oscillate( float _ph, float _wavelen, Waveform _wave )
{
// get the next higher tlen
int t = 0;
@@ -139,27 +140,28 @@ public:
int lookup = static_cast<int>( lookupf );
const float ip = fraction( lookupf );
const sample_t s1 = s_waveforms[ _wave ].sampleAt( t, lookup );
const sample_t s2 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen );
const sample_t s1 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, lookup );
const sample_t s2 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, ( lookup + 1 ) % tlen );
const int lm = lookup == 0 ? tlen - 1 : lookup - 1;
const sample_t s0 = s_waveforms[ _wave ].sampleAt( t, lm );
const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 2 ) % tlen );
const sample_t s0 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, lm );
const sample_t s3 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, ( lookup + 2 ) % tlen );
const sample_t sr = optimal4pInterpolate( s0, s1, s2, s3, ip );
return sr;
/* lookup = lookup << 1;
/*
lookup = lookup << 1;
tlen = tlen << 1;
t += 1;
const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, lookup );
const sample_t s4 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen );
const sample_t s3 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, lookup );
const sample_t s4 = s_waveforms[ static_cast<std::size_t>(_wave) ].sampleAt( t, ( lookup + 1 ) % tlen );
const sample_t s34 = linearInterpolate( s3, s4, ip );
const float ip2 = ( ( tlen - _wavelen ) / tlen - 0.5 ) * 2.0;
return linearInterpolate( s12, s34, ip2 );
*/
*/
};
@@ -167,11 +169,11 @@ public:
static bool s_wavesGenerated;
static std::array<WaveMipMap, NumBLWaveforms> s_waveforms;
static std::array<WaveMipMap, NumWaveforms> s_waveforms;
static QString s_wavetableDir;
};
} // namespace lmms
#endif
#endif // LMMS_BANDLIMITEDWAVE_H

76
include/BarModelEditor.h Normal file
View 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

View File

@@ -28,9 +28,8 @@
*
*/
#ifndef BASIC_FILTERS_H
#define BASIC_FILTERS_H
#ifndef LMMS_BASIC_FILTERS_H
#define LMMS_BASIC_FILTERS_H
#ifndef __USE_XOPEN
#define __USE_XOPEN
@@ -41,7 +40,6 @@
#include "lmms_basics.h"
#include "lmms_constants.h"
#include "interpolation.h"
#include "MemoryManager.h"
namespace lmms
{
@@ -51,7 +49,6 @@ template<ch_cnt_t CHANNELS=DEFAULT_CHANNELS> class BasicFilters;
template<ch_cnt_t CHANNELS>
class LinkwitzRiley
{
MM_OPERATORS
public:
LinkwitzRiley( float sampleRate )
{
@@ -146,9 +143,13 @@ using StereoLinkwitzRiley = LinkwitzRiley<2>;
template<ch_cnt_t CHANNELS>
class BiQuad
{
MM_OPERATORS
public:
BiQuad()
BiQuad() :
m_a1(0.),
m_a2(0.),
m_b0(0.),
m_b1(0.),
m_b2(0.)
{
clearHistory();
}
@@ -189,7 +190,6 @@ using StereoBiQuad = BiQuad<2>;
template<ch_cnt_t CHANNELS>
class OnePole
{
MM_OPERATORS
public:
OnePole()
{
@@ -210,7 +210,7 @@ public:
inline float update( float s, ch_cnt_t ch )
{
if( qAbs( s ) < 1.0e-10f && qAbs( m_z1[ch] ) < 1.0e-10f ) return 0.0f;
if (std::abs(s) < 1.0e-10f && std::abs(m_z1[ch]) < 1.0e-10f) return 0.0f;
return m_z1[ch] = s * m_a0 + m_z1[ch] * m_b1;
}
@@ -223,9 +223,8 @@ using StereoOnePole = OnePole<2>;
template<ch_cnt_t CHANNELS>
class BasicFilters
{
MM_OPERATORS
public:
enum FilterTypes
enum class FilterType
{
LowPass,
HiPass,
@@ -248,8 +247,7 @@ public:
Highpass_SV,
Notch_SV,
FastFormant,
Tripole,
NumFilters
Tripole
};
static inline float minFreq()
@@ -262,20 +260,20 @@ public:
return( 0.01f );
}
inline void setFilterType( const int _idx )
inline void setFilterType( const FilterType _idx )
{
m_doubleFilter = _idx == DoubleLowPass || _idx == DoubleMoog;
m_doubleFilter = _idx == FilterType::DoubleLowPass || _idx == FilterType::DoubleMoog;
if( !m_doubleFilter )
{
m_type = static_cast<FilterTypes>( _idx );
m_type = _idx;
return;
}
// Double lowpass mode, backwards-compat for the goofy
// Add-NumFilters to signify doubleFilter stuff
m_type = _idx == DoubleLowPass
? LowPass
: Moog;
m_type = _idx == FilterType::DoubleLowPass
? FilterType::LowPass
: FilterType::Moog;
if( m_subFilter == nullptr )
{
m_subFilter = new BasicFilters<CHANNELS>(
@@ -330,33 +328,39 @@ public:
}
}
inline void setSampleRate(const sample_rate_t sampleRate)
{
m_sampleRate = sampleRate;
m_sampleRatio = 1.f / m_sampleRate;
if (m_subFilter != nullptr)
{
m_subFilter->setSampleRate(m_sampleRate);
}
}
inline sample_t update( sample_t _in0, ch_cnt_t _chnl )
{
sample_t out;
sample_t out = 0.0f;
switch( m_type )
{
case Moog:
case FilterType::Moog:
{
sample_t x = _in0 - m_r*m_y4[_chnl];
// four cascaded onepole filters
// (bilinear transform)
m_y1[_chnl] = qBound( -10.0f,
( x + m_oldx[_chnl] ) * m_p
- m_k * m_y1[_chnl],
10.0f );
m_y2[_chnl] = qBound( -10.0f,
( m_y1[_chnl] + m_oldy1[_chnl] ) * m_p
- m_k * m_y2[_chnl],
10.0f );
m_y3[_chnl] = qBound( -10.0f,
( m_y2[_chnl] + m_oldy2[_chnl] ) * m_p
- m_k * m_y3[_chnl],
10.0f );
m_y4[_chnl] = qBound( -10.0f,
( m_y3[_chnl] + m_oldy3[_chnl] ) * m_p
- m_k * m_y4[_chnl],
m_y1[_chnl] = std::clamp((x + m_oldx[_chnl]) * m_p
- m_k * m_y1[_chnl], -10.0f,
10.0f);
m_y2[_chnl] = std::clamp((m_y1[_chnl] + m_oldy1[_chnl]) * m_p
- m_k * m_y2[_chnl], -10.0f,
10.0f);
m_y3[_chnl] = std::clamp((m_y2[_chnl] + m_oldy2[_chnl]) * m_p
- m_k * m_y3[_chnl], -10.0f,
10.0f );
m_y4[_chnl] = std::clamp((m_y3[_chnl] + m_oldy3[_chnl]) * m_p
- m_k * m_y4[_chnl], -10.0f,
10.0f);
m_oldx[_chnl] = x;
m_oldy1[_chnl] = m_y1[_chnl];
@@ -369,27 +373,23 @@ public:
// 3x onepole filters with 4x oversampling and interpolation of oversampled signal:
// input signal is linear-interpolated after oversampling, output signal is averaged from oversampled outputs
case Tripole:
case FilterType::Tripole:
{
out = 0.0f;
float ip = 0.0f;
for( int i = 0; i < 4; ++i )
{
ip += 0.25f;
sample_t x = linearInterpolate( m_last[_chnl], _in0, ip ) - m_r * m_y3[_chnl];
m_y1[_chnl] = qBound( -10.0f,
( x + m_oldx[_chnl] ) * m_p
- m_k * m_y1[_chnl],
10.0f );
m_y2[_chnl] = qBound( -10.0f,
( m_y1[_chnl] + m_oldy1[_chnl] ) * m_p
- m_k * m_y2[_chnl],
10.0f );
m_y3[_chnl] = qBound( -10.0f,
( m_y2[_chnl] + m_oldy2[_chnl] ) * m_p
- m_k * m_y3[_chnl],
10.0f );
m_y1[_chnl] = std::clamp((x + m_oldx[_chnl]) * m_p
- m_k * m_y1[_chnl], -10.0f,
10.0f);
m_y2[_chnl] = std::clamp((m_y1[_chnl] + m_oldy1[_chnl]) * m_p
- m_k * m_y2[_chnl], -10.0f,
10.0f);
m_y3[_chnl] = std::clamp((m_y2[_chnl] + m_oldy2[_chnl]) * m_p
- m_k * m_y3[_chnl], -10.0f,
10.0f);
m_oldx[_chnl] = x;
m_oldy1[_chnl] = m_y1[_chnl];
m_oldy2[_chnl] = m_y2[_chnl];
@@ -405,8 +405,8 @@ public:
// and extended to other SV filter types
// /* Hal Chamberlin's state variable filter */
case Lowpass_SV:
case Bandpass_SV:
case FilterType::Lowpass_SV:
case FilterType::Bandpass_SV:
{
float highpass;
@@ -422,15 +422,14 @@ public:
}
/* mix filter output into output buffer */
return m_type == Lowpass_SV
return m_type == FilterType::Lowpass_SV
? m_delay4[_chnl]
: m_delay3[_chnl];
}
case Highpass_SV:
case FilterType::Highpass_SV:
{
float hp;
for( int i = 0; i < 2; ++i ) // 2x oversample
{
m_delay2[_chnl] = m_delay2[_chnl] + m_svf1 * m_delay1[_chnl];
@@ -441,10 +440,9 @@ public:
return hp;
}
case Notch_SV:
case FilterType::Notch_SV:
{
float hp1, hp2;
float hp1;
for( int i = 0; i < 2; ++i ) // 2x oversample
{
m_delay2[_chnl] = m_delay2[_chnl] + m_svf1 * m_delay1[_chnl]; /* delay2/4 = lowpass output */
@@ -452,7 +450,7 @@ public:
m_delay1[_chnl] = m_svf1 * hp1 + m_delay1[_chnl]; /* delay1/3 = bandpass output */
m_delay4[_chnl] = m_delay4[_chnl] + m_svf2 * m_delay3[_chnl];
hp2 = m_delay2[_chnl] - m_delay4[_chnl] - m_svq * m_delay3[_chnl];
float hp2 = m_delay2[_chnl] - m_delay4[_chnl] - m_svq * m_delay3[_chnl];
m_delay3[_chnl] = m_svf2 * hp2 + m_delay3[_chnl];
}
@@ -466,22 +464,22 @@ public:
// can be driven up to self-oscillation (BTW: do not remove the limits!!!).
// (C) 1998 ... 2009 S.Fendt. Released under the GPL v2.0 or any later version.
case Lowpass_RC12:
case FilterType::Lowpass_RC12:
{
sample_t lp, bp, hp, in;
sample_t lp = 0.0f;
for( int n = 4; n != 0; --n )
{
in = _in0 + m_rcbp0[_chnl] * m_rcq;
in = qBound( -1.0f, in, 1.0f );
sample_t in = _in0 + m_rcbp0[_chnl] * m_rcq;
in = std::clamp(in, -1.0f, 1.0f);
lp = in * m_rcb + m_rclp0[_chnl] * m_rca;
lp = qBound( -1.0f, lp, 1.0f );
lp = std::clamp(lp, -1.0f, 1.0f);
hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
sample_t hp = m_rcc * (m_rchp0[_chnl] + in - m_rclast0[_chnl]);
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
bp = qBound( -1.0f, bp, 1.0f );
sample_t bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
bp = std::clamp(bp, -1.0f, 1.0f);
m_rclast0[_chnl] = in;
m_rclp0[_chnl] = lp;
@@ -490,45 +488,45 @@ public:
}
return lp;
}
case Highpass_RC12:
case Bandpass_RC12:
case FilterType::Highpass_RC12:
case FilterType::Bandpass_RC12:
{
sample_t hp, bp, in;
sample_t hp, bp;
for( int n = 4; n != 0; --n )
{
in = _in0 + m_rcbp0[_chnl] * m_rcq;
in = qBound( -1.0f, in, 1.0f );
sample_t in = _in0 + m_rcbp0[_chnl] * m_rcq;
in = std::clamp(in, -1.0f, 1.0f);
hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
bp = qBound( -1.0f, bp, 1.0f );
bp = std::clamp(bp, -1.0f, 1.0f);
m_rclast0[_chnl] = in;
m_rchp0[_chnl] = hp;
m_rcbp0[_chnl] = bp;
}
return m_type == Highpass_RC12 ? hp : bp;
return m_type == FilterType::Highpass_RC12 ? hp : bp;
}
case Lowpass_RC24:
case FilterType::Lowpass_RC24:
{
sample_t lp, bp, hp, in;
sample_t lp;
for( int n = 4; n != 0; --n )
{
// first stage is as for the 12dB case...
in = _in0 + m_rcbp0[_chnl] * m_rcq;
in = qBound( -1.0f, in, 1.0f );
sample_t in = _in0 + m_rcbp0[_chnl] * m_rcq;
in = std::clamp(in, -1.0f, 1.0f);
lp = in * m_rcb + m_rclp0[_chnl] * m_rca;
lp = qBound( -1.0f, lp, 1.0f );
lp = std::clamp(lp, -1.0f, 1.0f);
hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
sample_t hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
bp = qBound( -1.0f, bp, 1.0f );
sample_t bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
bp = std::clamp(bp, -1.0f, 1.0f);
m_rclast0[_chnl] = in;
m_rclp0[_chnl] = lp;
@@ -537,16 +535,16 @@ public:
// second stage gets the output of the first stage as input...
in = lp + m_rcbp1[_chnl] * m_rcq;
in = qBound( -1.0f, in, 1.0f );
in = std::clamp(in, -1.0f, 1.0f );
lp = in * m_rcb + m_rclp1[_chnl] * m_rca;
lp = qBound( -1.0f, lp, 1.0f );
lp = std::clamp(lp, -1.0f, 1.0f);
hp = m_rcc * ( m_rchp1[_chnl] + in - m_rclast1[_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_rcb + m_rcbp1[_chnl] * m_rca;
bp = qBound( -1.0f, bp, 1.0f );
bp = std::clamp(bp, -1.0f, 1.0f);
m_rclast1[_chnl] = in;
m_rclp1[_chnl] = lp;
@@ -555,91 +553,89 @@ public:
}
return lp;
}
case Highpass_RC24:
case Bandpass_RC24:
case FilterType::Highpass_RC24:
case FilterType::Bandpass_RC24:
{
sample_t hp, bp, in;
sample_t hp, bp;
for( int n = 4; n != 0; --n )
{
// first stage is as for the 12dB case...
in = _in0 + m_rcbp0[_chnl] * m_rcq;
in = qBound( -1.0f, in, 1.0f );
sample_t in = _in0 + m_rcbp0[_chnl] * m_rcq;
in = std::clamp(in, -1.0f, 1.0f);
hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
bp = qBound( -1.0f, bp, 1.0f );
bp = std::clamp(bp, -1.0f, 1.0f);
m_rclast0[_chnl] = in;
m_rchp0[_chnl] = hp;
m_rcbp0[_chnl] = bp;
// second stage gets the output of the first stage as input...
in = m_type == Highpass_RC24
in = m_type == FilterType::Highpass_RC24
? hp + m_rcbp1[_chnl] * m_rcq
: bp + m_rcbp1[_chnl] * m_rcq;
in = qBound( -1.0f, in, 1.0f );
in = std::clamp(in, -1.0f, 1.0f);
hp = m_rcc * ( m_rchp1[_chnl] + in - m_rclast1[_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_rcb + m_rcbp1[_chnl] * m_rca;
bp = qBound( -1.0f, bp, 1.0f );
bp = std::clamp(bp, -1.0f, 1.0f);
m_rclast1[_chnl] = in;
m_rchp1[_chnl] = hp;
m_rcbp1[_chnl] = bp;
}
return m_type == Highpass_RC24 ? hp : bp;
return m_type == FilterType::Highpass_RC24 ? hp : bp;
}
case Formantfilter:
case FastFormant:
case FilterType::Formantfilter:
case FilterType::FastFormant:
{
if( qAbs( _in0 ) < 1.0e-10f && qAbs( m_vflast[0][_chnl] ) < 1.0e-10f ) { return 0.0f; } // performance hack - skip processing when the numbers get too small
sample_t hp, bp, in;
if (std::abs(_in0) < 1.0e-10f && std::abs(m_vflast[0][_chnl]) < 1.0e-10f) { return 0.0f; } // performance hack - skip processing when the numbers get too small
out = 0;
const int os = m_type == FastFormant ? 1 : 4; // no oversampling for fast formant
const int os = m_type == FilterType::FastFormant ? 1 : 4; // no oversampling for fast formant
for( int o = 0; o < os; ++o )
{
// first formant
in = _in0 + m_vfbp[0][_chnl] * m_vfq;
in = qBound( -1.0f, in, 1.0f );
sample_t in = _in0 + m_vfbp[0][_chnl] * m_vfq;
in = std::clamp(in, -1.0f, 1.0f);
hp = m_vfc[0] * ( m_vfhp[0][_chnl] + in - m_vflast[0][_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
sample_t hp = m_vfc[0] * ( m_vfhp[0][_chnl] + in - m_vflast[0][_chnl] );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_vfb[0] + m_vfbp[0][_chnl] * m_vfa[0];
bp = qBound( -1.0f, bp, 1.0f );
sample_t bp = hp * m_vfb[0] + m_vfbp[0][_chnl] * m_vfa[0];
bp = std::clamp(bp, -1.0f, 1.0f);
m_vflast[0][_chnl] = in;
m_vfhp[0][_chnl] = hp;
m_vfbp[0][_chnl] = bp;
in = bp + m_vfbp[2][_chnl] * m_vfq;
in = qBound( -1.0f, in, 1.0f );
in = std::clamp(in, -1.0f, 1.0f);
hp = m_vfc[0] * ( m_vfhp[2][_chnl] + in - m_vflast[2][_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_vfb[0] + m_vfbp[2][_chnl] * m_vfa[0];
bp = qBound( -1.0f, bp, 1.0f );
bp = std::clamp(bp, -1.0f, 1.0f);
m_vflast[2][_chnl] = in;
m_vfhp[2][_chnl] = hp;
m_vfbp[2][_chnl] = bp;
in = bp + m_vfbp[4][_chnl] * m_vfq;
in = qBound( -1.0f, in, 1.0f );
in = std::clamp(in, -1.0f, 1.0f);
hp = m_vfc[0] * ( m_vfhp[4][_chnl] + in - m_vflast[4][_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_vfb[0] + m_vfbp[4][_chnl] * m_vfa[0];
bp = qBound( -1.0f, bp, 1.0f );
bp = std::clamp(bp, -1.0f, 1.0f);
m_vflast[4][_chnl] = in;
m_vfhp[4][_chnl] = hp;
@@ -649,39 +645,39 @@ public:
// second formant
in = _in0 + m_vfbp[0][_chnl] * m_vfq;
in = qBound( -1.0f, in, 1.0f );
in = std::clamp(in, -1.0f, 1.0f);
hp = m_vfc[1] * ( m_vfhp[1][_chnl] + in - m_vflast[1][_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_vfb[1] + m_vfbp[1][_chnl] * m_vfa[1];
bp = qBound( -1.0f, bp, 1.0f );
bp = std::clamp(bp, -1.0f, 1.0f);
m_vflast[1][_chnl] = in;
m_vfhp[1][_chnl] = hp;
m_vfbp[1][_chnl] = bp;
in = bp + m_vfbp[3][_chnl] * m_vfq;
in = qBound( -1.0f, in, 1.0f );
in = std::clamp(in, -1.0f, 1.0f);
hp = m_vfc[1] * ( m_vfhp[3][_chnl] + in - m_vflast[3][_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_vfb[1] + m_vfbp[3][_chnl] * m_vfa[1];
bp = qBound( -1.0f, bp, 1.0f );
bp = std::clamp(bp, -1.0f, 1.0f);
m_vflast[3][_chnl] = in;
m_vfhp[3][_chnl] = hp;
m_vfbp[3][_chnl] = bp;
in = bp + m_vfbp[5][_chnl] * m_vfq;
in = qBound( -1.0f, in, 1.0f );
in = std::clamp(in, -1.0f, 1.0f);
hp = m_vfc[1] * ( m_vfhp[5][_chnl] + in - m_vflast[5][_chnl] );
hp = qBound( -1.0f, hp, 1.0f );
hp = std::clamp(hp, -1.0f, 1.0f);
bp = hp * m_vfb[1] + m_vfbp[5][_chnl] * m_vfa[1];
bp = qBound( -1.0f, bp, 1.0f );
bp = std::clamp(bp, -1.0f, 1.0f);
m_vflast[5][_chnl] = in;
m_vfhp[5][_chnl] = hp;
@@ -689,7 +685,7 @@ public:
out += bp;
}
return m_type == FastFormant ? out * 2.0f : out * 0.5f;
return m_type == FilterType::FastFormant ? out * 2.0f : out * 0.5f;
}
default:
@@ -710,16 +706,16 @@ public:
inline void calcFilterCoeffs( float _freq, float _q )
{
// temp coef vars
_q = qMax( _q, minQ() );
_q = std::max(_q, minQ());
if( m_type == Lowpass_RC12 ||
m_type == Bandpass_RC12 ||
m_type == Highpass_RC12 ||
m_type == Lowpass_RC24 ||
m_type == Bandpass_RC24 ||
m_type == Highpass_RC24 )
if( m_type == FilterType::Lowpass_RC12 ||
m_type == FilterType::Bandpass_RC12 ||
m_type == FilterType::Highpass_RC12 ||
m_type == FilterType::Lowpass_RC24 ||
m_type == FilterType::Bandpass_RC24 ||
m_type == FilterType::Highpass_RC24 )
{
_freq = qBound( 50.0f, _freq, 20000.0f );
_freq = std::clamp(_freq, 50.0f, 20000.0f);
const float sr = m_sampleRatio * 0.25f;
const float f = 1.0f / ( _freq * F_2PI );
@@ -732,10 +728,10 @@ public:
return;
}
if( m_type == Formantfilter ||
m_type == FastFormant )
if( m_type == FilterType::Formantfilter ||
m_type == FilterType::FastFormant )
{
_freq = qBound( minFreq(), _freq, 20000.0f ); // limit freq and q for not getting bad noise out of the filter...
_freq = std::clamp(_freq, minFreq(), 20000.0f); // limit freq and q for not getting bad noise out of the filter...
// formats for a, e, i, o, u, a
static const float _f[6][2] = { { 1000, 1400 }, { 500, 2300 },
@@ -758,7 +754,7 @@ public:
const float f1 = 1.0f / ( linearInterpolate( _f[vowel+0][1], _f[vowel+1][1], fract ) * F_2PI );
// samplerate coeff: depends on oversampling
const float sr = m_type == FastFormant ? m_sampleRatio : m_sampleRatio * 0.25f;
const float sr = m_type == FilterType::FastFormant ? m_sampleRatio : m_sampleRatio * 0.25f;
m_vfa[0] = 1.0f - sr / ( f0 + sr );
m_vfb[0] = 1.0f - m_vfa[0];
@@ -769,11 +765,11 @@ public:
return;
}
if( m_type == Moog ||
m_type == DoubleMoog )
if( m_type == FilterType::Moog ||
m_type == FilterType::DoubleMoog )
{
// [ 0 - 0.5 ]
const float f = qBound( minFreq(), _freq, 20000.0f ) * m_sampleRatio;
const float f = std::clamp(_freq, minFreq(), 20000.0f) * m_sampleRatio;
// (Empirical tunning)
m_p = ( 3.6f - 3.2f * f ) * f;
m_k = 2.0f * m_p - 1;
@@ -788,9 +784,9 @@ public:
return;
}
if( m_type == Tripole )
if( m_type == FilterType::Tripole )
{
const float f = qBound( 20.0f, _freq, 20000.0f ) * m_sampleRatio * 0.25f;
const float f = std::clamp(_freq, 20.0f, 20000.0f) * m_sampleRatio * 0.25f;
m_p = ( 3.6f - 3.2f * f ) * f;
m_k = 2.0f * m_p - 1.0f;
@@ -799,20 +795,20 @@ public:
return;
}
if( m_type == Lowpass_SV ||
m_type == Bandpass_SV ||
m_type == Highpass_SV ||
m_type == Notch_SV )
if( m_type == FilterType::Lowpass_SV ||
m_type == FilterType::Bandpass_SV ||
m_type == FilterType::Highpass_SV ||
m_type == FilterType::Notch_SV )
{
const float f = sinf( qMax( minFreq(), _freq ) * m_sampleRatio * F_PI );
m_svf1 = qMin( f, 0.825f );
m_svf2 = qMin( f * 2.0f, 0.825f );
m_svq = qMax( 0.0001f, 2.0f - ( _q * 0.1995f ) );
const float f = sinf(std::max(minFreq(), _freq) * m_sampleRatio * F_PI);
m_svf1 = std::min(f, 0.825f);
m_svf2 = std::min(f * 2.0f, 0.825f);
m_svq = std::max(0.0001f, 2.0f - (_q * 0.1995f));
return;
}
// other filters
_freq = qBound( minFreq(), _freq, 20000.0f );
_freq = std::clamp(_freq, minFreq(), 20000.0f);
const float omega = F_2PI * _freq * m_sampleRatio;
const float tsin = sinf( omega ) * 0.5f;
const float tcos = cosf( omega );
@@ -826,38 +822,38 @@ public:
switch( m_type )
{
case LowPass:
case FilterType::LowPass:
{
const float b1 = ( 1.0f - tcos ) * a0;
const float b0 = b1 * 0.5f;
m_biQuad.setCoeffs( a1, a2, b0, b1, b0 );
break;
}
case HiPass:
case FilterType::HiPass:
{
const float b1 = ( -1.0f - tcos ) * a0;
const float b0 = b1 * -0.5f;
m_biQuad.setCoeffs( a1, a2, b0, b1, b0 );
break;
}
case BandPass_CSG:
case FilterType::BandPass_CSG:
{
const float b0 = tsin * a0;
m_biQuad.setCoeffs( a1, a2, b0, 0.0f, -b0 );
break;
}
case BandPass_CZPG:
case FilterType::BandPass_CZPG:
{
const float b0 = alpha * a0;
m_biQuad.setCoeffs( a1, a2, b0, 0.0f, -b0 );
break;
}
case Notch:
case FilterType::Notch:
{
m_biQuad.setCoeffs( a1, a2, a0, a1, a0 );
break;
}
case AllPass:
case FilterType::AllPass:
{
m_biQuad.setCoeffs( a1, a2, a2, a1, 1.0f );
break;
@@ -906,7 +902,7 @@ private:
// in/out history for Lowpass_SV (state-variant lowpass)
frame m_delay1, m_delay2, m_delay3, m_delay4;
FilterTypes m_type;
FilterType m_type;
bool m_doubleFilter;
float m_sampleRate;
@@ -918,4 +914,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_BASIC_FILTERS_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef BUFFER_MANAGER_H
#define BUFFER_MANAGER_H
#ifndef LMMS_BUFFER_MANAGER_H
#define LMMS_BUFFER_MANAGER_H
#include "lmms_export.h"
#include "lmms_basics.h"
@@ -54,4 +54,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_BUFFER_MANAGER_H

View File

@@ -23,10 +23,10 @@
*
*/
#ifndef LMMS_GUI_CPU_LOAD_WIDGET_H
#define LMMS_GUI_CPU_LOAD_WIDGET_H
#ifndef CPULOAD_WIDGET_H
#define CPULOAD_WIDGET_H
#include <algorithm>
#include <QTimer>
#include <QPixmap>
#include <QWidget>
@@ -41,6 +41,7 @@ namespace lmms::gui
class CPULoadWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY(int stepSize MEMBER m_stepSize)
public:
CPULoadWidget( QWidget * _parent );
~CPULoadWidget() override = default;
@@ -55,6 +56,8 @@ protected slots:
private:
int stepSize() const { return std::max(1, m_stepSize); }
int m_currentLoad;
QPixmap m_temp;
@@ -65,9 +68,11 @@ private:
QTimer m_updateTimer;
int m_stepSize = 1;
} ;
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_CPU_LOAD_WIDGET_H

View File

@@ -22,9 +22,8 @@
*
*/
#ifndef CAPTION_MENU_H
#define CAPTION_MENU_H
#ifndef LMMS_GUI_CAPTION_MENU_H
#define LMMS_GUI_CAPTION_MENU_H
#include <QMenu>
@@ -47,4 +46,4 @@ public:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_CAPTION_MENU_H

View File

@@ -22,8 +22,10 @@
*
*/
#ifndef TRACK_CONTENT_OBJECT_H
#define TRACK_CONTENT_OBJECT_H
#ifndef LMMS_CLIP_H
#define LMMS_CLIP_H
#include <optional>
#include <QColor>
@@ -48,7 +50,6 @@ class TrackView;
class LMMS_EXPORT Clip : public Model, public JournallingObject
{
Q_OBJECT
MM_OPERATORS
mapPropertyFromModel(bool,isMuted,setMuted,m_mutedModel);
mapPropertyFromModel(bool,isSolo,setSolo,m_soloModel);
public:
@@ -109,24 +110,8 @@ public:
return m_autoResize;
}
QColor color() const
{
return m_color;
}
void setColor( const QColor & c )
{
m_color = c;
}
bool hasColor();
void useCustomClipColor( bool b );
bool usesCustomClipColor()
{
return m_useCustomClipColor;
}
auto color() const -> const std::optional<QColor>& { return m_color; }
void setColor(const std::optional<QColor>& color);
virtual void movePosition( const TimePos & pos );
virtual void changeLength( const TimePos & length );
@@ -164,13 +149,6 @@ signals:
private:
enum Actions
{
NoAction,
Move,
Resize
} ;
Track * m_track;
QString m_name;
@@ -184,8 +162,7 @@ private:
bool m_selectViewOnCreate;
QColor m_color;
bool m_useCustomClipColor;
std::optional<QColor> m_color;
friend class ClipView;
@@ -194,4 +171,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_CLIP_H

View File

@@ -22,9 +22,10 @@
*
*/
#ifndef TRACK_CONTENT_OBJECT_VIEW_H
#define TRACK_CONTENT_OBJECT_VIEW_H
#ifndef LMMS_GUI_CLIP_VIEW_H
#define LMMS_GUI_CLIP_VIEW_H
#include <optional>
#include <QVector>
@@ -140,7 +141,7 @@ public slots:
void resetColor();
protected:
enum ContextMenuAction
enum class ContextMenuAction
{
Remove,
Cut,
@@ -184,6 +185,7 @@ protected:
virtual void paintTextLabel(QString const & text, QPainter & painter);
auto hasCustomColor() const -> bool;
protected slots:
void updateLength();
@@ -191,9 +193,9 @@ protected slots:
private:
enum Actions
enum class Action
{
NoAction,
None,
Move,
MoveSelection,
Resize,
@@ -206,7 +208,7 @@ private:
static TextFloat * s_textFloat;
Clip * m_clip;
Actions m_action;
Action m_action;
QPoint m_initialMousePos;
QPoint m_initialMouseGlobalPos;
QVector<TimePos> m_initialOffsets;
@@ -241,7 +243,7 @@ private:
bool mouseMovedDistance( QMouseEvent * me, int distance );
TimePos draggedClipPos( QMouseEvent * me );
int knifeMarkerPos( QMouseEvent * me );
void setColor(const QColor* color);
void setColor(const std::optional<QColor>& color);
//! Return true iff the clip could be split. Currently only implemented for samples
virtual bool splitClip( const TimePos pos ){ return false; };
void updateCursor(QMouseEvent * me);
@@ -252,4 +254,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_GUI_CLIP_VIEW_H

View File

@@ -22,11 +22,13 @@
*
*/
#ifndef CLIPBOARD_H
#define CLIPBOARD_H
#ifndef LMMS_CLIPBOARD_H
#define LMMS_CLIPBOARD_H
#include <QMap>
#include <QDomElement>
#include <QMap>
#include "lmms_export.h"
class QMimeData;
@@ -44,7 +46,7 @@ namespace lmms::Clipboard
bool hasFormat( MimeType mT );
// Helper methods for String data
void copyString( const QString & str, MimeType mT );
void LMMS_EXPORT copyString(const QString& str, MimeType mT);
QString getString( MimeType mT );
// Helper methods for String Pair data
@@ -68,4 +70,4 @@ namespace lmms::Clipboard
} // namespace lmms::Clipboard
#endif
#endif // LMMS_CLIPBOARD_H

View File

@@ -21,8 +21,8 @@
*
*/
#ifndef COLOR_CHOOSER_H
#define COLOR_CHOOSER_H
#ifndef LMMS_GUI_COLOR_CHOOSER_H
#define LMMS_GUI_COLOR_CHOOSER_H
#include <QApplication>
#include <QColor>
@@ -34,7 +34,7 @@ namespace lmms::gui
{
class ColorChooser: public QColorDialog
class ColorChooser : public QColorDialog
{
public:
ColorChooser(const QColor &initial, QWidget *parent): QColorDialog(initial, parent) {};
@@ -68,5 +68,4 @@ private:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_COLOR_CHOOSER_H

54
include/ColorHelper.h Normal file
View 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

View File

@@ -22,9 +22,8 @@
*
*/
#ifndef COMBOBOX_H
#define COMBOBOX_H
#ifndef LMMS_GUI_COMBOBOX_H
#define LMMS_GUI_COMBOBOX_H
#include <QMenu>
#include <QWidget>
@@ -67,9 +66,9 @@ protected:
private:
static QPixmap* s_background;
static QPixmap* s_arrow;
static QPixmap* s_arrowSelected;
QPixmap m_background = embed::getIconPixmap("combobox_bg");
QPixmap m_arrow = embed::getIconPixmap("combobox_arrow");
QPixmap m_arrowSelected = embed::getIconPixmap("combobox_arrow_selected");
QMenu m_menu;
@@ -83,4 +82,4 @@ private slots:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_COMBOBOX_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef COMBOBOX_MODEL_H
#define COMBOBOX_MODEL_H
#ifndef LMMS_COMBOBOX_MODEL_H
#define LMMS_COMBOBOX_MODEL_H
#include <memory>
#include <utility>
@@ -72,12 +72,12 @@ public:
const QString & itemText( int i ) const
{
return m_items[qBound<int>( minValue(), i, maxValue() )].first;
return m_items[std::clamp(i, minValue(), maxValue())].first;
}
const PixmapLoader* itemPixmap( int i ) const
{
return m_items[qBound<int>( minValue(), i, maxValue() )].second.get();
return m_items[std::clamp(i, minValue(), maxValue())].second.get();
}
int size() const
@@ -95,4 +95,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_COMBOBOX_MODEL_H

View File

@@ -22,18 +22,17 @@
*
*/
#ifndef CONFIG_MGR_H
#define CONFIG_MGR_H
#ifndef LMMS_CONFIG_MANAGER_H
#define LMMS_CONFIG_MANAGER_H
#include "lmmsconfig.h"
#include <QMap>
#include <QPair>
#include <QStringList>
#include <QVector>
#include <QObject>
#include <vector>
#include "lmms_export.h"
@@ -240,11 +239,8 @@ public:
void addRecentlyOpenedProject(const QString & _file);
const QString & value(const QString & cls,
const QString & attribute) const;
const QString & value(const QString & cls,
const QString & attribute,
const QString & defaultVal) const;
QString value(const QString& cls, const QString& attribute, const QString& defaultVal = "") const;
void setValue(const QString & cls, const QString & attribute,
const QString & value);
void deleteValue(const QString & cls, const QString & attribute);
@@ -303,7 +299,7 @@ private:
unsigned int m_configVersion;
QStringList m_recentlyOpenedProjects;
using stringPairVector = QVector<QPair<QString, QString>>;
using stringPairVector = std::vector<QPair<QString, QString>>;
using settingsMap = QMap<QString, stringPairVector>;
settingsMap m_settings;
@@ -314,4 +310,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_CONFIG_MANAGER_H

View File

@@ -70,8 +70,8 @@
**
****************************************************************************/
#ifndef CONTROLLAYOUT_H
#define CONTROLLAYOUT_H
#ifndef LMMS_GUI_CONTROL_LAYOUT_H
#define LMMS_GUI_CONTROL_LAYOUT_H
#include <QLayout>
#include <QMultiMap>
@@ -141,4 +141,4 @@ private:
} // namespace lmms::gui
#endif // CONTROLLAYOUT_H
#endif // LMMS_GUI_CONTROL_LAYOUT_H

View File

@@ -23,9 +23,8 @@
*
*/
#ifndef CONTROLLER_H
#define CONTROLLER_H
#ifndef LMMS_CONTROLLER_H
#define LMMS_CONTROLLER_H
#include "lmms_export.h"
#include "Engine.h"
@@ -46,26 +45,25 @@ class ControllerDialog;
} // namespace gui
using ControllerVector = QVector<Controller*>;
using ControllerVector = std::vector<Controller*>;
class LMMS_EXPORT Controller : public Model, public JournallingObject
{
Q_OBJECT
public:
enum ControllerTypes
enum class ControllerType
{
DummyController,
LfoController,
MidiController,
PeakController,
Dummy,
Lfo,
Midi,
Peak,
/*
XYController,
EquationController
XY,
Equation
*/
NumControllerTypes
} ;
Controller( ControllerTypes _type, Model * _parent,
Controller( ControllerType _type, Model * _parent,
const QString & _display_name );
~Controller() override;
@@ -84,7 +82,7 @@ public:
m_sampleExact = _exact;
}
inline ControllerTypes type() const
inline ControllerType type() const
{
return( m_type );
}
@@ -95,8 +93,8 @@ public:
{
switch( m_type )
{
case LfoController: return( true );
case PeakController: return( true );
case ControllerType::Lfo: return( true );
case ControllerType::Peak: return( true );
default:
break;
}
@@ -113,13 +111,13 @@ public:
void loadSettings( const QDomElement & _this ) override;
QString nodeName() const override;
static Controller * create( ControllerTypes _tt, Model * _parent );
static Controller * create( ControllerType _tt, Model * _parent );
static Controller * create( const QDomElement & _this,
Model * _parent );
inline static float fittedValue( float _val )
{
return qBound<float>( 0.0f, _val, 1.0f );
return std::clamp(_val, 0.0f, 1.0f);
}
static long runningPeriods()
@@ -166,7 +164,7 @@ protected:
int m_connectionCount;
QString m_name;
ControllerTypes m_type;
ControllerType m_type;
static ControllerVector s_controllers;
@@ -184,5 +182,4 @@ signals:
} // namespace lmms
#endif
#endif // LMMS_CONTROLLER_H

View File

@@ -26,17 +26,17 @@
*
*/
#ifndef CONTROLLER_CONNECTION_H
#define CONTROLLER_CONNECTION_H
#ifndef LMMS_CONTROLLER_CONNECTION_H
#define LMMS_CONTROLLER_CONNECTION_H
#include <QObject>
#include <QVector>
#include "Controller.h"
#include "JournallingObject.h"
#include "ValueBuffer.h"
#include <vector>
namespace lmms
{
@@ -47,7 +47,7 @@ namespace gui
class ControllerConnectionDialog;
}
using ControllerConnectionVector = QVector<ControllerConnection*>;
using ControllerConnectionVector = std::vector<ControllerConnection*>;
class LMMS_EXPORT ControllerConnection : public QObject, public JournallingObject
{
@@ -128,5 +128,4 @@ signals:
} // namespace lmms
#endif
#endif // LMMS_CONTROLLER_CONNECTION_H

View File

@@ -23,9 +23,8 @@
*
*/
#ifndef CONTROLLER_CONNECTION_DIALOG_H
#define CONTROLLER_CONNECTION_DIALOG_H
#ifndef LMMS_GUI_CONTROLLER_CONNECTION_DIALOG_H
#define LMMS_GUI_CONTROLLER_CONNECTION_DIALOG_H
#include <QDialog>
#include <QSortFilterProxyModel>
@@ -111,4 +110,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_GUI_CONTROLLER_CONNECTION_DIALOG_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef CONTROLLER_DIALOG_H
#define CONTROLLER_DIALOG_H
#ifndef LMMS_GUI_CONTROLLER_DIALOG_H
#define LMMS_GUI_CONTROLLER_DIALOG_H
#include <QWidget>
@@ -61,4 +61,4 @@ protected:
} // namespace lmms
#endif
#endif // LMMS_GUI_CONTROLLER_DIALOG_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef CONTROLLER_RACK_VIEW_H
#define CONTROLLER_RACK_VIEW_H
#ifndef LMMS_GUI_CONTROLLER_RACK_VIEW_H
#define LMMS_GUI_CONTROLLER_RACK_VIEW_H
#include <QWidget>
#include <QCloseEvent>
@@ -92,4 +92,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_GUI_CONTROLLER_RACK_VIEW_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef CONTROLLER_VIEW_H
#define CONTROLLER_VIEW_H
#ifndef LMMS_GUI_CONTROLLER_VIEW_H
#define LMMS_GUI_CONTROLLER_VIEW_H
#include <QFrame>
@@ -88,4 +88,4 @@ private:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_CONTROLLER_VIEW_H

View File

@@ -22,10 +22,8 @@
*
*/
#ifndef CONTROLS_H
#define CONTROLS_H
#ifndef LMMS_GUI_CONTROLS_H
#define LMMS_GUI_CONTROLS_H
// headers only required for covariance
#include "AutomatableModel.h"
@@ -146,4 +144,4 @@ public:
} // namespace lmms
#endif // CONTROLS_H
#endif // LMMS_GUI_CONTROLS_H

View File

@@ -1,6 +1,29 @@
/* Text customizable knob */
#ifndef CUSTOM_TEXT_KNOB_H
#define CUSTOM_TEXT_KNOB_H
/*
* CustomTextKnob.h
*
* Copyright (c) 2020 Ibuki Sugiyama <main/at/fuwa.dev>
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef LMMS_GUI_CUSTOM_TEXT_KNOB_H
#define LMMS_GUI_CUSTOM_TEXT_KNOB_H
#include "Knob.h"
@@ -13,7 +36,7 @@ class LMMS_EXPORT CustomTextKnob : public Knob
protected:
inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible
public:
CustomTextKnob( knobTypes _knob_num, QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() );
CustomTextKnob( KnobType _knob_num, QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() );
CustomTextKnob( QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() ); //!< default ctor
@@ -34,4 +57,4 @@ protected:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_CUSTOM_TEXT_KNOB_H

View File

@@ -23,15 +23,14 @@
*
*/
#ifndef DATA_FILE_H
#define DATA_FILE_H
#ifndef LMMS_DATA_FILE_H
#define LMMS_DATA_FILE_H
#include <map>
#include <QDomDocument>
#include <vector>
#include "lmms_export.h"
#include "MemoryManager.h"
class QTextStream;
@@ -43,14 +42,13 @@ class ProjectVersion;
class LMMS_EXPORT DataFile : public QDomDocument
{
MM_OPERATORS
using UpgradeMethod = void(DataFile::*)();
public:
enum Types
enum class Type
{
UnknownType,
Unknown,
SongProject,
SongProjectTemplate,
InstrumentTrackSettings,
@@ -58,10 +56,8 @@ public:
ClipboardData,
JournalData,
EffectSettings,
MidiClip,
TypeCount
MidiClip
} ;
using Type = Types;
DataFile( const QString& fileName );
DataFile( const QByteArray& data );
@@ -129,6 +125,11 @@ private:
void upgrade_defaultTripleOscillatorHQ();
void upgrade_mixerRename();
void upgrade_bbTcoRename();
void upgrade_sampleAndHold();
void upgrade_midiCCIndexing();
void upgrade_loopsRename();
void upgrade_noteTypes();
void upgrade_fixCMTDelays();
// List of all upgrade methods
static const std::vector<UpgradeMethod> UPGRADE_METHODS;
@@ -148,10 +149,9 @@ private:
QDomElement m_head;
Type m_type;
unsigned int m_fileVersion;
} ;
} // namespace lmms
#endif
#endif // LMMS_DATA_FILE_H

View File

@@ -22,15 +22,13 @@
* Boston, MA 02110-1301 USA.
*
*/
#ifndef DELAY_H
#define DELAY_H
#ifndef LMMS_DELAY_H
#define LMMS_DELAY_H
#include "lmms_basics.h"
#include "lmms_math.h"
#include "interpolation.h"
#include "MemoryManager.h"
namespace lmms
{
@@ -75,20 +73,20 @@ public:
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC<frame>(maxDelay );
m_buffer = new frame[maxDelay];
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~CombFeedback()
{
MM_FREE( m_buffer );
delete[] m_buffer;
}
inline void setMaxDelay( int maxDelay )
{
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC<frame>( maxDelay );
delete[] m_buffer;
m_buffer = new frame[maxDelay];
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
@@ -146,20 +144,20 @@ class CombFeedfwd
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC<frame>( maxDelay );
m_buffer = new frame[maxDelay];
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~CombFeedfwd()
{
MM_FREE( m_buffer );
delete[] m_buffer;
}
inline void setMaxDelay( int maxDelay )
{
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC<frame>( maxDelay );
delete[] m_buffer;
m_buffer = new frame[maxDelay];
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
@@ -217,20 +215,20 @@ class CombFeedbackDualtap
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC<frame>( maxDelay );
m_buffer = new frame[maxDelay];
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~CombFeedbackDualtap()
{
MM_FREE( m_buffer );
delete[] m_buffer;
}
inline void setMaxDelay( int maxDelay )
{
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC<frame>( maxDelay );
delete[] m_buffer;
m_buffer = new frame[maxDelay];
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
@@ -298,20 +296,20 @@ public:
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC<frame>( maxDelay );
m_buffer = new frame[maxDelay];
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~AllpassDelay()
{
MM_FREE( m_buffer );
delete[] m_buffer;
}
inline void setMaxDelay( int maxDelay )
{
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC<frame>( maxDelay );
delete[] m_buffer;
m_buffer = new frame[maxDelay];
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
@@ -365,4 +363,4 @@ using StereoAllpassDelay = AllpassDelay<2>;
} // namespace lmms
#endif
#endif // LMMS_DELAY_H

View File

@@ -24,8 +24,8 @@
*
*/
#ifndef DEPRECATIONHELPER_H
#define DEPRECATIONHELPER_H
#ifndef LMMS_DEPRECATIONHELPER_H
#define LMMS_DEPRECATIONHELPER_H
#include <QFontMetrics>
#include <QWheelEvent>
@@ -66,4 +66,4 @@ inline QPoint position(QWheelEvent *wheelEvent)
} // namespace lmms
#endif // DEPRECATIONHELPER_H
#endif // LMMS_DEPRECATIONHELPER_H

View File

@@ -23,11 +23,10 @@
*
*/
#ifndef DETUNING_HELPER_H
#define DETUNING_HELPER_H
#ifndef LMMS_DETUNING_HELPER_H
#define LMMS_DETUNING_HELPER_H
#include "InlineAutomation.h"
#include "MemoryManager.h"
namespace lmms
{
@@ -35,7 +34,6 @@ namespace lmms
class DetuningHelper : public InlineAutomation
{
Q_OBJECT
MM_OPERATORS
public:
DetuningHelper() :
InlineAutomation()
@@ -64,4 +62,4 @@ public:
} // namespace lmms
#endif
#endif // LMMS_DETUNING_HELPER_H

View File

@@ -23,9 +23,8 @@
*
*/
#ifndef DRUMSYNTH_H
#define DRUMSYNTH_H
#ifndef LMMS_DRUM_SYNTH_H
#define LMMS_DRUM_SYNTH_H
#include <stdint.h>
#include "lmms_basics.h"
@@ -57,4 +56,4 @@ class DrumSynth {
} // namespace lmms
#endif // DRUMSYNTH_H
#endif // LMMS_DRUM_SYNTH_H

View File

@@ -22,9 +22,8 @@
*
*/
#ifndef DSP_EFFECT_LIBRARY_H
#define DSP_EFFECT_LIBRARY_H
#ifndef LMMS_DSPEFFECTLIBRARY_H
#define LMMS_DSPEFFECTLIBRARY_H
#include "lmms_math.h"
#include "lmms_constants.h"
@@ -188,7 +187,7 @@ namespace lmms::DspEffectLibrary
template<typename sample_t>
inline sample_t saturate( sample_t x )
{
return qMin<sample_t>( qMax<sample_t>( -1.0f, x ), 1.0f );
return std::min<sample_t>(std::max<sample_t>(-1.0f, x), 1.0f);
}
@@ -199,7 +198,7 @@ namespace lmms::DspEffectLibrary
const sample_t _gain,
const sample_t _ratio,
const FastBassBoost & _orig = FastBassBoost() ) :
m_frequency( qMax<sample_t>( _frequency, 10.0 ) ),
m_frequency(std::max<sample_t>(_frequency, 10.0)),
m_gain1( 1.0 / ( m_frequency + 1.0 ) ),
m_gain2( _gain ),
m_ratio( _ratio ),
@@ -331,5 +330,4 @@ namespace lmms::DspEffectLibrary
} // namespace lmms::DspEffectLibrary
#endif
#endif // LMMS_DSPEFFECTLIBRARY_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef DUMMY_EFFECT_H
#define DUMMY_EFFECT_H
#ifndef LMMS_DUMMY_EFFECT_H
#define LMMS_DUMMY_EFFECT_H
#include <QDomElement>
@@ -149,4 +149,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_DUMMY_EFFECT_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef DUMMY_INSTRUMENT_H
#define DUMMY_INSTRUMENT_H
#ifndef LMMS_DUMMY_INSTRUMENT_H
#define LMMS_DUMMY_INSTRUMENT_H
#include "Instrument.h"
#include "InstrumentView.h"
@@ -77,4 +77,4 @@ public:
} // namespace lmms
#endif
#endif // LMMS_DUMMY_INSTRUMENT_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef DUMMY_PLUGIN_H
#define DUMMY_PLUGIN_H
#ifndef LMMS_DUMMY_PLUGIN_H
#define LMMS_DUMMY_PLUGIN_H
#include "Plugin.h"
#include "PluginView.h"
@@ -68,4 +68,4 @@ protected:
} // namespace lmms
#endif
#endif // LMMS_DUMMY_PLUGIN_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef EDITOR_COMMON_H
#define EDITOR_COMMON_H
#ifndef LMMS_GUI_EDITOR_H
#define LMMS_GUI_EDITOR_H
#include <QMainWindow>
#include <QToolBar>
@@ -113,4 +113,4 @@ protected:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_EDITOR_H

View File

@@ -23,15 +23,14 @@
*
*/
#ifndef EFFECT_H
#define EFFECT_H
#ifndef LMMS_EFFECT_H
#define LMMS_EFFECT_H
#include "Plugin.h"
#include "Engine.h"
#include "AudioEngine.h"
#include "AutomatableModel.h"
#include "TempoSyncKnobModel.h"
#include "MemoryManager.h"
namespace lmms
{
@@ -49,7 +48,6 @@ class EffectView;
class LMMS_EXPORT Effect : public Plugin
{
MM_OPERATORS
Q_OBJECT
public:
Effect( const Plugin::Descriptor * _desc,
@@ -157,6 +155,11 @@ public:
{
m_noRun = _state;
}
inline TempoSyncKnobModel* autoQuitModel()
{
return &m_autoQuitModel;
}
EffectChain * effectChain() const
{
@@ -241,4 +244,4 @@ using EffectKeyList = Effect::Descriptor::SubPluginFeatures::KeyList;
} // namespace lmms
#endif
#endif // LMMS_EFFECT_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef EFFECT_CHAIN_H
#define EFFECT_CHAIN_H
#ifndef LMMS_EFFECT_CHAIN_H
#define LMMS_EFFECT_CHAIN_H
#include "Model.h"
#include "SerializingObject.h"
@@ -69,7 +69,7 @@ public:
private:
using EffectList = QVector<Effect*>;
using EffectList = std::vector<Effect*>;
EffectList m_effects;
BoolModel m_enabledModel;
@@ -85,5 +85,4 @@ signals:
} // namespace lmms
#endif
#endif // LMMS_EFFECT_CHAIN_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef EFFECT_CONTROL_DIALOG_H
#define EFFECT_CONTROL_DIALOG_H
#ifndef LMMS_GUI_EFFECT_CONTROL_DIALOG_H
#define LMMS_GUI_EFFECT_CONTROL_DIALOG_H
#include <QWidget>
@@ -64,4 +64,4 @@ protected:
} // namespace lmms
#endif
#endif // LMMS_GUI_EFFECT_CONTROL_DIALOG_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef EFFECT_CONTROLS_H
#define EFFECT_CONTROLS_H
#ifndef LMMS_EFFECT_CONTROLS_H
#define LMMS_EFFECT_CONTROLS_H
#include "Model.h"
#include "JournallingObject.h"
@@ -82,4 +82,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_EFFECT_CONTROLS_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef EFFECT_RACK_VIEW_H
#define EFFECT_RACK_VIEW_H
#ifndef LMMS_GUI_EFFECT_RACK_VIEW_H
#define LMMS_GUI_EFFECT_RACK_VIEW_H
#include <QWidget>
@@ -88,4 +88,4 @@ private:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_EFFECT_RACK_VIEW_H

View File

@@ -2,6 +2,7 @@
* EffectSelectDialog.h - dialog to choose effect plugin
*
* Copyright (c) 2006-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2023 Lost Robot <r94231/at/gmail.com>
*
* This file is part of LMMS - https://lmms.io
*
@@ -22,53 +23,98 @@
*
*/
#ifndef EFFECT_SELECT_DIALOG_H
#define EFFECT_SELECT_DIALOG_H
#include <QDialog>
#include <QSortFilterProxyModel>
#include <QStandardItemModel>
#ifndef LMMS_GUI_EFFECT_SELECT_DIALOG_H
#define LMMS_GUI_EFFECT_SELECT_DIALOG_H
#include "Effect.h"
namespace Ui { class EffectSelectDialog; }
#include <QDialog>
#include <QHeaderView>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QPushButton>
#include <QRegularExpression>
#include <QScrollArea>
#include <QSortFilterProxyModel>
#include <QStandardItemModel>
#include <QTableView>
namespace lmms::gui
{
class DualColumnFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
DualColumnFilterProxyModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent)
{
}
void setEffectTypeFilter(const QString& filter)
{
m_effectTypeFilter = filter;
invalidateFilter();
}
protected:
bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override
{
QModelIndex nameIndex = sourceModel()->index(source_row, 0, source_parent);
QModelIndex typeIndex = sourceModel()->index(source_row, 1, source_parent);
QString name = sourceModel()->data(nameIndex, Qt::DisplayRole).toString();
QString type = sourceModel()->data(typeIndex, Qt::DisplayRole).toString();
// TODO: cleanup once we drop Qt5 support
#if (QT_VERSION >= QT_VERSION_CHECK(5,12,0))
QRegularExpression nameRegularExpression(filterRegularExpression());
nameRegularExpression.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
bool nameFilterPassed = nameRegularExpression.match(name).capturedStart() != -1;
#else
QRegExp nameRegularExpression(filterRegExp());
nameRegularExpression.setCaseSensitivity(Qt::CaseInsensitive);
bool nameFilterPassed = nameRegularExpression.indexIn(name) != -1;
#endif
bool typeFilterPassed = type.contains(m_effectTypeFilter, Qt::CaseInsensitive);
return nameFilterPassed && typeFilterPassed;
}
private:
QString m_effectTypeFilter;
};
class EffectSelectDialog : public QDialog
{
Q_OBJECT
public:
EffectSelectDialog( QWidget * _parent );
~EffectSelectDialog() override;
Effect * instantiateSelectedPlugin( EffectChain * _parent );
EffectSelectDialog(QWidget* parent);
Effect* instantiateSelectedPlugin(EffectChain* parent);
protected slots:
void acceptSelection();
void rowChanged( const QModelIndex &, const QModelIndex & );
void sortAgain();
void rowChanged(const QModelIndex&, const QModelIndex&);
void updateSelection();
bool eventFilter(QObject* obj, QEvent* event) override;
private:
Ui::EffectSelectDialog * ui;
EffectKeyList m_effectKeys;
EffectKey m_currentSelection;
QStandardItemModel m_sourceModel;
QSortFilterProxyModel m_model;
QWidget * m_descriptionWidget;
} ;
DualColumnFilterProxyModel m_model;
QWidget* m_descriptionWidget;
QTableView* m_pluginList;
QScrollArea* m_scrollArea;
QLineEdit* m_filterEdit;
};
} // namespace lmms::gui
#endif

View File

@@ -23,13 +23,14 @@
*
*/
#ifndef EFFECT_VIEW_H
#define EFFECT_VIEW_H
#ifndef LMMS_GUI_EFFECT_VIEW_H
#define LMMS_GUI_EFFECT_VIEW_H
#include "AutomatableModel.h"
#include "PluginView.h"
#include "Effect.h"
class QGraphicsOpacityEffect;
class QGroupBox;
class QLabel;
class QPushButton;
@@ -61,6 +62,11 @@ public:
}
static constexpr int DEFAULT_WIDTH = 215;
static constexpr int DEFAULT_HEIGHT = 60;
void mouseMoveEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
public slots:
void editControls();
@@ -90,10 +96,13 @@ private:
Knob * m_gate;
QMdiSubWindow * m_subWindow;
EffectControlDialog * m_controlView;
bool m_dragging;
QGraphicsOpacityEffect* m_opacityEffect;
} ;
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_EFFECT_VIEW_H

View File

@@ -22,14 +22,12 @@
*
*/
#ifndef ENGINE_H
#define ENGINE_H
#ifndef LMMS_ENGINE_H
#define LMMS_ENGINE_H
#include <QString>
#include <QObject>
#include "lmmsconfig.h"
#include "lmms_export.h"
#include "lmms_basics.h"
@@ -157,5 +155,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_ENGINE_H

View File

@@ -22,10 +22,11 @@
*
*/
#ifndef ENVELOPE_AND_LFO_PARAMETERS_H
#define ENVELOPE_AND_LFO_PARAMETERS_H
#ifndef LMMS_ENVELOPE_AND_LFO_PARAMETERS_H
#define LMMS_ENVELOPE_AND_LFO_PARAMETERS_H
#include <QVector>
#include <memory>
#include <vector>
#include "JournallingObject.h"
#include "AutomatableModel.h"
@@ -70,7 +71,18 @@ public:
using LfoList = QList<EnvelopeAndLfoParameters*>;
LfoList m_lfos;
} ;
};
enum class LfoShape
{
SineWave,
TriangleWave,
SawWave,
SquareWave,
UserDefinedWave,
RandomWave,
Count
};
EnvelopeAndLfoParameters( float _value_for_zero_amount,
Model * _parent );
@@ -113,6 +125,28 @@ public:
return m_rFrames;
}
// Envelope
const FloatModel& getPredelayModel() const { return m_predelayModel; }
const FloatModel& getAttackModel() const { return m_attackModel; }
const FloatModel& getHoldModel() const { return m_holdModel; }
const FloatModel& getDecayModel() const { return m_decayModel; }
const FloatModel& getSustainModel() const { return m_sustainModel; }
const FloatModel& getReleaseModel() const { return m_releaseModel; }
const FloatModel& getAmountModel() const { return m_amountModel; }
FloatModel& getAmountModel() { return m_amountModel; }
// LFO
inline f_cnt_t getLfoPredelayFrames() const { return m_lfoPredelayFrames; }
inline f_cnt_t getLfoAttackFrames() const { return m_lfoAttackFrames; }
inline f_cnt_t getLfoOscillationFrames() const { return m_lfoOscillationFrames; }
const FloatModel& getLfoAmountModel() const { return m_lfoAmountModel; }
FloatModel& getLfoAmountModel() { return m_lfoAmountModel; }
const TempoSyncKnobModel& getLfoSpeedModel() const { return m_lfoSpeedModel; }
const BoolModel& getX100Model() const { return m_x100Model; }
const IntModel& getLfoWaveModel() const { return m_lfoWaveModel; }
std::shared_ptr<const SampleBuffer> getLfoUserWave() const { return m_userWave; }
public slots:
void updateSampleVars();
@@ -167,18 +201,9 @@ private:
sample_t * m_lfoShapeData;
sample_t m_random;
bool m_bad_lfoShapeData;
SampleBuffer m_userWave;
std::shared_ptr<const SampleBuffer> m_userWave = SampleBuffer::emptyBuffer();
enum LfoShapes
{
SineWave,
TriangleWave,
SawWave,
SquareWave,
UserDefinedWave,
RandomWave,
NumLfoShapes
} ;
constexpr static auto NumLfoShapes = static_cast<std::size_t>(LfoShape::Count);
sample_t lfoShapeSample( fpp_t _frame_offset );
void updateLfoShapeData();
@@ -190,4 +215,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_ENVELOPE_AND_LFO_PARAMETERS_H

View File

@@ -23,16 +23,13 @@
*
*/
#ifndef ENVELOPE_AND_LFO_VIEW_H
#define ENVELOPE_AND_LFO_VIEW_H
#ifndef LMMS_GUI_ENVELOPE_AND_LFO_VIEW_H
#define LMMS_GUI_ENVELOPE_AND_LFO_VIEW_H
#include <QWidget>
#include "ModelView.h"
class QPaintEvent;
class QPixmap;
namespace lmms
{
@@ -46,6 +43,8 @@ class Knob;
class LedCheckBox;
class PixmapButton;
class TempoSyncKnob;
class EnvelopeGraph;
class LfoGraph;
@@ -62,8 +61,6 @@ protected:
void dragEnterEvent( QDragEnterEvent * _dee ) override;
void dropEvent( QDropEvent * _de ) override;
void mousePressEvent( QMouseEvent * _me ) override;
void paintEvent( QPaintEvent * _pe ) override;
protected slots:
@@ -71,13 +68,10 @@ protected slots:
private:
static QPixmap * s_envGraph;
static QPixmap * s_lfoGraph;
EnvelopeAndLfoParameters * m_params;
// envelope stuff
EnvelopeGraph* m_envelopeGraph;
Knob * m_predelayKnob;
Knob * m_attackKnob;
Knob * m_holdKnob;
@@ -87,6 +81,7 @@ private:
Knob * m_amountKnob;
// LFO stuff
LfoGraph* m_lfoGraph;
Knob * m_lfoPredelayKnob;
Knob * m_lfoAttackKnob;
TempoSyncKnob * m_lfoSpeedKnob;
@@ -96,12 +91,10 @@ private:
LedCheckBox * m_x100Cb;
LedCheckBox * m_controlEnvAmountCb;
float m_randomGraph;
} ;
} // namespace gui
} // namespace lmms
#endif
#endif // LMMS_GUI_ENVELOPE_AND_LFO_VIEW_H

77
include/EnvelopeGraph.h Normal file
View 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

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef EXPORT_FILTER_H
#define EXPORT_FILTER_H
#ifndef LMMS_EXPORT_FILTER_H
#define LMMS_EXPORT_FILTER_H
#include <QFile>
@@ -69,4 +69,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_EXPORT_FILTER_H

View File

@@ -23,9 +23,8 @@
*
*/
#ifndef EXPORT_PROJECT_DIALOG_H
#define EXPORT_PROJECT_DIALOG_H
#ifndef LMMS_GUI_EXPORT_PROJECT_DIALOG_H
#define LMMS_GUI_EXPORT_PROJECT_DIALOG_H
#include <QDialog>
#include <memory>
@@ -63,12 +62,11 @@ private:
QString m_fileExtension;
bool m_multiExport;
ProjectRenderer::ExportFileFormats m_ft;
ProjectRenderer::ExportFileFormat m_ft;
std::unique_ptr<RenderManager> m_renderManager;
} ;
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_EXPORT_PROJECT_DIALOG_H

View File

@@ -22,9 +22,8 @@
*
*/
#ifndef FADE_BUTTON_H
#define FADE_BUTTON_H
#ifndef LMMS_GUI_FADE_BUTTON_H
#define LMMS_GUI_FADE_BUTTON_H
#include <QAbstractButton>
#include <QColor>
@@ -77,4 +76,4 @@ private:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_FADE_BUTTON_H

View File

@@ -44,9 +44,8 @@
*
*/
#ifndef FADER_H
#define FADER_H
#ifndef LMMS_GUI_FADER_H
#define LMMS_GUI_FADER_H
#include <QElapsedTimer>
#include <QPixmap>
@@ -54,32 +53,35 @@
#include "AutomatableModelView.h"
#include "embed.h"
#include "lmms_math.h"
namespace lmms::gui
{
class TextFloat;
class SimpleTextFloat;
class LMMS_EXPORT Fader : public QWidget, public FloatModelView
{
Q_OBJECT
public:
Q_PROPERTY( QColor peakGreen READ peakGreen WRITE setPeakGreen )
Q_PROPERTY( QColor peakRed READ peakRed WRITE setPeakRed )
Q_PROPERTY( QColor peakYellow READ peakYellow WRITE setPeakYellow )
Q_PROPERTY( bool levelsDisplayedInDBFS READ getLevelsDisplayedInDBFS WRITE setLevelsDisplayedInDBFS )
Q_PROPERTY(QColor peakOk MEMBER m_peakOk)
Q_PROPERTY(QColor peakClip MEMBER m_peakClip)
Q_PROPERTY(QColor peakWarn MEMBER m_peakWarn)
Q_PROPERTY(bool levelsDisplayedInDBFS MEMBER m_levelsDisplayedInDBFS)
Q_PROPERTY(bool renderUnityLine READ getRenderUnityLine WRITE setRenderUnityLine)
Q_PROPERTY(QColor unityMarker MEMBER m_unityMarker)
Fader( FloatModel * _model, const QString & _name, QWidget * _parent );
Fader( FloatModel * _model, const QString & _name, QWidget * _parent, QPixmap * back, QPixmap * leds, QPixmap * knob );
Fader(FloatModel* model, const QString& name, QWidget* parent);
Fader(FloatModel* model, const QString& name, QWidget* parent, const QPixmap& knob);
~Fader() override = default;
void init(FloatModel * model, QString const & name);
void setPeak_L( float fPeak );
void setPeak_L(float fPeak);
float getPeak_L() { return m_fPeakValue_L; }
void setPeak_R( float fPeak );
void setPeak_R(float fPeak);
float getPeak_R() { return m_fPeakValue_R; }
inline float getMinPeak() const { return m_fMinPeak; }
@@ -88,91 +90,74 @@ public:
inline float getMaxPeak() const { return m_fMaxPeak; }
inline void setMaxPeak(float maxPeak) { m_fMaxPeak = maxPeak; }
QColor const & peakGreen() const;
void setPeakGreen( const QColor & c );
inline bool getRenderUnityLine() const { return m_renderUnityLine; }
inline void setRenderUnityLine(bool value = true) { m_renderUnityLine = value; }
QColor const & peakRed() const;
void setPeakRed( const QColor & c );
QColor const & peakYellow() const;
void setPeakYellow( const QColor & c );
inline bool getLevelsDisplayedInDBFS() const { return m_levelsDisplayedInDBFS; }
inline void setLevelsDisplayedInDBFS(bool value = true) { m_levelsDisplayedInDBFS = value; }
void setDisplayConversion( bool b )
void setDisplayConversion(bool b)
{
m_conversionFactor = b ? 100.0 : 1.0;
}
inline void setHintText( const QString & _txt_before,
const QString & _txt_after )
inline void setHintText(const QString& txt_before,
const QString& txt_after)
{
setDescription( _txt_before );
setUnit( _txt_after );
setDescription(txt_before);
setUnit(txt_after);
}
private:
void contextMenuEvent( QContextMenuEvent * _me ) override;
void mousePressEvent( QMouseEvent *ev ) override;
void mouseDoubleClickEvent( QMouseEvent* mouseEvent ) override;
void mouseMoveEvent( QMouseEvent *ev ) override;
void mouseReleaseEvent( QMouseEvent * _me ) override;
void wheelEvent( QWheelEvent *ev ) override;
void paintEvent( QPaintEvent *ev ) override;
void contextMenuEvent(QContextMenuEvent* me) override;
void mousePressEvent(QMouseEvent* ev) override;
void mouseDoubleClickEvent(QMouseEvent* mouseEvent) override;
void mouseMoveEvent(QMouseEvent* ev) override;
void mouseReleaseEvent(QMouseEvent* me) override;
void wheelEvent(QWheelEvent* ev) override;
void paintEvent(QPaintEvent* ev) override;
inline bool clips(float const & value) const { return value >= 1.0f; }
void paintDBFSLevels(QPaintEvent *ev, QPainter & painter);
void paintLinearLevels(QPaintEvent *ev, QPainter & painter);
void paintLevels(QPaintEvent* ev, QPainter& painter, bool linear = false);
int knobPosY() const
{
float fRange = model()->maxValue() - model()->minValue();
float realVal = model()->value() - model()->minValue();
return height() - ( ( height() - m_knob->height() ) * ( realVal / fRange ) );
return height() - ((height() - m_knob.height()) * (realVal / fRange));
}
void setPeak( float fPeak, float &targetPeak, float &persistentPeak, QElapsedTimer &lastPeakTimer );
int calculateDisplayPeak( float fPeak );
void setPeak(float fPeak, float& targetPeak, float& persistentPeak, QElapsedTimer& lastPeakTimer);
void updateTextFloat();
// Private members
private:
float m_fPeakValue_L;
float m_fPeakValue_R;
float m_persistentPeak_L;
float m_persistentPeak_R;
float m_fMinPeak;
float m_fMaxPeak;
float m_fPeakValue_L {0.};
float m_fPeakValue_R {0.};
float m_persistentPeak_L {0.};
float m_persistentPeak_R {0.};
float m_fMinPeak {dbfsToAmp(-42)};
float m_fMaxPeak {dbfsToAmp(9)};
QElapsedTimer m_lastPeakTimer_L;
QElapsedTimer m_lastPeakTimer_R;
static QPixmap * s_back;
static QPixmap * s_leds;
static QPixmap * s_knob;
QPixmap * m_back;
QPixmap * m_leds;
QPixmap * m_knob;
QPixmap m_knob {embed::getIconPixmap("fader_knob")};
bool m_levelsDisplayedInDBFS;
bool m_levelsDisplayedInDBFS {true};
int m_moveStartPoint;
float m_startValue;
int m_moveStartPoint {-1};
float m_startValue {0.};
static TextFloat * s_textFloat;
static SimpleTextFloat* s_textFloat;
QColor m_peakGreen;
QColor m_peakRed;
QColor m_peakYellow;
QColor m_peakOk {10, 212, 92};
QColor m_peakClip {193, 32, 56};
QColor m_peakWarn {214, 236, 82};
QColor m_unityMarker {63, 63, 63, 255};
bool m_renderUnityLine {true};
} ;
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_FADER_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef FIFO_BUFFER_H
#define FIFO_BUFFER_H
#ifndef LMMS_FIFO_BUFFER_H
#define LMMS_FIFO_BUFFER_H
#include <QSemaphore>
@@ -94,4 +94,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_FIFO_BUFFER_H

View File

@@ -22,21 +22,24 @@
*
*/
#ifndef FILE_BROWSER_H
#define FILE_BROWSER_H
#ifndef LMMS_GUI_FILE_BROWSER_H
#define LMMS_GUI_FILE_BROWSER_H
#include <QCheckBox>
#include <QDir>
#include <QMutex>
#include "embed.h"
#include "FileBrowserSearcher.h"
#include <QProgressBar>
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
#include <QRecursiveMutex>
#endif
#include <QTreeWidget>
#include "SideBarWidget.h"
#include "lmmsconfig.h"
class QLineEdit;
@@ -67,17 +70,31 @@ public:
*/
FileBrowser( const QString & directories, const QString & filter,
const QString & title, const QPixmap & pm,
QWidget * parent, bool dirs_as_items = false, bool recurse = false,
QWidget * parent, bool dirs_as_items = false,
const QString& userDir = "",
const QString& factoryDir = "");
~FileBrowser() override = default;
static QStringList directoryBlacklist()
{
static auto s_blacklist = QStringList{
#ifdef LMMS_BUILD_LINUX
"/bin", "/boot", "/dev", "/etc", "/proc", "/run", "/sbin",
"/sys"
#endif
#ifdef LMMS_BUILD_WIN32
"C:\\Windows"
#endif
};
return s_blacklist;
}
static QDir::Filters dirFilters() { return QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot; }
static QDir::SortFlags sortFlags() { return QDir::LocaleAware | QDir::DirsFirst | QDir::Name | QDir::IgnoreCase; }
private slots:
void reloadTree();
void expandItems( QTreeWidgetItem * item=nullptr, QList<QString> expandedDirs = QList<QString>() );
// call with item=NULL to filter the entire tree
bool filterItems( const QString & filter, QTreeWidgetItem * item=nullptr );
void expandItems(const QList<QString>& expandedDirs, QTreeWidgetItem* item = nullptr);
void giveFocusToFilter();
private:
@@ -85,21 +102,33 @@ private:
void addItems( const QString & path );
void saveDirectoriesStates();
void restoreDirectoriesStates();
void buildSearchTree();
void onSearch(const QString& filter);
void toggleSearch(bool on);
FileBrowserTreeWidget * m_fileBrowserTreeWidget;
FileBrowserTreeWidget * m_searchTreeWidget;
QLineEdit * m_filterEdit;
std::shared_ptr<FileBrowserSearcher::SearchFuture> m_currentSearch;
QProgressBar* m_searchIndicator = nullptr;
QString m_directories; //!< Directories to search, split with '*'
QString m_filter; //!< Filter as used in QDir::match()
bool m_dirsAsItems;
bool m_recurse;
void addContentCheckBox();
QCheckBox* m_showUserContent = nullptr;
QCheckBox* m_showFactoryContent = nullptr;
QString m_userDir;
QString m_factoryDir;
QList<QString> m_savedExpandedDirs;
QString m_previousFilterValue;
} ;
@@ -116,7 +145,6 @@ public:
//! that are expanded in the tree.
QList<QString> expandedDirs( QTreeWidgetItem * item = nullptr ) const;
protected:
void contextMenuEvent( QContextMenuEvent * e ) override;
void mousePressEvent( QMouseEvent * me ) override;
@@ -165,12 +193,10 @@ private slots:
class Directory : public QTreeWidgetItem
{
public:
Directory( const QString & filename, const QString & path,
const QString & filter );
Directory(const QString& filename, const QString& path, const QString& filter, bool disableEntryPopulation = false);
void update();
@@ -195,14 +221,12 @@ public:
private:
void initPixmaps();
bool addItems( const QString & path );
static QPixmap * s_folderPixmap;
static QPixmap * s_folderOpenedPixmap;
static QPixmap * s_folderLockedPixmap;
QPixmap m_folderPixmap = embed::getIconPixmap("folder");
QPixmap m_folderOpenedPixmap = embed::getIconPixmap("folder_opened");
QPixmap m_folderLockedPixmap = embed::getIconPixmap("folder_locked");
//! Directories that lead here
//! Initially, this is just set to the current path of a directory
@@ -215,7 +239,7 @@ private:
QString m_filter;
int m_dirCount;
bool m_disableEntryPopulation = false;
} ;
@@ -224,20 +248,19 @@ private:
class FileItem : public QTreeWidgetItem
{
public:
enum FileTypes
enum class FileType
{
ProjectFile,
PresetFile,
SampleFile,
SoundFontFile,
PatchFile,
MidiFile,
VstPluginFile,
UnknownFile,
NumFileTypes
Project,
Preset,
Sample,
SoundFont,
Patch,
Midi,
VstPlugin,
Unknown
} ;
enum FileHandling
enum class FileHandling
{
NotSupported,
LoadAsProject,
@@ -256,7 +279,7 @@ public:
return QFileInfo(m_path, text(0)).absoluteFilePath();
}
inline FileTypes type() const
inline FileType type() const
{
return( m_type );
}
@@ -268,27 +291,20 @@ public:
inline bool isTrack() const
{
return m_handling == LoadAsPreset || m_handling == LoadByPlugin;
return m_handling == FileHandling::LoadAsPreset || m_handling == FileHandling::LoadByPlugin;
}
QString extension();
static QString extension( const QString & file );
static QString defaultFilters();
private:
void initPixmaps();
void determineFileType();
static QPixmap * s_projectFilePixmap;
static QPixmap * s_presetFilePixmap;
static QPixmap * s_sampleFilePixmap;
static QPixmap * s_soundfontFilePixmap;
static QPixmap * s_vstPluginFilePixmap;
static QPixmap * s_midiFilePixmap;
static QPixmap * s_unknownFilePixmap;
QString m_path;
FileTypes m_type;
FileType m_type;
FileHandling m_handling;
} ;
@@ -298,4 +314,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_GUI_FILE_BROWSER_H

View File

@@ -0,0 +1,148 @@
/*
* FileBrowserSearcher.h - Batch processor for searching the filesystem
*
* Copyright (c) 2023 saker <sakertooth@gmail.com>
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef LMMS_FILE_BROWSER_SEARCHER_H
#define LMMS_FILE_BROWSER_SEARCHER_H
#include <QHash>
#include <QString>
#include <QStringList>
#include <optional>
#include <queue>
#ifdef __MINGW32__
#include <mingw.condition_variable.h>
#include <mingw.mutex.h>
#include <mingw.thread.h>
#else
#include <condition_variable>
#include <mutex>
#include <thread>
#endif
namespace lmms::gui {
//! An active object that handles searching for files that match a certain filter across the file system.
class FileBrowserSearcher
{
public:
//! Number of milliseconds to wait for before a match should be processed by the user.
static constexpr int MillisecondsPerMatch = 1;
//! The future object for FileBrowserSearcher. It is used to track the current state of search operations, as
// well as retrieve matches.
class SearchFuture
{
public:
//! Possible state values of the future object.
enum class State
{
Idle,
Running,
Cancelled,
Completed
};
//! Constructs a future object using the specified filter, paths, and valid file extensions in the Idle state.
SearchFuture(const QString& filter, const QStringList& paths, const QStringList& extensions)
: m_filter(filter)
, m_paths(paths)
, m_extensions(extensions)
{
}
//! Retrieves a match from the match list.
auto match() -> QString
{
const auto lock = std::lock_guard{m_matchesMutex};
return m_matches.empty() ? QString{} : m_matches.takeFirst();
}
//! Returns the current state of this future object.
auto state() -> State { return m_state; }
//! Returns the filter used.
auto filter() -> const QString& { return m_filter; }
//! Returns the paths to filter.
auto paths() -> const QStringList& { return m_paths; }
//! Returns the valid file extensions.
auto extensions() -> const QStringList& { return m_extensions; }
private:
//! Adds a match to the match list.
auto addMatch(const QString& match) -> void
{
const auto lock = std::lock_guard{m_matchesMutex};
m_matches.append(match);
}
QString m_filter;
QStringList m_paths;
QStringList m_extensions;
QStringList m_matches;
std::mutex m_matchesMutex;
std::atomic<State> m_state = State::Idle;
friend FileBrowserSearcher;
};
~FileBrowserSearcher();
//! Enqueues a search to be ran by the worker thread.
//! Returns a future that the caller can use to track state and results of the operation.
auto search(const QString& filter, const QStringList& paths, const QStringList& extensions)
-> std::shared_ptr<SearchFuture>;
//! Sends a signal to cancel a running search.
auto cancel() -> void { m_cancelRunningSearch = true; }
//! Returns the global instance of the searcher object.
static auto instance() -> FileBrowserSearcher*
{
static auto s_instance = FileBrowserSearcher{};
return &s_instance;
}
private:
//! Event loop for the worker thread.
auto run() -> void;
//! Using Depth-first search (DFS), filters the specified path and adds any matches to the future list.
auto process(SearchFuture* searchFuture, const QString& path) -> bool;
std::queue<std::shared_ptr<SearchFuture>> m_searchQueue;
std::atomic<bool> m_cancelRunningSearch = false;
bool m_workerStopped = false;
std::mutex m_workerMutex;
std::condition_variable m_workerCond;
std::thread m_worker{[this] { run(); }};
};
} // namespace lmms::gui
#endif // LMMS_FILE_BROWSER_SEARCHER_H

View File

@@ -22,9 +22,8 @@
*
*/
#ifndef FILEDIALOG_H
#define FILEDIALOG_H
#ifndef LMMS_GUI_FILE_DIALOG_H
#define LMMS_GUI_FILE_DIALOG_H
#include <QFileDialog>
@@ -57,4 +56,4 @@ public:
} // namespace lmms::gui
#endif // FILEDIALOG_H
#endif // LMMS_GUI_FILE_DIALOG_H

83
include/Flags.h Normal file
View 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

View 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

View File

@@ -23,9 +23,8 @@
*
*/
#ifndef GRAPH_H
#define GRAPH_H
#ifndef LMMS_GUI_GRAPH_H
#define LMMS_GUI_GRAPH_H
#include <QWidget>
#include <QPixmap>
@@ -49,13 +48,12 @@ class LMMS_EXPORT Graph : public QWidget, public ModelView
{
Q_OBJECT
public:
enum graphStyle
enum class Style
{
NearestStyle, //!< draw as stairs
LinearStyle, //!< connect each 2 samples with a line, with wrapping
LinearNonCyclicStyle, //!< LinearStyle without wrapping
BarStyle, //!< draw thick bars
NumGraphStyles
Nearest, //!< draw as stairs
Linear, //!< connect each 2 samples with a line, with wrapping
LinearNonCyclic, //!< Linear without wrapping
Bar, //!< draw thick bars
};
/**
@@ -63,7 +61,7 @@ public:
* @param _width Pixel width of widget
* @param _height Pixel height of widget
*/
Graph( QWidget * _parent, graphStyle _style = Graph::LinearStyle,
Graph( QWidget * _parent, Style _style = Style::Linear,
int _width = 132,
int _height = 104
);
@@ -79,13 +77,13 @@ public:
return castModel<graphModel>();
}
inline graphStyle getGraphStyle()
inline Style getGraphStyle()
{
return m_graphStyle;
}
inline void setGraphStyle( graphStyle _s )
inline void setGraphStyle( Style _s )
{
m_graphStyle = _s;
update();
@@ -115,7 +113,7 @@ private:
QPixmap m_foreground;
QColor m_graphColor;
graphStyle m_graphStyle;
Style m_graphStyle;
bool m_mouseDown;
int m_lastCursorX;
@@ -228,4 +226,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_GUI_GRAPH_H

View File

@@ -22,9 +22,8 @@
*
*/
#ifndef GROUP_BOX_H
#define GROUP_BOX_H
#ifndef LMMS_GUI_GROUP_BOX_H
#define LMMS_GUI_GROUP_BOX_H
#include <QWidget>
@@ -51,6 +50,21 @@ public:
return m_led;
}
/**
* @brief Returns whether the LED button is shown or not
*
* @return true LED button is shown
* @return false LED button is hidden
*/
bool ledButtonShown() const;
/**
* @brief Sets if the LED check box is shown or not
*
* @param value Set to true to show the LED check box or to false to hide it.
*/
void setLedButtonShown(bool value);
int titleBarHeight() const
{
return m_titleBarHeight;
@@ -74,5 +88,4 @@ private:
} // namespace lmms::gui
#endif
#endif // LMMS_GUI_GROUP_BOX_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef GUIAPPLICATION_H
#define GUIAPPLICATION_H
#ifndef LMMS_GUI_GUI_APPLICATION_H
#define LMMS_GUI_GUI_APPLICATION_H
#include <QObject>
@@ -96,4 +96,4 @@ LMMS_EXPORT GuiApplication* getGUI();
} // namespace lmms::gui
#endif // GUIAPPLICATION_H
#endif // LMMS_GUI_GUI_APPLICATION_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef IMPORT_FILTER_H
#define IMPORT_FILTER_H
#ifndef LMMS_IMPORT_FILTER_H
#define LMMS_IMPORT_FILTER_H
#include <QFile>
@@ -114,4 +114,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_IMPORT_FILTER_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef INLINE_AUTOMATION_H
#define INLINE_AUTOMATION_H
#ifndef LMMS_INLINE_AUTOMATION_H
#define LMMS_INLINE_AUTOMATION_H
#include "AutomationNode.h"
#include "AutomationClip.h"
@@ -99,4 +99,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_INLINE_AUTOMATION_H

View File

@@ -23,13 +23,14 @@
*
*/
#ifndef INSTRUMENT_H
#define INSTRUMENT_H
#ifndef LMMS_INSTRUMENT_H
#define LMMS_INSTRUMENT_H
#include <QString>
#include "Flags.h"
#include "lmms_export.h"
#include "lmms_basics.h"
#include "MemoryManager.h"
#include "Plugin.h"
#include "TimePos.h"
@@ -45,9 +46,8 @@ class Track;
class LMMS_EXPORT Instrument : public Plugin
{
MM_OPERATORS
public:
enum Flag
enum class Flag
{
NoFlags = 0x00,
IsSingleStreamed = 0x01, /*! Instrument provides a single audio stream for all notes */
@@ -55,7 +55,7 @@ public:
IsNotBendable = 0x04, /*! Instrument can't react to pitch bend changes */
};
Q_DECLARE_FLAGS(Flags, Flag);
using Flags = lmms::Flags<Flag>;
Instrument(InstrumentTrack * _instrument_track,
const Descriptor * _descriptor,
@@ -102,7 +102,7 @@ public:
virtual Flags flags() const
{
return NoFlags;
return Flag::NoFlags;
}
// sub-classes can re-implement this for receiving all incoming
@@ -149,9 +149,9 @@ private:
} ;
Q_DECLARE_OPERATORS_FOR_FLAGS(Instrument::Flags)
LMMS_DECLARE_OPERATORS_FOR_FLAGS(Instrument::Flag)
} // namespace lmms
#endif
#endif // LMMS_INSTRUMENT_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef INSTRUMENT_FUNCTION_VIEWS_H
#define INSTRUMENT_FUNCTION_VIEWS_H
#ifndef LMMS_INSTRUMENT_FUNCTION_VIEWS_H
#define LMMS_INSTRUMENT_FUNCTION_VIEWS_H
#include "ModelView.h"
@@ -99,4 +99,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_INSTRUMENT_FUNCTION_VIEWS_H

View File

@@ -22,8 +22,8 @@
*
*/
#ifndef INSTRUMENT_FUNCTIONS_H
#define INSTRUMENT_FUNCTIONS_H
#ifndef LMMS_INSTRUMENT_FUNCTIONS_H
#define LMMS_INSTRUMENT_FUNCTIONS_H
#include "JournallingObject.h"
#include "lmms_basics.h"
@@ -119,7 +119,7 @@ public:
};
struct ChordTable : public QVector<Chord>
struct ChordTable
{
private:
ChordTable();
@@ -131,6 +131,7 @@ public:
};
static std::array<Init, NUM_CHORD_TABLES> s_initTable;
std::vector<Chord> m_chords;
public:
static const ChordTable & getInstance()
@@ -150,6 +151,11 @@ public:
{
return getByName( name, false );
}
const std::vector<Chord>& chords() const
{
return m_chords;
}
};
@@ -170,14 +176,13 @@ class InstrumentFunctionArpeggio : public Model, public JournallingObject
{
Q_OBJECT
public:
enum ArpDirections
enum class ArpDirection
{
ArpDirUp,
ArpDirDown,
ArpDirUpAndDown,
ArpDirDownAndUp,
ArpDirRandom,
NumArpDirections
Up,
Down,
UpAndDown,
DownAndUp,
Random
} ;
InstrumentFunctionArpeggio( Model * _parent );
@@ -196,11 +201,11 @@ public:
private:
enum ArpModes
enum class ArpMode
{
FreeMode,
SortMode,
SyncMode
Free,
Sort,
Sync
} ;
BoolModel m_arpEnabledModel;
@@ -224,4 +229,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_INSTRUMENT_FUNCTIONS_H

View File

@@ -23,8 +23,8 @@
*
*/
#ifndef INSTRUMENT_MIDI_IO_VIEW_H
#define INSTRUMENT_MIDI_IO_VIEW_H
#ifndef LMMS_GUI_INSTRUMENT_MIDI_IO_VIEW_H
#define LMMS_GUI_INSTRUMENT_MIDI_IO_VIEW_H
#include <QWidget>
@@ -76,4 +76,4 @@ private:
} // namespace lmms
#endif
#endif // LMMS_GUI_INSTRUMENT_MIDI_IO_VIEW_H

View File

@@ -22,67 +22,38 @@
*
*/
#ifndef INSTRUMENT_PLAY_HANDLE_H
#define INSTRUMENT_PLAY_HANDLE_H
#ifndef LMMS_INSTRUMENT_PLAY_HANDLE_H
#define LMMS_INSTRUMENT_PLAY_HANDLE_H
#include "PlayHandle.h"
#include "Instrument.h"
#include "NotePlayHandle.h"
#include "lmms_export.h"
namespace lmms
{
class Instrument;
class InstrumentTrack;
class LMMS_EXPORT InstrumentPlayHandle : public PlayHandle
{
public:
InstrumentPlayHandle( Instrument * instrument, InstrumentTrack* instrumentTrack );
InstrumentPlayHandle(Instrument * instrument, InstrumentTrack* instrumentTrack);
~InstrumentPlayHandle() override = default;
void play( sampleFrame * _working_buffer ) override
{
// ensure that all our nph's have been processed first
ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack( m_instrument->instrumentTrack(), true );
bool nphsLeft;
do
{
nphsLeft = false;
for( const NotePlayHandle * constNotePlayHandle : nphv )
{
NotePlayHandle * notePlayHandle = const_cast<NotePlayHandle *>( constNotePlayHandle );
if( notePlayHandle->state() != ThreadableJob::ProcessingState::Done &&
!notePlayHandle->isFinished())
{
nphsLeft = true;
notePlayHandle->process();
}
}
}
while( nphsLeft );
m_instrument->play( _working_buffer );
}
void play(sampleFrame * working_buffer) override;
bool isFinished() const override
{
return false;
}
bool isFromTrack( const Track* _track ) const override
{
return m_instrument->isFromTrack( _track );
}
bool isFromTrack(const Track* track) const override;
private:
Instrument* m_instrument;
} ;
};
} // namespace lmms
#endif
#endif // LMMS_INSTRUMENT_PLAY_HANDLE_H

Some files were not shown because too many files have changed in this diff Show More