Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved Waveshaper / Spline-based graph replacement #4367

Open
wants to merge 52 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
578415a
Create copy of original waveshaper
josh-audio May 18, 2018
e99b4ec
Merge branch 'master' into waveshaper2
josh-audio May 22, 2018
2f9bc3e
Begin VectorGraph class
josh-audio May 23, 2018
ae58cf7
Begin adding model
josh-audio May 23, 2018
c0a2ef8
Basic data storage and rendering
josh-audio May 24, 2018
a3a062a
Initial revision of drawing code
josh-audio May 24, 2018
b851c69
Create points with right click
josh-audio May 24, 2018
ba67f4f
Move newly created points before releasing right click
josh-audio May 25, 2018
8de2637
Points cannot be moved above 1 or below 0
josh-audio May 25, 2018
4c60044
Make points movable
josh-audio May 25, 2018
ba5069f
Add tension handles
josh-audio May 25, 2018
e47df2a
Add locking to points
josh-audio May 25, 2018
9a2a8f8
Editible tension points
josh-audio May 26, 2018
caa6039
Fix mouse tracking bug
josh-audio May 26, 2018
c3104b3
Hook up DSP
josh-audio May 28, 2018
fa7a784
Various tension tweaks
josh-audio May 28, 2018
44ea721
Allow points to be deleted via right click
josh-audio May 29, 2018
36f1691
Prevent a point and a tension handle from being manipulated simultane…
josh-audio May 29, 2018
e6c217a
Fix warnings
josh-audio May 29, 2018
e6a3464
Change curve to be based on a cycloid instead of a parabola
josh-audio May 30, 2018
43b61db
spaces -> tabs
josh-audio May 30, 2018
a2f9fd1
Points that are completely locked cannot be targeted for drag
josh-audio May 30, 2018
a02372c
Make handles more grabbable
josh-audio May 30, 2018
8b59d77
Reset tension on handle right click
josh-audio May 30, 2018
5a32215
Make mouse move to end point on tension move
josh-audio May 30, 2018
9a14ee8
Fix handles sometimes drawing a pixel above where they should
josh-audio May 30, 2018
5f729a1
Fix issue where lines weren't drawing between points sometimes
josh-audio May 30, 2018
39adedd
Partially fix tension handles on vertical lines
josh-audio May 30, 2018
852ee61
Allow curve types to be changed, implement stairs and hold types
josh-audio May 31, 2018
f5e2db9
Fix line sometimes not drawing all the way to the last point
josh-audio May 31, 2018
6c1c3e7
Remember last curve adjustment for new point creation
josh-audio May 31, 2018
98e1b62
Tweaks and improvements to the stairs curve type
josh-audio Jun 1, 2018
57d339d
Add pulse curve type
josh-audio Jun 1, 2018
3f5abf7
Add double curve type
josh-audio Jun 1, 2018
10d681d
Add wave tension type
josh-audio Jun 2, 2018
811370b
Fix some tension handles drawing inconsistently
josh-audio Jun 2, 2018
4010a34
Don't draw tension handle on hold
josh-audio Jun 2, 2018
8ff2214
Prevent first and last points from being deleted
josh-audio Jun 2, 2018
2be53e9
Reset last remembered tension on right click
josh-audio Jun 2, 2018
6dde7e6
Color ui based on work by @budislav
josh-audio Jun 3, 2018
01d99d1
Remove unnecessary buttons
josh-audio Jun 3, 2018
823e8f9
Apparently removing those pictures was a bad idea
josh-audio Jun 3, 2018
5a342fc
Clean up
josh-audio Jun 4, 2018
a84fd70
Enable snap to grid when alt is pressed
josh-audio Jun 5, 2018
6d202ad
Warning fixed I think
josh-audio Jun 5, 2018
a650529
How about now
josh-audio Jun 5, 2018
234dd95
Merge branch 'master' into waveshaper2
PhysSong Dec 22, 2022
3ed3520
Rename to WaveShaper2 and fix merge errors
PhysSong Dec 22, 2022
31fb248
VectorGraph: don't try to hide and fix cursors
PhysSong Dec 22, 2022
d7141c0
Fix a double free of VectorGraphModel
PhysSong Dec 22, 2022
970ce05
Revert submodule changes
PhysSong Jan 1, 2023
56dc975
Partially address review comments
PhysSong Jan 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
302 changes: 302 additions & 0 deletions include/VectorGraph.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
/*
* VectorGraph.h - vector-based replacement for Graph.h
*
* Copyright (c) 2018 Joshua Wade
*
* 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 VECTORGRAPH_H
#define VECTORGRAPH_H

#include <QWidget>
#include <QPainter>
#include <QVector>
#include <QtMath>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Standard C++ math functions look better than Qt math functions.


#include "ModelView.h"

class VectorGraphModel;
class VectorGraphPoint;




class EXPORT VectorGraph : public QWidget, public ModelView
{
Q_OBJECT
public:
VectorGraph( QWidget * _parent, int _width, int _height );
virtual ~VectorGraph() = default;

inline void setResolution(int resolution)
{
m_resolution = resolution;
}

inline VectorGraphModel * model()
{
return castModel<VectorGraphModel>();
}

inline int getWidth()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider not using get prefix unless the meaning is ambiguous without it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be confused with QWidget::width(), so I think we should check if we really need this.

{
return m_width;
}

inline int getHeight()
{
return m_height;
}

float calculateSample(float input);
bool eventFilter(QObject *watched, QEvent *event);

signals:
void drawn();
protected:
void paintEvent( QPaintEvent * event ) override;
void mousePressEvent( QMouseEvent * event );
void mouseMoveEvent( QMouseEvent * event );
void mouseReleaseEvent( QMouseEvent * event );

private slots:
void deletePoint();

private:
QPainter m_canvas;
int m_resolution;
int m_width;
int m_height;
int m_currentPoint;
};



class EXPORT VectorGraphModel : public Model
{
Q_OBJECT
public:
VectorGraphModel(Model *_parent, bool _default_constructed);
virtual ~VectorGraphModel() = default;

inline void setPoints(QVector<VectorGraphPoint> points)
{
m_points = points;
}

inline int getPointCount()
{
return m_points.size();
}

inline void setCurrentDraggedPoint(int index)
{
m_currentDraggedPoint = index;
}

inline void resetCurrentDraggedPoint()
{
m_currentDraggedPoint = -1;
}

inline int getCurrentDraggedPoint()
{
return m_currentDraggedPoint;
}

inline void setCurrentDraggedTensionHandle(int index)
{
m_currentDraggedTensionHandle = index;
}

inline void resetCurrentDraggedTensionHandle()
{
m_currentDraggedTensionHandle = -1;
}

inline int getCurrentDraggedTensionHandle()
{
return m_currentDraggedTensionHandle;
}

inline QPoint getStoredCursorPos()
{
return m_storedCursorPos;
}

inline void setStoredCursorPos(QPoint point)
{
m_storedCursorPos = point;
}

VectorGraphPoint * getPoint(int index);
float calculateSample(float input);
float calculateSectionSample(float input, int sectionStartIndex);
int getSectionStartIndex(float input);
void insertPointAfter(int index, VectorGraphPoint point);
void tryMove(int index, float x, float y);
int getPointIndexFromCoords(int x, int y, int canvasWidth, int canvasHeight);
int getPointIndexFromTensionHandleCoords(int x, int y, int canvasWidth, int canvasHeight);
void deletePoint(int index);


const inline int getPointSize()
{
return 5;
}
const inline int getTensionHandleSize()
{
return 3;
}

private:
QVector<VectorGraphPoint> m_points;
int m_currentDraggedPoint;
int m_currentDraggedTensionHandle;
QPoint m_storedCursorPos;
static inline bool floatEqual(float a, float b, float epsilon)
{
return qFabs(a - b) < epsilon;
}

static inline bool arePointsWithinDistance(float x1, float x2, float y1, float y2, float distance)
{
//return qPow(x2 - x1, 2) + qPow(y2 - y1, 2) <= qPow(distance, 2);
qreal aSquared = qPow(x2 - x1, 2);
qreal bSquared = qPow(y2 - y1, 2);
qreal cSquared = qPow(distance, 2);
bool result = aSquared + bSquared <= cSquared;
return result;
}
};



class VectorGraphPoint
{
public:
enum TensionType
{
SingleCurve
};

VectorGraphPoint(float x, float y, float tension, TensionType type);
VectorGraphPoint();
inline float x()
{
return m_x;
}
inline float y()
{
return m_y;
}
inline void setX(float x)
{
m_x = x;
}
inline void setY(float y)
{
m_y = y;
}
inline float tension()
{
return m_tension;
}
inline TensionType tensionType()
{
return m_tensionType;
}
inline float tensionPower()
{
return m_tensionPower;
}
inline float absTensionPower()
{
return m_absTensionPower;
}
inline float dryAmt()
{
return m_dryAmt;
}
inline void setTension(float tension)
{
m_tension = tension;

// Variables for single curve
m_tensionPower = qPow(10, -1 * tension);
m_absTensionPower = qPow(10, qAbs(tension));

m_dryAmt = 0.2 * qPow(1 - qAbs(tension), 3);
}
inline void lockX()
{
m_isXLocked = true;
}
inline void lockY()
{
m_isYLocked = true;
}
inline void permaLockX()
{
m_isXPermaLocked = true;
}
inline void permaLockY()
{
m_isYPermaLocked = true;
}
inline void unlockX()
{
m_isXLocked = false;
}
inline void unlockY()
{
m_isYLocked = false;
}
inline void permaUnlockX()
{
m_isXPermaLocked = false;
}
inline void permaUnlockY()
{
m_isYPermaLocked = false;
}
inline bool isXLocked()
{
return m_isXLocked || m_isXPermaLocked;
}
inline bool isYLocked()
{
return m_isYLocked || m_isYPermaLocked;
}
private:
float m_x;
float m_y;
float m_tension;
float m_tensionPower;
float m_absTensionPower;
float m_dryAmt;
TensionType m_tensionType;
bool m_isXLocked;
bool m_isYLocked;
bool m_isXPermaLocked;
bool m_isYPermaLocked;
};

#endif
1 change: 1 addition & 0 deletions plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ IF("${PLUGIN_LIST}" STREQUAL "")
VstEffect
watsyn
waveshaper
waveshaper2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor, but use tabs instead of spaces.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do, I edited that with a different editor. Thanks for catching this.

vibed
Xpressive
zynaddsubfx
Expand Down
2 changes: 1 addition & 1 deletion plugins/LadspaEffect/calf/veal
3 changes: 3 additions & 0 deletions plugins/waveshaper2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
INCLUDE(BuildPlugin)

BUILD_PLUGIN(waveshaper2 waveshaper2.cpp waveshaper2_controls.cpp waveshaper2_control_dialog.cpp MOCFILES waveshaper2_controls.h waveshaper2_control_dialog.h EMBEDDED_RESOURCES *.png)
Binary file added plugins/waveshaper2/add1_active.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/waveshaper2/add1_inactive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/waveshaper2/artwork.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/waveshaper2/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/waveshaper2/reset_active.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/waveshaper2/reset_inactive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/waveshaper2/smooth_active.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/waveshaper2/smooth_inactive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/waveshaper2/sub1_active.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/waveshaper2/sub1_inactive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/waveshaper2/wavegraph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading