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

Sample editor instant feedback #1314

Open
wants to merge 3 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
6 changes: 3 additions & 3 deletions src/core/Basics/Sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ namespace H2Core
{

const char* Sample::__class_name = "Sample";
const char* EnvelopePoint::__class_name = "EnvolopePoint";
const char* EnvelopePoint::__class_name = "EnvelopePoint";

const std::vector<QString> Sample::__loop_modes = { "forward", "reverse", "pingpong" };

Expand All @@ -51,11 +51,11 @@ static RubberBand::RubberBandStretcher::Options compute_rubberband_options( cons


/* EnvelopePoint */
EnvelopePoint::EnvelopePoint() : Object( EnvelopePoint::__class_name ), frame( 0 ), value( 0 )
Copy link
Contributor

Choose a reason for hiding this comment

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

How come you removed the H2Core::Object in here? It's used for debugging and shouldn't add too much weight.

Copy link
Contributor Author

@charbeljc charbeljc Jul 7, 2021

Choose a reason for hiding this comment

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

How come you removed the H2Core::Object in here? It's used for debugging and shouldn't add too much weight.

Hum, I was maybe a bit to quick with this. I think EnvelopePoint should go away in favor of a proper Envelope class.
Besides, I have a pending patch which removes the H2Core::Object's overhead...

My point was to get rid of the unique_ptr around EnvelopePoint in envelope, so I can access them from python. I don't remember the details right now, but pybind11 caused me some troubles with those std::shared_ptr<std::unique_ptr> ...

ihmo, EnvelopePoints should be plain dummy structs with copy semantics, and let the (to be written) Envelope let deal with them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @theGreatWhiteShark I just restored EnvelopePoint inheritance of H2Core::Object.
Regards

Copy link
Contributor

Choose a reason for hiding this comment

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

I think EnvelopePoint should go away in favor of a proper Envelope class.
Besides, I have a pending patch which removes the H2Core::Object's overhead...

Could you split off these changes and make a separate PR? Such fundamental changes in the code base require the consent of at least a majority of all maintainers. This will happen much faster if it's a concise one.

One thing to think about in advance (and I haven't done yet, so, there is a chance none of this makes sense): The envelope in the sample editor is quite similar to the automation path. Maybe there could be a common basis.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think EnvelopePoint should go away in favor of a proper Envelope class.
Besides, I have a pending patch which removes the H2Core::Object's overhead...

Could you split off these changes and make a separate PR? Such fundamental changes in the code base require the consent of at least a majority of all maintainers. This will happen much faster if it's a concise one.

Yes, I will do a separate PR on this.

One thing to think about in advance (and I haven't done yet, so, there is a chance none of this makes sense): The envelope in the sample editor is quite similar to the automation path. Maybe there could be a common basis.

I will have a look at those automation path. If we could factor out some code, it would be nice.

Copy link
Contributor Author

@charbeljc charbeljc Jul 9, 2021

Choose a reason for hiding this comment

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

Please see #1318 and #1319 (this one is extracted from #1313)

EnvelopePoint::EnvelopePoint() : Object( EnvelopePoint::__class_name ), frame( 0 ), value( 0 )
{
}

EnvelopePoint::EnvelopePoint( int f, int v ) : Object( EnvelopePoint::__class_name ), frame( f ), value( v )
EnvelopePoint::EnvelopePoint( int f, int v ) : Object ( EnvelopePoint::__class_name), frame( f ), value( v )
{
}

Expand Down
183 changes: 92 additions & 91 deletions src/gui/src/SampleEditor/MainSampleWaveDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,8 @@ MainSampleWaveDisplay::MainSampleWaveDisplay(QWidget* pParent)
m_bUpdatePosition = false;
m_nSampleLength = 0;

m_bStartSliderIsMoved = false;
m_bLoopSliderIsMoved = false;
m_bEndSliderIsmoved = false;

m_SelectedSlider = NONE;
m_SelectedSlider = SampleEditor::Slider::NoSlider;
m_pEditedSample = nullptr;
setMouseTracking(true);
}

Expand All @@ -89,14 +86,14 @@ void MainSampleWaveDisplay::paintLocatorEvent( int pos, bool updateposi)
update();
}

static void set_paint_color(QPainter & painter, const QColor & color, bool selected, MainSampleWaveDisplay::Slider which)
static void set_paint_color(QPainter & painter, const QColor & color, bool selected, SampleEditor::Slider which)
{
if (!selected) {
painter.setPen( color );
} else {
QColor highlight = QColor(std::min(255, color.red() + 20 + 20 * (which == MainSampleWaveDisplay::END)),
std::min(255, color.green() + 20 + 20 * (which == MainSampleWaveDisplay::START)),
std::min(255, color.blue() + 20 + 20 * (which == MainSampleWaveDisplay::LOOP)));
QColor highlight = QColor(std::min(255, color.red() + 20 + 20 * (which == SampleEditor::EndSlider)),
std::min(255, color.green() + 20 + 20 * (which == SampleEditor::StartSlider)),
std::min(255, color.blue() + 20 + 20 * (which == SampleEditor::LoopSlider)));

painter.setPen ( highlight );
}
Expand All @@ -119,13 +116,13 @@ void MainSampleWaveDisplay::paintEvent(QPaintEvent *ev)
for ( int x = 25; x < width() -25; x++ ) {
if ( !issmaller || x <= m_nSampleLength){
painter.drawLine( x, -m_pPeakDatal[x -25] +VCenterl, x, -m_pPeakDatal[x -24] +VCenterl );
painter.drawLine( x, -m_pPeakDatar[x -25] +VCenterr, x, -m_pPeakDatar[x -24] +VCenterr );
painter.drawLine( x, -m_pPeakDatar[x -25] +VCenterr, x, -m_pPeakDatar[x -24] +VCenterr );
}else
{
painter.drawLine( x, 0 +VCenterl, x, 0 +VCenterl );
painter.drawLine( x, 0 +VCenterr, x, 0 +VCenterr );
}

}


Expand All @@ -147,15 +144,15 @@ void MainSampleWaveDisplay::paintEvent(QPaintEvent *ev)
font.setWeight( 63 );
painter.setFont( font );
//start frame pointer
set_paint_color(painter, startColor, m_SelectedSlider == START, m_SelectedSlider);
painter.drawLine( m_nStartFramePosition, 4, m_nStartFramePosition, height() -4 );
set_paint_color(painter, startColor, m_SelectedSlider == SampleEditor::Slider::StartSlider, m_SelectedSlider);
painter.drawLine( m_nStartFramePosition, 4, m_nStartFramePosition, height() -4 );
painter.drawText( m_nStartFramePosition -10, 250, 10,20, Qt::AlignRight, "S" );
//endframe pointer
set_paint_color(painter, endColor, m_SelectedSlider == END, m_SelectedSlider);
set_paint_color(painter, endColor, m_SelectedSlider == SampleEditor::Slider::EndSlider, m_SelectedSlider);
painter.drawLine( m_nEndFramePosition, 4, m_nEndFramePosition, height() -4 );
painter.drawText( m_nEndFramePosition -10, 123, 10, 20, Qt::AlignRight, "E" );
//loopframe pointer
set_paint_color(painter, loopColor, m_SelectedSlider == LOOP, m_SelectedSlider);
set_paint_color(painter, loopColor, m_SelectedSlider == SampleEditor::Slider::LoopSlider, m_SelectedSlider);
painter.drawLine( m_nLoopFramePosition, 4, m_nLoopFramePosition, height() -4 );
painter.drawText( m_nLoopFramePosition , 0, 10, 20, Qt::AlignLeft, "L" );

Expand All @@ -171,78 +168,76 @@ void MainSampleWaveDisplay::updateDisplayPointer()



void MainSampleWaveDisplay::updateDisplay( const QString& filename )
std::shared_ptr<H2Core::Sample> MainSampleWaveDisplay::loadSampleAndUpdateDisplay( const QString& filename )
{

auto pNewSample = Sample::load( filename );

if ( pNewSample ) {

int nSampleLength = pNewSample->get_frames();
m_nSampleLength = nSampleLength;
float nScaleFactor = nSampleLength / (width() -50);
if ( nScaleFactor < 1 ){
nScaleFactor = 1;
}
if ( ! pNewSample ) {
update();
return nullptr;
}
m_pEditedSample = pNewSample;
int nSampleLength = pNewSample->get_frames();
m_nSampleLength = nSampleLength;
float nScaleFactor = nSampleLength / (width() -50);
if ( nScaleFactor < 1 ){
nScaleFactor = 1;
}

float fGain = height() / 4.0 * 1.0;

auto pSampleDatal = pNewSample->get_data_l();
auto pSampleDatar = pNewSample->get_data_r();

unsigned nSamplePos = 0;
int nVall = 0;
int nValr = 0;
int newVall = 0;
int newValr = 0;
for ( int i = 0; i < width(); ++i ){
for ( int j = 0; j < nScaleFactor; ++j ) {
if ( j < nSampleLength && nSamplePos < nSampleLength) {
if ( pSampleDatal[ nSamplePos ] && pSampleDatar[ nSamplePos ] ){
newVall = static_cast<int>( pSampleDatal[ nSamplePos ] * fGain );
newValr = static_cast<int>( pSampleDatar[ nSamplePos ] * fGain );
nVall = newVall;
nValr = newValr;
}else
{
nVall = 0;
nValr = 0;
}
float fGain = height() / 4.0 * 1.0;

auto pSampleDatal = pNewSample->get_data_l();
auto pSampleDatar = pNewSample->get_data_r();

unsigned nSamplePos = 0;
int nVall = 0;
int nValr = 0;
int newVall = 0;
int newValr = 0;
for ( int i = 0; i < width(); ++i ){
for ( int j = 0; j < nScaleFactor; ++j ) {
if ( j < nSampleLength && nSamplePos < nSampleLength) {
if ( pSampleDatal[ nSamplePos ] && pSampleDatar[ nSamplePos ] ){
newVall = static_cast<int>( pSampleDatal[ nSamplePos ] * fGain );
newValr = static_cast<int>( pSampleDatar[ nSamplePos ] * fGain );
nVall = newVall;
nValr = newValr;
}else
{
nVall = 0;
nValr = 0;
}
++nSamplePos;
}
m_pPeakDatal[ i ] = nVall;
m_pPeakDatar[ i ] = nValr;
++nSamplePos;
}
m_pPeakDatal[ i ] = nVall;
m_pPeakDatar[ i ] = nValr;
}
update();

}
void MainSampleWaveDisplay::mouseUpdateDone() {
HydrogenApp::get_instance()->getSampleEditor()->returnAllMainWaveDisplayValues();
m_bStartSliderIsMoved = false;
m_bLoopSliderIsMoved = false;
m_bEndSliderIsmoved = false;
return pNewSample;
}


void MainSampleWaveDisplay::mouseMoveEvent(QMouseEvent *ev)
{
if (ev->buttons() && Qt::LeftButton) {
testPosition( ev );
if ( ev->buttons() && Qt::LeftButton ) {
if ( m_SelectedSlider != SampleEditor::Slider::NoSlider ) {
testPosition( ev );
emit sliderEdited( m_SelectedSlider );
}
} else {
chooseSlider( ev );
}
update();
mouseUpdateDone();
}

void MainSampleWaveDisplay::mousePressEvent(QMouseEvent *ev)
{
chooseSlider( ev );
testPosition( ev );
if ( m_SelectedSlider != SampleEditor::Slider::NoSlider ) {
testPosition( ev );
emit sliderEdited( m_SelectedSlider );
}
update();
mouseUpdateDone();
}

void MainSampleWaveDisplay::testPosition( QMouseEvent *ev )
Expand All @@ -251,69 +246,75 @@ void MainSampleWaveDisplay::testPosition( QMouseEvent *ev )
//startframepointer
int x = std::min(width() - 25, std::max(25, ev->x()));

if ( m_SelectedSlider == START ) {
if ( m_SelectedSlider == SampleEditor::Slider::StartSlider ) {
m_nStartFramePosition = x;
m_bStartSliderIsMoved = true;
if ( m_nStartFramePosition > m_nLoopFramePosition ){
m_nLoopFramePosition = m_nStartFramePosition;
m_bLoopSliderIsMoved = true;
}
if ( m_nStartFramePosition > m_nEndFramePosition ){
m_nEndFramePosition = m_nStartFramePosition;
m_bEndSliderIsmoved = true;
}
}

//loopframeposition
else if ( m_SelectedSlider == LOOP ) {
else if ( m_SelectedSlider == SampleEditor::Slider::LoopSlider ) {
if (x >= m_nStartFramePosition && x <= m_nEndFramePosition ) {
m_nLoopFramePosition = x ;
m_bLoopSliderIsMoved = true;
}
}
//endframeposition
else if ( m_SelectedSlider == END) {
else if ( m_SelectedSlider == SampleEditor::Slider::EndSlider) {
if (x >= m_nStartFramePosition) {
m_nEndFramePosition = x ;
m_bEndSliderIsmoved = true;
}
if ( m_nEndFramePosition < m_nLoopFramePosition ){
m_nLoopFramePosition = m_nEndFramePosition;
m_bLoopSliderIsMoved = true;
}
}
}


void MainSampleWaveDisplay::mouseReleaseEvent(QMouseEvent *ev)
{
m_SelectedSlider = NONE;
if ( m_SelectedSlider != SampleEditor::Slider::NoSlider ) {
emit doneEditingSlider( m_SelectedSlider );
}
m_SelectedSlider = SampleEditor::Slider::NoSlider;
update();
mouseUpdateDone();
}




void MainSampleWaveDisplay::chooseSlider(QMouseEvent * ev)
{
assert(ev);

QPoint start = QPoint(m_nStartFramePosition, height());
QPoint end = QPoint(m_nEndFramePosition, height() / 2);
QPoint loop = QPoint(m_nLoopFramePosition, 0);

int ds = (ev->pos() - start).manhattanLength();
int de = (ev->pos() - end).manhattanLength();
int dl = (ev->pos() - loop).manhattanLength();
m_SelectedSlider = NONE;

if (ds <= de && ds <= dl) {
m_SelectedSlider = START;
} else if (de < ds && de <= dl) {
m_SelectedSlider = END;
int ds = std::abs(ev->x() - m_nStartFramePosition);
int de = std::abs(ev->x() - m_nEndFramePosition);
int dl = std::abs(ev->x() - m_nLoopFramePosition);

if (ds < de && ds < dl) {
m_SelectedSlider = SampleEditor::Slider::StartSlider;
} else if (de < ds && de < dl) {
m_SelectedSlider = SampleEditor::Slider::EndSlider;
} else if (dl < ds && dl < de) {
m_SelectedSlider = LOOP;
m_SelectedSlider = SampleEditor::Slider::LoopSlider;
} else {
QPoint start = QPoint(m_nStartFramePosition, height());
QPoint end = QPoint(m_nEndFramePosition, height() / 2);
QPoint loop = QPoint(m_nLoopFramePosition, 0);

ds = (ev->pos() - start).manhattanLength();
de = (ev->pos() - end).manhattanLength();
dl = (ev->pos() - loop).manhattanLength();
if (ds <= de && ds <= dl) {
m_SelectedSlider = SampleEditor::Slider::StartSlider;
} else if (de < ds && de <= dl) {
m_SelectedSlider = SampleEditor::Slider::EndSlider;
} else if (dl < ds && dl < de) {
m_SelectedSlider = SampleEditor::Slider::LoopSlider;
} else {
m_SelectedSlider = SampleEditor::Slider::NoSlider; // should never occur
}
}
}

30 changes: 12 additions & 18 deletions src/gui/src/SampleEditor/MainSampleWaveDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,43 +28,36 @@

#include <core/Object.h>
#include "SampleEditor.h"
class SampleEditor;

class MainSampleWaveDisplay : public QWidget, public H2Core::Object
{
H2_OBJECT
Q_OBJECT

public:

enum Slider {
NONE,
START,
LOOP,
END
};

explicit MainSampleWaveDisplay(QWidget* pParent);
~MainSampleWaveDisplay();

void updateDisplay( const QString& filename );
std::shared_ptr<H2Core::Sample> loadSampleAndUpdateDisplay( const QString& filename );
void updateDisplayPointer();

void paintLocatorEvent( int pos, bool last_event);
void paintEvent(QPaintEvent *ev);

void testPositionFromSampleeditor();

int m_nStartFramePosition;
int m_nLoopFramePosition;
int m_nEndFramePosition;

bool m_bStartSliderIsMoved;
bool m_bLoopSliderIsMoved;
bool m_bEndSliderIsmoved;

Slider m_SelectedSlider;
SampleEditor::Slider m_SelectedSlider;

std::shared_ptr<H2Core::Sample> getEditedSample() { return m_pEditedSample; }

signals:
void doneEditingSlider ( SampleEditor::Slider slider );
void sliderEdited ( SampleEditor::Slider slider );

private:
virtual void mouseMoveEvent(QMouseEvent *ev);
Expand All @@ -73,11 +66,12 @@ class MainSampleWaveDisplay : public QWidget, public H2Core::Object
void testPosition( QMouseEvent *ev );
void chooseSlider( QMouseEvent *ev );
void mouseUpdateDone();


std::shared_ptr<H2Core::Sample> m_pEditedSample;
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the purpose of this member variable? It's never used.

QPixmap m_background;
int* m_pPeakDatal;
int* m_pPeakDatar;

int m_nSampleLength;
int m_nLocator;
bool m_bUpdatePosition;
Expand Down
Loading