diff --git a/src/core/Basics/Sample.h b/src/core/Basics/Sample.h index bcd78bce1..ea9c0afe7 100644 --- a/src/core/Basics/Sample.h +++ b/src/core/Basics/Sample.h @@ -112,7 +112,7 @@ class Sample : public H2Core::Object float pitch; ///< desired pitch int c_settings; ///< TODO should be crispness, see rubberband -h /** constructor */ - Rubberband() : use( false ), divider ( 1.0 ), pitch( 1.0 ), c_settings( 4 ) { }; + Rubberband() : use( false ), divider ( 1.0 ), pitch( 0.0 ), c_settings( 4 ) { }; /** copy constructor */ Rubberband( const Rubberband* other ) : use( other->use ), diff --git a/src/gui/src/SampleEditor/MainSampleWaveDisplay.cpp b/src/gui/src/SampleEditor/MainSampleWaveDisplay.cpp index b84c900cf..830879feb 100644 --- a/src/gui/src/SampleEditor/MainSampleWaveDisplay.cpp +++ b/src/gui/src/SampleEditor/MainSampleWaveDisplay.cpp @@ -55,11 +55,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); } @@ -86,14 +83,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 ); } @@ -116,13 +113,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 ); } - + } @@ -144,15 +141,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" ); @@ -168,78 +165,76 @@ void MainSampleWaveDisplay::updateDisplayPointer() -void MainSampleWaveDisplay::updateDisplay( const QString& filename ) +std::shared_ptr 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( pSampleDatal[ nSamplePos ] * fGain ); - newValr = static_cast( 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( pSampleDatal[ nSamplePos ] * fGain ); + newValr = static_cast( 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 ) @@ -248,35 +243,29 @@ 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; } } } @@ -284,9 +273,11 @@ void MainSampleWaveDisplay::testPosition( QMouseEvent *ev ) 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(); } @@ -294,23 +285,33 @@ void MainSampleWaveDisplay::mouseReleaseEvent(QMouseEvent *ev) 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 + } } } diff --git a/src/gui/src/SampleEditor/MainSampleWaveDisplay.h b/src/gui/src/SampleEditor/MainSampleWaveDisplay.h index 133babe3b..d5fa2c485 100644 --- a/src/gui/src/SampleEditor/MainSampleWaveDisplay.h +++ b/src/gui/src/SampleEditor/MainSampleWaveDisplay.h @@ -28,7 +28,6 @@ #include #include "SampleEditor.h" -class SampleEditor; class MainSampleWaveDisplay : public QWidget, public H2Core::Object { @@ -36,35 +35,29 @@ class MainSampleWaveDisplay : public QWidget, public H2Core::Object 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 getEditedSample() { return m_pEditedSample; } + + signals: + void doneEditingSlider ( SampleEditor::Slider slider ); + void sliderEdited ( SampleEditor::Slider slider ); private: virtual void mouseMoveEvent(QMouseEvent *ev); @@ -73,11 +66,12 @@ class MainSampleWaveDisplay : public QWidget, public H2Core::Object m_pEditedSample; QPixmap m_background; int* m_pPeakDatal; int* m_pPeakDatar; - + int m_nSampleLength; int m_nLocator; bool m_bUpdatePosition; diff --git a/src/gui/src/SampleEditor/SampleEditor.cpp b/src/gui/src/SampleEditor/SampleEditor.cpp index 607e3e8fd..ae6d2855e 100644 --- a/src/gui/src/SampleEditor/SampleEditor.cpp +++ b/src/gui/src/SampleEditor/SampleEditor.cpp @@ -62,7 +62,6 @@ SampleEditor::SampleEditor ( QWidget* pParent, int nSelectedComponent, int nSele m_pTargetDisplayTimer = new QTimer(this); connect(m_pTargetDisplayTimer, SIGNAL(timeout()), this, SLOT(updateTargetsamplePositionRuler())); - setClean(); m_nSelectedLayer = nSelectedLayer; m_nSelectedComponent = nSelectedComponent; m_sSampleName = sSampleFilename; @@ -75,7 +74,8 @@ SampleEditor::SampleEditor ( QWidget* pParent, int nSelectedComponent, int nSele m_nSlframes = 0; m_pPositionsRulerPath = nullptr; m_bPlayButton = false; - m_fRatio = 1.0f; + m_bPlayingOriginalSample = false; + m_Ratio = 1.0; __rubberband.c_settings = 4; QString newfilename = sSampleFilename.section( '/', -1 ); @@ -93,7 +93,7 @@ SampleEditor::SampleEditor ( QWidget* pParent, int nSelectedComponent, int nSele if ( m_pSampleFromFile == nullptr ) { reject(); } - + // m_pEditedSample = std::make_shared(m_pSampleFromFile); unsigned slframes = m_pSampleFromFile->get_frames(); LoopCountSpinBox->setRange(0, 20000 ); @@ -106,30 +106,47 @@ SampleEditor::SampleEditor ( QWidget* pParent, int nSelectedComponent, int nSele __rubberband.use = false; __rubberband.divider = 1.0; + __rubberband.pitch = 0.0; + openDisplays(); getAllFrameInfos(); + returnAllMainWaveDisplayValues(); + doneEditing(); + setClean(); + + m_bAdjusting = false; + m_bSampleEditorClean = true; adjustSize(); setFixedSize ( width(), height() ); + connect( StartFrameSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedStartFrameSpinBox(int) ) ); + connect( LoopFrameSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedLoopFrameSpinBox(int) ) ); + connect( EndFrameSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedEndFrameSpinBox(int) ) ); + connect( LoopCountSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedLoopCountSpinBox( int ) ) ); + connect( ProcessingTypeComboBox, SIGNAL( currentIndexChanged ( const QString ) ), this, SLOT( valueChangedProcessingTypeComboBox( const QString ) ) ); + connect( rubberComboBox, SIGNAL( currentIndexChanged ( const QString ) ), this, SLOT( valueChangedrubberComboBox( const QString ) ) ); + connect( rubberbandCsettingscomboBox, SIGNAL( currentIndexChanged ( const QString ) ), this, SLOT( valueChangedrubberbandCsettingscomboBox( const QString ) ) ); + connect( pitchdoubleSpinBox, SIGNAL ( valueChanged( double ) ), this, SLOT( valueChangedpitchdoubleSpinBox( double ) ) ); + connect( EditTypeComboBox, SIGNAL ( currentIndexChanged ( int ) ), this, SLOT( valueChangedEditTypeComboBox( int ) ) ); + + connect( m_pTargetSampleView, SIGNAL ( envelopeEdited ( SampleEditor::EnvelopeType ) ), this, SLOT( envelopeEdited ( SampleEditor::EnvelopeType ) ) ); + connect( m_pTargetSampleView, SIGNAL ( doneEditingEnvelope ( SampleEditor::EnvelopeType ) ), this, SLOT( envelopeEdited ( SampleEditor::EnvelopeType ) ) ); + + connect( m_pMainSampleWaveDisplay, SIGNAL ( sliderEdited ( SampleEditor::Slider ) ), this, SLOT( sliderEdited ( SampleEditor::Slider ) ) ); + connect( m_pMainSampleWaveDisplay, SIGNAL ( doneEditingSlider ( SampleEditor::Slider ) ), this, SLOT( sliderEdited ( SampleEditor::Slider ) ) ); + + #ifndef H2CORE_HAVE_RUBBERBAND if ( !Filesystem::file_executable( Preferences::get_instance()->m_rubberBandCLIexecutable , true /* silent */) ) { RubberbandCframe->setDisabled ( true ); - setClean(); } #else RubberbandCframe->setDisabled ( false ); - setClean(); #endif - - __rubberband.pitch = 0.0; - - m_bAdjusting = false; - m_bSampleEditorClean = true; } - SampleEditor::~SampleEditor() { m_pMainSampleWaveDisplay->close(); @@ -147,6 +164,42 @@ SampleEditor::~SampleEditor() INFOLOG ( "DESTROY" ); } +void SampleEditor::envelopeEdited( SampleEditor::EnvelopeType mode) +{ + returnAllTargetDisplayValues(); + setUnclean(); + doneEditing(); +} + +bool SampleEditor::rubberbandIsOff() +{ + return rubberComboBox->currentIndex() == 0; +} + +void SampleEditor::doneEditing() { + auto edited = std::make_shared(m_pSampleFromFile); + edited->apply(__loops, + __rubberband, + *m_pTargetSampleView->get_velocity(), + *m_pTargetSampleView->get_pan()); + m_pTargetSampleView->updateDisplay( edited, 1.0 ); + m_pEditedSample = edited; +} + +void SampleEditor::sliderEdited( SampleEditor::Slider slider ) +{ + returnAllMainWaveDisplayValues(); + if ( rubberbandIsOff() && + (slider == SampleEditor::Slider::StartSlider || + slider == SampleEditor::Slider::EndSlider || + slider == SampleEditor::Slider::LoopSlider && __loops.count) + ) { + __rubberband.divider = computeNoopRubberbandDivider(); + } + setUnclean(); + doneEditing(); +} + void SampleEditor::closeEvent(QCloseEvent *event) { @@ -167,39 +220,53 @@ void SampleEditor::closeEvent(QCloseEvent *event) void SampleEditor::getAllFrameInfos() { - std::shared_ptr pInstrument = nullptr; - std::shared_ptr pSample; - std::shared_ptr pSong = Hydrogen::get_instance()->getSong(); - - if (pSong != nullptr) { - InstrumentList *pInstrList = pSong->getInstrumentList(); - int nInstr = Hydrogen::get_instance()->getSelectedInstrumentNumber(); - if ( nInstr >= static_cast(pInstrList->size()) ) { - nInstr = -1; - } + H2Core::Hydrogen *hydrogen = Hydrogen::get_instance(); + if ( hydrogen == nullptr ) { + ERRORLOG("no hydrogen"); + return; + } - if (nInstr == -1) { - pInstrument = nullptr; - } - else { - pInstrument = pInstrList->get( nInstr ); - //INFOLOG( "new instr: " + pInstrument->m_sName ); - } + std::shared_ptr pSong = hydrogen->getSong(); + if ( pSong == nullptr ) { + ERRORLOG("no song"); + return; } - - assert( pInstrument ); - auto pCompo = pInstrument->get_component(0); - assert( pCompo ); + InstrumentList *pInstrList = pSong->getInstrumentList(); + if ( pInstrList == nullptr ) { + ERRORLOG("no instrument list"); + return; + } + int nInstr = hydrogen->getSelectedInstrumentNumber(); + if ( nInstr < 0 || nInstr >= static_cast(pInstrList->size()) ) { + ERRORLOG("out of range instrument number"); + return; + } + + std::shared_ptr pInstrument = pInstrList->get( nInstr ); + if ( pInstrument == nullptr ) { + ERRORLOG("no instrument"); + return; + }; + + auto pCompo = pInstrument->get_component( m_nSelectedComponent ); + if ( pCompo == nullptr ) { + ERRORLOG("no instrument component"); + return; + } auto pLayer = pCompo->get_layer( m_nSelectedLayer ); - if ( pLayer ) { - pSample = pLayer->get_sample(); + if ( pLayer == nullptr ) { + ERRORLOG("invalid layer selection"); + return; + } + + std::shared_ptr pSample = pLayer->get_sample(); + if ( pSample == nullptr ) { + ERRORLOG("no sample"); } - - assert( pSample ); -//this values are needed if we restore a sample from disk if a new song with sample changes will load + // this values are needed if we restore a sample from disk if a new song with sample changes will load m_bSampleIsModified = pSample->get_is_modified(); m_nSamplerate = pSample->get_sample_rate(); __loops = pSample->get_loops(); @@ -211,7 +278,6 @@ void SampleEditor::getAllFrameInfos() m_pTargetSampleView->get_velocity()->push_back( EnvelopePoint( m_pTargetSampleView->width(), 0 ) ); } else { m_pTargetSampleView->get_velocity()->clear(); - for(auto& pt : *pSample->get_velocity_envelope() ){ m_pTargetSampleView->get_velocity()->emplace_back( pt ); } @@ -228,6 +294,7 @@ void SampleEditor::getAllFrameInfos() } if (m_bSampleIsModified) { + // update loop and rubberband settings view __loops.end_frame = pSample->get_loops().end_frame; if ( __loops.mode == Sample::Loops::FORWARD ) { ProcessingTypeComboBox->setCurrentIndex ( 0 ); @@ -238,7 +305,7 @@ void SampleEditor::getAllFrameInfos() if ( __loops.mode == Sample::Loops::PINGPONG ) { ProcessingTypeComboBox->setCurrentIndex ( 2 ); } - + StartFrameSpinBox->setValue( __loops.start_frame ); LoopFrameSpinBox->setValue( __loops.loop_frame ); EndFrameSpinBox->setValue( __loops.end_frame ); @@ -251,24 +318,20 @@ void SampleEditor::getAllFrameInfos() m_pMainSampleWaveDisplay->m_nEndFramePosition = __loops.end_frame / m_divider + 25 ; m_pMainSampleWaveDisplay->updateDisplayPointer(); - if( !__rubberband.use ) { - rubberComboBox->setCurrentIndex( 0 ); - } - rubberbandCsettingscomboBox->setCurrentIndex( __rubberband.c_settings ); - if( !__rubberband.use ) { - rubberbandCsettingscomboBox->setCurrentIndex( 4 ); - } - + pitchdoubleSpinBox->setValue( __rubberband.pitch ); - if( !__rubberband.use ) { - pitchdoubleSpinBox->setValue( 0.0 ); - } + // if( !__rubberband.use ) { + // pitchdoubleSpinBox->setValue( 0.0 ); + //} + + setSamplelengthFrames(); - if( __rubberband.divider == 1.0/64.0) { + if ( !__rubberband.use || (std::abs(computeCurrentRatio() - 1.0) < 0.0001) ) { + rubberComboBox->setCurrentIndex( 0 ); + } else if( __rubberband.divider == 1.0/64.0) { rubberComboBox->setCurrentIndex( 1 ); - } - else if( __rubberband.divider == 1.0/32.0) { + } else if( __rubberband.divider == 1.0/32.0) { rubberComboBox->setCurrentIndex( 2 ); } else if( __rubberband.divider == 1.0/16.0) { rubberComboBox->setCurrentIndex( 3 ); @@ -278,24 +341,14 @@ void SampleEditor::getAllFrameInfos() rubberComboBox->setCurrentIndex( 5 ); } else if( __rubberband.divider == 1.0/2.0) { rubberComboBox->setCurrentIndex( 6 ); - } else if( __rubberband.use && ( __rubberband.divider >= 1.0 ) ) { + } else if( __rubberband.use && ( __rubberband.divider >= 1.0 ) ) { rubberComboBox->setCurrentIndex( (int)(__rubberband.divider + 6) ); } - - setSamplelengthFrames(); - checkRatioSettings(); + checkRatioSettings(); } - m_pTargetSampleView->updateDisplay( pLayer ); - connect( StartFrameSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedStartFrameSpinBox(int) ) ); - connect( LoopFrameSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedLoopFrameSpinBox(int) ) ); - connect( EndFrameSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedEndFrameSpinBox(int) ) ); - connect( LoopCountSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChangedLoopCountSpinBox( int ) ) ); - connect( ProcessingTypeComboBox, SIGNAL( currentIndexChanged ( const QString ) ), this, SLOT( valueChangedProcessingTypeComboBox( const QString ) ) ); - connect( rubberComboBox, SIGNAL( currentIndexChanged ( const QString ) ), this, SLOT( valueChangedrubberComboBox( const QString ) ) ); - connect( rubberbandCsettingscomboBox, SIGNAL( currentIndexChanged ( const QString ) ), this, SLOT( valueChangedrubberbandCsettingscomboBox( const QString ) ) ); - connect( pitchdoubleSpinBox, SIGNAL ( valueChanged( double ) ), this, SLOT( valueChangedpitchdoubleSpinBox( double ) ) ); + m_pTargetSampleView->updateDisplay( pLayer ); } void SampleEditor::getAllLocalFrameInfos() @@ -312,13 +365,14 @@ void SampleEditor::openDisplays() { // wavedisplays m_divider = m_pSampleFromFile->get_frames() / 574.0F; - m_pMainSampleWaveDisplay->updateDisplay( m_sSampleName ); + auto sample = m_pMainSampleWaveDisplay->loadSampleAndUpdateDisplay( m_sSampleName ); + m_pMainSampleWaveDisplay->move( 1, 1 ); m_pSampleAdjustView->updateDisplay( m_sSampleName ); m_pSampleAdjustView->move( 1, 1 ); - m_pTargetSampleView->move( 1, 1 ); + m_pTargetSampleView->updateDisplay( sample, 1.0 ); } @@ -393,10 +447,10 @@ void SampleEditor::createNewLayer() pInstrument = pInstrList->get( nInstr ); } } - + std::shared_ptr pLayer = nullptr; if( pInstrument ) { - pLayer = pInstrument->get_component(0)->get_layer( m_nSelectedLayer ); + pLayer = pInstrument->get_component( m_nSelectedComponent )->get_layer( m_nSelectedLayer ); // insert new sample from newInstrument pLayer->set_sample( pEditSample ); @@ -425,17 +479,21 @@ bool SampleEditor::returnAllMainWaveDisplayValues() testpTimer(); // QMessageBox::information ( this, "Hydrogen", tr ( "jep %1" ).arg(m_pSample->get_frames())); - m_bSampleIsModified = true; - if( m_pMainSampleWaveDisplay->m_bStartSliderIsMoved ) __loops.start_frame = m_pMainSampleWaveDisplay->m_nStartFramePosition * m_divider - 25 * m_divider; - if( m_pMainSampleWaveDisplay->m_bLoopSliderIsMoved ) __loops.loop_frame = m_pMainSampleWaveDisplay->m_nLoopFramePosition * m_divider - 25 * m_divider; - if( m_pMainSampleWaveDisplay->m_bEndSliderIsmoved ) __loops.end_frame = m_pMainSampleWaveDisplay->m_nEndFramePosition * m_divider - 25 * m_divider ; - StartFrameSpinBox->setValue( __loops.start_frame ); - LoopFrameSpinBox->setValue( __loops.loop_frame ); - EndFrameSpinBox->setValue( __loops.end_frame ); + if (m_pMainSampleWaveDisplay->m_SelectedSlider != SampleEditor::NoSlider) { + m_bSampleIsModified = true; + __loops.start_frame = m_pMainSampleWaveDisplay->m_nStartFramePosition * m_divider - 25 * m_divider; + __loops.loop_frame = m_pMainSampleWaveDisplay->m_nLoopFramePosition * m_divider - 25 * m_divider; + __loops.end_frame = m_pMainSampleWaveDisplay->m_nEndFramePosition * m_divider - 25 * m_divider ; + StartFrameSpinBox->setValue( __loops.start_frame ); + LoopFrameSpinBox->setValue( __loops.loop_frame ); + EndFrameSpinBox->setValue( __loops.end_frame ); + } m_bOnewayStart = true; m_bOnewayLoop = true; m_bOnewayEnd = true; setSamplelengthFrames(); + resetPositionsRulerPath(); + checkRatioSettings(); m_bAdjusting = false; setUnclean(); return true; @@ -462,128 +520,170 @@ void SampleEditor::setClean() PrevChangesPushButton->setFlat ( true ); } -void SampleEditor::valueChangedStartFrameSpinBox( int ) +///////////////////////////////////////////////////////////////// +// Loop Controls +///////////////////////////////////////////////////////////////// +void SampleEditor::valueChangedStartFrameSpinBox( int value) { - testpTimer(); - m_pDetailFrame = StartFrameSpinBox->value(); - if (m_pDetailFrame == __loops.start_frame) { // no actual change - if (! m_bAdjusting ) on_PlayPushButton_clicked(); - return; - } + bool change = (value != __loops.start_frame); + if ( change && ! m_bAdjusting ) testpTimer(); + m_pDetailFrame = value; m_sLineColor = "Start"; if ( !m_bOnewayStart ){ m_pMainSampleWaveDisplay->m_nStartFramePosition = StartFrameSpinBox->value() / m_divider + 25 ; m_pMainSampleWaveDisplay->updateDisplayPointer(); m_pSampleAdjustView->setDetailSamplePosition( m_pDetailFrame, m_fZoomfactor , m_sLineColor); - __loops.start_frame = m_pDetailFrame; + __loops.start_frame = value; }else { m_pSampleAdjustView->setDetailSamplePosition( m_pDetailFrame, m_fZoomfactor , m_sLineColor); m_bOnewayStart = false; } - testPositionsSpinBoxes(); - setUnclean(); - setSamplelengthFrames(); + if ( change ) { + testPositionsSpinBoxes(); + setSamplelengthFrames(); + resetPositionsRulerPath(); + if ( rubberbandIsOff() ) { + __rubberband.divider = computeNoopRubberbandDivider(); + } + checkRatioSettings(); + setUnclean(); + } + doneEditing(); } -void SampleEditor::valueChangedLoopFrameSpinBox( int ) +void SampleEditor::valueChangedLoopFrameSpinBox( int value ) { - testpTimer(); - m_pDetailFrame = LoopFrameSpinBox->value(); - if (m_pDetailFrame == __loops.loop_frame) { - if ( ! m_bAdjusting ) on_PlayPushButton_clicked(); - return; - } + bool change = (value != __loops.loop_frame); + if ( change && ! m_bAdjusting ) testpTimer(); + m_pDetailFrame = value; m_sLineColor = "Loop"; if ( !m_bOnewayLoop ){ m_pMainSampleWaveDisplay->m_nLoopFramePosition = LoopFrameSpinBox->value() / m_divider + 25 ; m_pMainSampleWaveDisplay->updateDisplayPointer(); m_pSampleAdjustView->setDetailSamplePosition( m_pDetailFrame, m_fZoomfactor , m_sLineColor); - __loops.loop_frame = m_pDetailFrame; + __loops.loop_frame = value; }else { m_pSampleAdjustView->setDetailSamplePosition( m_pDetailFrame, m_fZoomfactor , m_sLineColor); m_bOnewayLoop = false; } - testPositionsSpinBoxes(); - setUnclean(); - setSamplelengthFrames(); + if ( change ) { + testPositionsSpinBoxes(); + setSamplelengthFrames(); + resetPositionsRulerPath(); + if ( rubberbandIsOff() ) { + __rubberband.divider = computeNoopRubberbandDivider(); + } + checkRatioSettings(); + setUnclean(); + } + doneEditing(); } -void SampleEditor::valueChangedEndFrameSpinBox( int ) +void SampleEditor::valueChangedEndFrameSpinBox( int value) { - testpTimer(); - m_pDetailFrame = EndFrameSpinBox->value(); - if ( m_pDetailFrame == __loops.end_frame) { - if ( ! m_bAdjusting ) on_PlayPushButton_clicked(); - return; - } + bool change = (value != __loops.end_frame); + if ( change && ! m_bAdjusting ) testpTimer(); + m_pDetailFrame = value; m_sLineColor = "End"; if ( !m_bOnewayEnd ){ m_pMainSampleWaveDisplay->m_nEndFramePosition = EndFrameSpinBox->value() / m_divider + 25 ; m_pMainSampleWaveDisplay->updateDisplayPointer(); m_pSampleAdjustView->setDetailSamplePosition( m_pDetailFrame, m_fZoomfactor , m_sLineColor); - __loops.end_frame = m_pDetailFrame; + __loops.end_frame = value; }else { m_bOnewayEnd = false; m_pSampleAdjustView->setDetailSamplePosition( m_pDetailFrame, m_fZoomfactor , m_sLineColor); } - testPositionsSpinBoxes(); - setUnclean(); - setSamplelengthFrames(); + if ( change ) { + testPositionsSpinBoxes(); + setSamplelengthFrames(); + resetPositionsRulerPath(); + if ( rubberbandIsOff() ) { + __rubberband.divider = computeNoopRubberbandDivider(); + } + checkRatioSettings(); + setUnclean(); + } + doneEditing(); } -void SampleEditor::on_PlayPushButton_clicked() +void SampleEditor::valueChangedLoopCountSpinBox( int value ) { - Hydrogen* pHydrogen = Hydrogen::get_instance(); + Hydrogen *hydrogen = Hydrogen::get_instance(); + bool change = (value != __loops.count); - if (PlayPushButton->text() == "Stop" ){ - testpTimer(); - return; + if ( change && ! m_bAdjusting ) testpTimer(); + + if ( hydrogen && m_nSlframes > hydrogen->getAudioOutput()->getSampleRate() * 60 ){ + hydrogen->getAudioEngine()->getSampler()->stopPlayingNotes(); + m_pMainSampleWaveDisplay->paintLocatorEvent( -1 , false); + m_pTimer->stop(); + m_bPlayButton = false; } + __loops.count = value; + if ( hydrogen && m_nSlframes > hydrogen->getAudioOutput()->getSampleRate() * 60 * 30){ // >30 min + LoopCountSpinBox->setMaximum(LoopCountSpinBox->value() -1); + } + if ( change ) { + testPositionsSpinBoxes(); + setSamplelengthFrames(); + resetPositionsRulerPath(); + if ( rubberbandIsOff() ) { + __rubberband.divider = computeNoopRubberbandDivider(); + } + checkRatioSettings(); + setUnclean(); + } + doneEditing(); +} - const float fPan = 0.f; - const int nLength = -1; - const float fPitch = 0.0f; - const int selectedLayer = InstrumentEditorPanel::get_instance()->getSelectedLayer(); - std::shared_ptr pSong = Hydrogen::get_instance()->getSong(); - if ( pSong == nullptr ) { - return; +void SampleEditor::valueChangedProcessingTypeComboBox( const QString unused ) +{ + Sample::Loops::LoopMode previous = __loops.mode; + + switch ( ProcessingTypeComboBox->currentIndex() ){ + case 0 :// + __loops.mode = Sample::Loops::FORWARD; + break; + case 1 :// + __loops.mode = Sample::Loops::REVERSE; + break; + case 2 :// + __loops.mode = Sample::Loops::PINGPONG; + break; + default: + __loops.mode = Sample::Loops::FORWARD; } - auto pInstr = pSong->getInstrumentList()->get( Hydrogen::get_instance()->getSelectedInstrumentNumber() ); - if ( pInstr == nullptr ) { - return; + bool change = ( previous != __loops.mode ); + if ( change ) { + resetPositionsRulerPath(); + setUnclean(); } - Note *pNote = new Note( pInstr, 0, pInstr->get_component( m_nSelectedComponent )->get_layer( selectedLayer )->get_end_velocity() - 0.01, fPan, nLength, fPitch); - pNote->set_specific_compo_id( m_nSelectedComponent ); - pHydrogen->getAudioEngine()->getSampler()->noteOn(pNote); + doneEditing(); +} - setSamplelengthFrames(); - createPositionsRulerPath(); - m_bPlayButton = true; - m_pMainSampleWaveDisplay->paintLocatorEvent( StartFrameSpinBox->value() / m_divider + 24 , true); - m_pSampleAdjustView->setDetailSamplePosition( __loops.start_frame, m_fZoomfactor , nullptr); - if( __rubberband.use == false ){ - m_pTimer->start(40); // update ruler at 25 fps - } +///////////////////////////////////////////////////////////////// +// Original / Edited Sample Playing +///////////////////////////////////////////////////////////////// - m_nRealtimeFrameEnd = pHydrogen->getRealtimeFrames() + m_nSlframes; - //calculate the new rubberband sample length - if( __rubberband.use ){ - m_nRealtimeFrameEndForTarget = pHydrogen->getRealtimeFrames() + (m_nSlframes * m_fRatio + 0.1); - }else - { - m_nRealtimeFrameEndForTarget = m_nRealtimeFrameEnd; +void SampleEditor::on_PlayPushButton_clicked() +{ + if (PlayPushButton->text() == "Stop" ){ // this should be a better way if we want to translate this label + testpTimer(); + return; } - m_pTargetDisplayTimer->start(40); // update ruler at 25 fps - PlayPushButton->setText( QString( "Stop") ); + m_bPlayButton = true; + playSample(m_pEditedSample, false); + PlayPushButton->setText( QString( "Stop") ); } void SampleEditor::on_PlayOrigPushButton_clicked() @@ -592,7 +692,14 @@ void SampleEditor::on_PlayOrigPushButton_clicked() testpTimer(); return; } + m_bPlayButton = true; + playSample(m_pSampleFromFile, true); + PlayOrigPushButton->setText( QString( "Stop") ); +} + +void SampleEditor::playSample(const std::shared_ptr sample, bool original) +{ const int selectedlayer = InstrumentEditorPanel::get_instance()->getSelectedLayer(); std::shared_ptr pSong = Hydrogen::get_instance()->getSong(); auto pInstr = pSong->getInstrumentList()->get( Hydrogen::get_instance()->getSelectedInstrumentNumber() ); @@ -602,27 +709,50 @@ void SampleEditor::on_PlayOrigPushButton_clicked() *instrument. Otherwise pInstr would be deleted if consumed by preview_instrument. */ auto pTmpInstrument = Instrument::load_instrument( pInstr->get_drumkit_name(), pInstr->get_name() ); - auto pNewSample = Sample::load( pInstr->get_component(0)->get_layer( selectedlayer )->get_sample()->get_filepath() ); + auto pNewSample = std::make_shared(sample); - if ( pNewSample != nullptr ){ - int length = ( ( pNewSample->get_frames() / pNewSample->get_sample_rate() + 1) * 100 ); - Hydrogen::get_instance()->getAudioEngine()->getSampler()->preview_instrument( pTmpInstrument ); - Hydrogen::get_instance()->getAudioEngine()->getSampler()->preview_sample( pNewSample, length ); - m_nSlframes = pNewSample->get_frames(); + if ( pNewSample == nullptr ) { + ERRORLOG("no sample to play"); + return; } - - m_pMainSampleWaveDisplay->paintLocatorEvent( StartFrameSpinBox->value() / m_divider + 24 , true); - m_pSampleAdjustView->setDetailSamplePosition( __loops.start_frame, m_fZoomfactor , nullptr); - m_pTimer->start(40); // update ruler at 25 fps - m_nRealtimeFrameEnd = Hydrogen::get_instance()->getRealtimeFrames() + m_nSlframes; - PlayOrigPushButton->setText( QString( "Stop") ); + if ( ! m_pPositionsRulerPath || m_bPlayingOriginalSample != original ) { + createPositionsRulerPath(pNewSample, original); + } + // m_nSlframes = pNewSample->get_frames(); + int length = ( ( pNewSample->get_frames() / pNewSample->get_sample_rate() + 1) * 100 ); + Hydrogen::get_instance()->getAudioEngine()->getSampler()->preview_instrument( pTmpInstrument ); + Hydrogen::get_instance()->getAudioEngine()->getSampler()->preview_sample( pNewSample, length ); + unsigned long realtime_play_start = Hydrogen::get_instance()->getRealtimeFrames();; + + m_pMainSampleWaveDisplay->paintLocatorEvent( original ? 24 : StartFrameSpinBox->value() / m_divider + 24 , true); + m_pSampleAdjustView->setDetailSamplePosition( original ? 0 : __loops.start_frame, m_fZoomfactor , nullptr); + m_nRealtimeFrameEnd = realtime_play_start + m_nSlframes; + + if ( original ) { + m_nRealtimeFrameEnd = realtime_play_start + pNewSample->get_frames(); + m_nOriginalFrames = pNewSample->get_frames(); + } + //calculate the new rubberband sample length + if( __rubberband.use ){ + m_nRealtimeFrameEndForTarget = realtime_play_start + (m_nSlframes * m_Ratio + 0.1); + }else + { + m_nRealtimeFrameEndForTarget = m_nRealtimeFrameEnd; + } + if ( original || ! __rubberband.use || std::abs(m_Ratio - 1.0 ) < 0.000001) { + m_pTimer->start(40); // update ruler at 25 fps + } + if ( ! original ) m_pTargetDisplayTimer->start(40); // update ruler at 25 fps } void SampleEditor::updateMainsamplePositionRuler() { unsigned long realpos = Hydrogen::get_instance()->getRealtimeFrames(); if ( realpos < m_nRealtimeFrameEnd ){ - unsigned frame = m_nSlframes - ( m_nRealtimeFrameEnd - realpos ); + unsigned total_frames = m_bPlayingOriginalSample ? m_nOriginalFrames : m_nSlframes; + + unsigned frame = total_frames - ( m_nRealtimeFrameEnd - realpos ); + if ( m_bPlayButton == true ){ m_pMainSampleWaveDisplay->paintLocatorEvent( m_pPositionsRulerPath[frame] / m_divider + 25 , true); m_pSampleAdjustView->setDetailSamplePosition( m_pPositionsRulerPath[frame], m_fZoomfactor , nullptr); @@ -635,6 +765,7 @@ void SampleEditor::updateMainsamplePositionRuler() { m_pMainSampleWaveDisplay->paintLocatorEvent( -1 , false); m_pTimer->stop(); + m_pTargetDisplayTimer->stop(); PlayPushButton->setText( QString( tr( "&Play" )) ); PlayOrigPushButton->setText( QString( tr( "P&lay original sample" ) ) ); m_bPlayButton = false; @@ -646,7 +777,7 @@ void SampleEditor::updateTargetsamplePositionRuler() unsigned long realpos = Hydrogen::get_instance()->getRealtimeFrames(); unsigned targetSampleLength; if( __rubberband.use ){ - targetSampleLength = m_nSlframes * m_fRatio + 0.1; + targetSampleLength = m_nSlframes * m_Ratio + 0.1; }else { targetSampleLength = m_nSlframes; @@ -654,7 +785,7 @@ void SampleEditor::updateTargetsamplePositionRuler() if ( realpos < m_nRealtimeFrameEndForTarget ){ unsigned pos = targetSampleLength - ( m_nRealtimeFrameEndForTarget - realpos ); m_pTargetSampleView->paintLocatorEventTargetDisplay( (m_pTargetSampleView->width() * pos /targetSampleLength), true); -// ERRORLOG( QString("sampleval: %1").arg(frame) ); + // ERRORLOG( QString("sampleval: %1").arg(frame) ); }else { m_pTargetSampleView->paintLocatorEventTargetDisplay( -1 , false); @@ -666,24 +797,29 @@ void SampleEditor::updateTargetsamplePositionRuler() } - -void SampleEditor::createPositionsRulerPath() +void SampleEditor::resetPositionsRulerPath() { + if ( !m_bPlayingOriginalSample && m_pPositionsRulerPath ) { + delete[] m_pPositionsRulerPath; + m_pPositionsRulerPath = nullptr; + } +} +void SampleEditor::createPositionsRulerPath(const std::shared_ptr sample, bool original) +{ + qWarning()<< "createPositionsRulerPath: " << original; setSamplelengthFrames(); + unsigned normalLength = m_pSampleFromFile->get_frames(); - unsigned oneSampleLength = __loops.end_frame - __loops.start_frame; + unsigned oneSampleLength = original ? normalLength : __loops.end_frame - __loops.start_frame; unsigned loopLength = __loops.end_frame - __loops.loop_frame; unsigned repeatsLength = loopLength * __loops.count; - unsigned newLength = 0; - if (oneSampleLength == loopLength){ - newLength = oneSampleLength + oneSampleLength * __loops.count ; - }else - { - newLength =oneSampleLength + repeatsLength; - } + unsigned newLength = oneSampleLength + repeatsLength; - unsigned normalLength = m_pSampleFromFile->get_frames(); + // if (original) { + // oneSampleLength = newLength = normalLength; + // loopLength = repeatsLength = 0; + // } unsigned * normalFrames = new unsigned[ normalLength ]; unsigned * tempFrames = new unsigned[ newLength ]; unsigned * loopFrames = new unsigned[ loopLength ]; @@ -691,53 +827,57 @@ void SampleEditor::createPositionsRulerPath() for ( unsigned i = 0; i < normalLength; i++ ) { normalFrames[i] = i; } + assert (original || m_nSlframes == newLength); Sample::Loops::LoopMode loopmode = __loops.mode; - long int z = __loops.loop_frame; - long int y = __loops.start_frame; for ( unsigned i = 0; i < newLength; i++){ //first vector tempFrames[i] = 0; } + long int y = original ? 0 : __loops.start_frame; for ( unsigned i = 0; i < oneSampleLength; i++, y++){ //first vector tempFrames[i] = normalFrames[y]; } + if (! original ) { + long int z = __loops.loop_frame; + for ( unsigned i = 0; i < loopLength; i++, z++){ //loop vector - for ( unsigned i = 0; i < loopLength; i++, z++){ //loop vector - - loopFrames[i] = normalFrames[z]; - } + loopFrames[i] = normalFrames[z]; + } - if ( loopmode == Sample::Loops::REVERSE ){ - std::reverse(loopFrames, loopFrames + loopLength); - } + if ( loopmode == Sample::Loops::REVERSE ) { - if ( loopmode == Sample::Loops::REVERSE && __loops.count > 0 && __loops.start_frame == __loops.loop_frame ){ - std::reverse( tempFrames, tempFrames + oneSampleLength ); - } + std::reverse(loopFrames, loopFrames + loopLength); - if ( loopmode == Sample::Loops::PINGPONG && __loops.start_frame == __loops.loop_frame){ - std::reverse(loopFrames, loopFrames + loopLength); - } + if ( __loops.count > 0 && __loops.start_frame == __loops.loop_frame ){ + std::reverse( tempFrames, tempFrames + oneSampleLength ); + } - for ( int i = 0; i< __loops.count ;i++){ - unsigned tempdataend = oneSampleLength + ( loopLength * i ); - if ( __loops.start_frame == __loops.loop_frame ){ - std::copy( loopFrames, loopFrames+loopLength ,tempFrames+ tempdataend ); - } - if ( loopmode == Sample::Loops::PINGPONG && __loops.count > 1){ + } else if ( loopmode == Sample::Loops::PINGPONG && __loops.start_frame == __loops.loop_frame){ std::reverse(loopFrames, loopFrames + loopLength); } - if ( __loops.start_frame != __loops.loop_frame ){ - std::copy( loopFrames, loopFrames+loopLength ,tempFrames+ tempdataend ); + + for ( int i = 0; i< __loops.count ;i++){ + + unsigned tempdataend = oneSampleLength + ( loopLength * i ); + + if ( __loops.start_frame == __loops.loop_frame ){ + std::copy( loopFrames, loopFrames+loopLength ,tempFrames+ tempdataend ); + } + if ( loopmode == Sample::Loops::PINGPONG && __loops.count > 1){ + std::reverse(loopFrames, loopFrames + loopLength); + } + if ( __loops.start_frame != __loops.loop_frame ){ + std::copy( loopFrames, loopFrames+loopLength ,tempFrames+ tempdataend ); + } } - } - if ( __loops.count == 0 && loopmode == Sample::Loops::REVERSE ){ - std::reverse( tempFrames + __loops.loop_frame, tempFrames + newLength); + if ( __loops.count == 0 && loopmode == Sample::Loops::REVERSE ){ + std::reverse( tempFrames + __loops.loop_frame, tempFrames + newLength); + } } if(m_pPositionsRulerPath) @@ -746,6 +886,7 @@ void SampleEditor::createPositionsRulerPath() } m_pPositionsRulerPath = tempFrames; + m_bPlayingOriginalSample = original; delete[] loopFrames; delete[] normalFrames; @@ -759,59 +900,31 @@ void SampleEditor::setSamplelengthFrames() unsigned oneSampleLength = __loops.end_frame - __loops.start_frame; unsigned loopLength = __loops.end_frame - __loops.loop_frame ; unsigned repeatsLength = loopLength * __loops.count; - unsigned newLength = 0; - - if (oneSampleLength == loopLength){ - newLength = oneSampleLength + oneSampleLength * __loops.count ; - }else - { - newLength =oneSampleLength + repeatsLength; - } + unsigned newLength = oneSampleLength + repeatsLength; m_nSlframes = newLength; newlengthLabel->setText(QString( tr( "new sample length" ) ) .append( QString( ": %1 " ).arg(newLength) ) .append( tr( "frames" ))); - checkRatioSettings(); -} - - - -void SampleEditor::valueChangedLoopCountSpinBox( int ) -{ - testpTimer(); - int count = LoopCountSpinBox->value(); - - if (count == __loops.count) { - if ( ! m_bAdjusting ) on_PlayOrigPushButton_clicked(); - return; + if ( rubberbandIsOff() ) { + __rubberband.divider == computeNoopRubberbandDivider(); } - if ( m_nSlframes > Hydrogen::get_instance()->getAudioOutput()->getSampleRate() * 60 ){ - Hydrogen::get_instance()->getAudioEngine()->getSampler()->stopPlayingNotes(); - m_pMainSampleWaveDisplay->paintLocatorEvent( -1 , false); - m_pTimer->stop(); - m_bPlayButton = false; - } - __loops.count = count; - setUnclean(); - setSamplelengthFrames(); - if ( m_nSlframes > Hydrogen::get_instance()->getAudioOutput()->getSampleRate() * 60 * 30){ // >30 min - LoopCountSpinBox->setMaximum(LoopCountSpinBox->value() -1); - } - + checkRatioSettings(); } - +///////////////////////////////////////////////////////////////// +// Rubberband Controls +///////////////////////////////////////////////////////////////// void SampleEditor::valueChangedrubberbandCsettingscomboBox( const QString ) { int new_settings = rubberbandCsettingscomboBox->currentIndex(); - if (new_settings == __rubberband.c_settings) { - if (! m_bAdjusting ) on_PlayPushButton_clicked(); - return; - } + bool change = (new_settings != __rubberband.c_settings); + + if ( ! change && ! m_bAdjusting ) testpTimer(); __rubberband.c_settings = new_settings; - setUnclean(); + if ( change ) setUnclean(); + doneEditing(); } @@ -819,30 +932,39 @@ void SampleEditor::valueChangedrubberbandCsettingscomboBox( const QString ) void SampleEditor::valueChangedpitchdoubleSpinBox( double ) { double new_value = pitchdoubleSpinBox->value(); - if (std::abs(new_value - __rubberband.pitch) < 0.0001) { - if (! m_bAdjusting ) on_PlayPushButton_clicked(); - return; + double old_value = __rubberband.pitch; + bool change = (std::abs(new_value - old_value) >= 0.0001); + if ( change ) { + bool used = __rubberband.use; + __rubberband.pitch = new_value; + __rubberband.use = !rubberbandIsOff() || std::abs(__rubberband.pitch) >= 0.0001; + if (!used && __rubberband.use) { + valueChangedrubberComboBox(""); + } + if (__rubberband.use && rubberbandIsOff()) { + __rubberband.divider == computeNoopRubberbandDivider(); + } + setUnclean(); } - __rubberband.pitch = new_value; - setUnclean(); + doneEditing(); } void SampleEditor::valueChangedrubberComboBox( const QString ) { - + bool current_usage = __rubberband.use; + float current_divider = __rubberband.divider; if( rubberComboBox->currentText() != "off" ){ __rubberband.use = true; }else { - __rubberband.use = false; - __rubberband.divider = 1.0; + __rubberband.use = std::abs(__rubberband.pitch) >= 0.0001; } switch ( rubberComboBox->currentIndex() ){ case 0 :// - __rubberband.divider = 4.0; + __rubberband.divider = computeNoopRubberbandDivider(); break; case 1 :// __rubberband.divider = 1.0/64.0; @@ -871,17 +993,32 @@ void SampleEditor::valueChangedrubberComboBox( const QString ) // QMessageBox::information ( this, "Hydrogen", tr ( "divider %1" ).arg( __rubberband.divider )); // float __rubberband.divider; setSamplelengthFrames(); + bool change = (current_usage != __rubberband.use) || (std::abs(current_divider - __rubberband.divider) >= 0.0001); + if ( change ) setUnclean(); + doneEditing(); +} +double SampleEditor::computeNoopRubberbandDivider() +{ + double bpm = Hydrogen::get_instance()->getNewBpmJTM(); + double duration = (double) m_nSlframes / (double) m_nSamplerate; + return duration * bpm / 60; +} - setUnclean(); +double SampleEditor::computeCurrentRatio() +{ + double durationtime = 60.0 / Hydrogen::get_instance()->getNewBpmJTM() * __rubberband.divider; + double induration = (double) m_nSlframes / (double) m_nSamplerate; + if (induration == 0.0) + return -1; + double ratio = durationtime / induration; + return ratio; } void SampleEditor::checkRatioSettings() { //calculate ratio - double durationtime = 60.0 / Hydrogen::get_instance()->getNewBpmJTM() * __rubberband.divider; - double induration = (double) m_nSlframes / (double) m_nSamplerate; - if (induration != 0.0) m_fRatio = durationtime / induration; + m_Ratio = computeCurrentRatio(); //my personal ratio quality settings //ratios < 0.1 || > 3.0 are bad (red) or experimental sounds @@ -892,11 +1029,11 @@ void SampleEditor::checkRatioSettings() //<---red---[--yellow--[------green------]----yellow----]---red---> //green ratio - if( ( m_fRatio >= 0.5 ) && ( m_fRatio <= 2.0 ) ){ + if( ( m_Ratio >= 0.5 ) && ( m_Ratio <= 2.0 ) ){ rubberComboBox->setStyleSheet("QComboBox { background-color: green; }"); } //yellow ratio - else if( ( m_fRatio >= 0.1 ) && ( m_fRatio <= 3.0 ) ){ + else if( ( m_Ratio >= 0.1 ) && ( m_Ratio <= 3.0 ) ){ rubberComboBox->setStyleSheet("QComboBox { background-color: yellow; }"); } //red ratio @@ -904,7 +1041,7 @@ void SampleEditor::checkRatioSettings() rubberComboBox->setStyleSheet("QComboBox { background-color: red; }"); } QString text = QString( tr(" RB-Ratio" ) ) - .append( QString( " %1" ).arg( m_fRatio ) ); + .append( QString( " %1" ).arg( m_Ratio ) ); ratiolabel->setText( text ); //no rubberband = default @@ -915,26 +1052,29 @@ void SampleEditor::checkRatioSettings() } -void SampleEditor::valueChangedProcessingTypeComboBox( const QString unused ) +void SampleEditor::valueChangedEditTypeComboBox( int index ) { - switch ( ProcessingTypeComboBox->currentIndex() ){ + if ( ! m_pTargetSampleView ) { + // qWarning() << "no TargetSampleView!"; + return; + } + switch ( index ){ case 0 :// - __loops.mode = Sample::Loops::FORWARD; + m_pTargetSampleView->setEditMode( SampleEditor::EnvelopeType::VelocityEnvelope ); break; case 1 :// - __loops.mode = Sample::Loops::REVERSE; - break; - case 2 :// - __loops.mode = Sample::Loops::PINGPONG; + if ( m_pTargetSampleView ) { + m_pTargetSampleView->setEditMode( SampleEditor::EnvelopeType::PanEnvelope ); + } break; default: - __loops.mode = Sample::Loops::FORWARD; + if ( m_pTargetSampleView ) { + m_pTargetSampleView->setEditMode( SampleEditor::EnvelopeType::NoEnvelope ); + } } - setUnclean(); } - void SampleEditor::on_verticalzoomSlider_valueChanged( int value ) { m_fZoomfactor = value / 10 +1; diff --git a/src/gui/src/SampleEditor/SampleEditor.h b/src/gui/src/SampleEditor/SampleEditor.h index 1ef232b61..671a04658 100644 --- a/src/gui/src/SampleEditor/SampleEditor.h +++ b/src/gui/src/SampleEditor/SampleEditor.h @@ -47,8 +47,20 @@ class SampleEditor : public QDialog, public Ui_SampleEditor_UI, public H2Core: H2_OBJECT(SampleEditor) Q_OBJECT public: - - SampleEditor( QWidget* pParent, int nSelectedComponent, int nSelectedLayer, QString nSampleFilename ); + + enum Slider { + NoSlider, + StartSlider, + EndSlider, + LoopSlider + }; + enum EnvelopeType { + NoEnvelope, + VelocityEnvelope, + PanEnvelope + }; + SampleEditor( QWidget* pParent, + int nSelectedComponent, int nSelectedLayer, QString nSampleFilename ); ~SampleEditor(); void setSampleName( QString name); @@ -58,9 +70,25 @@ class SampleEditor : public QDialog, public Ui_SampleEditor_UI, public H2Core: void setUnclean(); void setClean(); + void playSample(const std::shared_ptr sample, bool original); + double computeNoopRubberbandDivider(); + double computeCurrentRatio(); //this values come from the real sample to restore a frm song loaded sample bool m_bSampleIsModified; ///< true if sample is modified + bool rubberbandIsOff(); + protected: + MainSampleWaveDisplay *m_pMainSampleWaveDisplay; + TargetWaveDisplay *m_pTargetSampleView; + DetailWaveDisplay *m_pSampleAdjustView; + + public slots: + void envelopeEdited( SampleEditor::EnvelopeType mode); + void sliderEdited( SampleEditor::Slider slider); + void doneEditing(); + + public slots: + void valueChangedEditTypeComboBox( int ); private slots: void valueChangedLoopCountSpinBox( int ); void valueChangedProcessingTypeComboBox( const QString ); @@ -69,9 +97,11 @@ class SampleEditor : public QDialog, public Ui_SampleEditor_UI, public H2Core: void valueChangedpitchdoubleSpinBox( double ); void on_ClosePushButton_clicked(); void on_PrevChangesPushButton_clicked(); + void valueChangedStartFrameSpinBox( int ); void valueChangedLoopFrameSpinBox( int ); void valueChangedEndFrameSpinBox( int ); + void on_PlayPushButton_clicked(); void on_PlayOrigPushButton_clicked(); void on_verticalzoomSlider_valueChanged ( int value ); @@ -89,22 +119,21 @@ class SampleEditor : public QDialog, public Ui_SampleEditor_UI, public H2Core: void testPositionsSpinBoxes(); void createNewLayer(); void setSamplelengthFrames(); - void createPositionsRulerPath(); + void createPositionsRulerPath(std::shared_ptr sample, bool original); + void resetPositionsRulerPath(); void testpTimer(); void closeEvent(QCloseEvent *event); void checkRatioSettings(); virtual void mouseReleaseEvent(QMouseEvent *ev); - - MainSampleWaveDisplay *m_pMainSampleWaveDisplay; - TargetWaveDisplay *m_pTargetSampleView; - DetailWaveDisplay *m_pSampleAdjustView; - + + std::shared_ptr m_pSampleFromFile; + std::shared_ptr m_pEditedSample; int m_nSelectedLayer; int m_nSelectedComponent; QString m_sSampleName; - + double m_divider; float m_fZoomfactor; unsigned m_pDetailFrame; @@ -116,15 +145,16 @@ class SampleEditor : public QDialog, public Ui_SampleEditor_UI, public H2Core: bool m_bPlayButton; bool m_bAdjusting; bool m_bSampleEditorClean; - + bool m_bPlayingOriginalSample; unsigned long m_nRealtimeFrameEnd; unsigned long m_nRealtimeFrameEndForTarget; unsigned m_nSlframes; + unsigned m_nOriginalFrames; unsigned m_nSamplerate; QTimer *m_pTimer; QTimer *m_pTargetDisplayTimer; unsigned *m_pPositionsRulerPath; - float m_fRatio; + double m_Ratio; H2Core::Sample::Loops __loops; H2Core::Sample::Rubberband __rubberband; }; diff --git a/src/gui/src/SampleEditor/TargetWaveDisplay.cpp b/src/gui/src/SampleEditor/TargetWaveDisplay.cpp index ecfa2c965..c65c9b309 100644 --- a/src/gui/src/SampleEditor/TargetWaveDisplay.cpp +++ b/src/gui/src/SampleEditor/TargetWaveDisplay.cpp @@ -40,7 +40,6 @@ using namespace H2Core; #include "TargetWaveDisplay.h" #include "../Skin.h" -static TargetWaveDisplay::EnvelopeEditMode getEnvelopeEditMode(); TargetWaveDisplay::TargetWaveDisplay(QWidget* pParent) : QWidget( pParent ) @@ -67,12 +66,11 @@ TargetWaveDisplay::TargetWaveDisplay(QWidget* pParent) m_UpdatePosition = false; m_nSelectedEnvelopePoint = -1; m_nSnapRadius = 6; + m_EditMode = SampleEditor::VelocityEnvelope; setMouseTracking(true); } - - TargetWaveDisplay::~TargetWaveDisplay() { //INFOLOG( "DESTROY" ); @@ -81,6 +79,12 @@ TargetWaveDisplay::~TargetWaveDisplay() delete[] m_pPeakData_Right; } +void TargetWaveDisplay::setEditMode(SampleEditor::EnvelopeType mode) +{ + // qWarning() << "SetEditMode:" << mode; + m_EditMode = mode; +} + static void paintEnvelope(Sample::VelocityEnvelope &envelope, QPainter &painter, int selected, const QColor & lineColor, const QColor & handleColor, const QColor & selectedColor) { @@ -113,8 +117,6 @@ void TargetWaveDisplay::paintEvent(QPaintEvent *ev) { QPainter painter( this ); - m_EditMode = getEnvelopeEditMode(); - painter.setRenderHint( QPainter::Antialiasing ); painter.drawPixmap( ev->rect(), m_Background, ev->rect() ); painter.setPen( QColor( 252, 142, 73 )); @@ -147,10 +149,10 @@ void TargetWaveDisplay::paintEvent(QPaintEvent *ev) QColor selectedtHandleColor = QColor( 255, 100, 90 ); //volume line - paintEnvelope(m_VelocityEnvelope, painter, m_EditMode == TargetWaveDisplay::VELOCITY ? m_nSelectedEnvelopePoint : -1, + paintEnvelope(m_VelocityEnvelope, painter, m_EditMode == SampleEditor::VelocityEnvelope ? m_nSelectedEnvelopePoint : -1, volumeLineColor, volumeHandleColor, selectedtHandleColor); //pan line - paintEnvelope(m_PanEnvelope, painter, m_EditMode == TargetWaveDisplay::PAN ? m_nSelectedEnvelopePoint : -1, + paintEnvelope(m_PanEnvelope, painter, m_EditMode == SampleEditor::PanEnvelope ? m_nSelectedEnvelopePoint : -1, panLineColor, panHandleColor, selectedtHandleColor); painter.setPen( QPen( QColor( 255, 255, 255 ), 1, Qt::DotLine ) ); @@ -201,45 +203,54 @@ void TargetWaveDisplay::paintLocatorEventTargetDisplay( int pos, bool updateposi void TargetWaveDisplay::updateDisplay( std::shared_ptr pLayer ) { - if ( pLayer && pLayer->get_sample() ) { - - int nSampleLength = pLayer->get_sample()->get_frames(); - float nScaleFactor = nSampleLength / width(); - - float fGain = (height() - 8) / 2.0 * pLayer->get_gain(); - - auto pSampleDatal = pLayer->get_sample()->get_data_l(); - auto pSampleDatar = pLayer->get_sample()->get_data_r(); - int nSamplePos = 0; - int nVall; - int nValr; - for ( int i = 0; i < width(); ++i ){ - nVall = 0; - nValr = 0; - for ( int j = 0; j < nScaleFactor; ++j ) { - if ( j < nSampleLength ) { - if ( pSampleDatal[ nSamplePos ] < 0 ){ - int newVal = static_cast( pSampleDatal[ nSamplePos ] * -fGain ); - nVall = newVal; - }else - { - int newVal = static_cast( pSampleDatal[ nSamplePos ] * fGain ); - nVall = newVal; - } - if ( pSampleDatar[ nSamplePos ] > 0 ){ - int newVal = static_cast( pSampleDatar[ nSamplePos ] * -fGain ); - nValr = newVal; - }else - { - int newVal = static_cast( pSampleDatar[ nSamplePos ] * fGain ); - nValr = newVal; - } + // qWarning() << "TargetWaveDisplay::updateDisplay: layer:" << pLayer; + if ( ! pLayer ) { + return; + } + updateDisplay( pLayer->get_sample(), pLayer->get_gain() ); +} + +void TargetWaveDisplay::updateDisplay( std::shared_ptr sample, double gain ) +{ + // qWarning() << "TargetWaveDisplay::updateDisplay: sample:" << sample; + + int nSampleLength = sample->get_frames(); + float nScaleFactor = nSampleLength / width(); + + float fGain = (height() - 8) / 2.0 * gain; + + auto pSampleDatal = sample->get_data_l(); + auto pSampleDatar = sample->get_data_r(); + + int nSamplePos = 0; + int nVall; + int nValr; + for ( int i = 0; i < width(); ++i ){ + nVall = 0; + nValr = 0; + for ( int j = 0; j < nScaleFactor; ++j ) { + if ( j < nSampleLength ) { + if ( pSampleDatal[ nSamplePos ] < 0 ){ + int newVal = static_cast( pSampleDatal[ nSamplePos ] * -fGain ); + nVall = newVal; + }else + { + int newVal = static_cast( pSampleDatal[ nSamplePos ] * fGain ); + nVall = newVal; + } + if ( pSampleDatar[ nSamplePos ] > 0 ){ + int newVal = static_cast( pSampleDatar[ nSamplePos ] * -fGain ); + nValr = newVal; + }else + { + int newVal = static_cast( pSampleDatar[ nSamplePos ] * fGain ); + nValr = newVal; } - ++nSamplePos; } - m_pPeakData_Left[ i ] = nVall; - m_pPeakData_Right[ i ] = nValr; + ++nSamplePos; } + m_pPeakData_Left[ i ] = nVall; + m_pPeakData_Right[ i ] = nValr; } update(); @@ -248,8 +259,7 @@ void TargetWaveDisplay::updateDisplay( std::shared_ptr void TargetWaveDisplay::updateMouseSelection(QMouseEvent *ev) { - m_EditMode = getEnvelopeEditMode(); - const Sample::VelocityEnvelope & envelope = (m_EditMode == TargetWaveDisplay::VELOCITY) ? m_VelocityEnvelope : m_PanEnvelope; + const Sample::VelocityEnvelope & envelope = (m_EditMode == SampleEditor::VelocityEnvelope) ? m_VelocityEnvelope : m_PanEnvelope; m_nX = std::min(UI_WIDTH, std::max(0, ev->x())); m_nY = std::min(UI_HEIGHT, std::max(0, ev->y())); @@ -283,8 +293,7 @@ void TargetWaveDisplay::updateEnvelope() if ( m_nSelectedEnvelopePoint == -1 ) { return; } - m_EditMode = getEnvelopeEditMode(); - Sample::VelocityEnvelope & envelope = (m_EditMode == TargetWaveDisplay::VELOCITY) ? m_VelocityEnvelope : m_PanEnvelope; + Sample::VelocityEnvelope & envelope = (m_EditMode == SampleEditor::VelocityEnvelope) ? m_VelocityEnvelope : m_PanEnvelope; envelope.erase( envelope.begin() + m_nSelectedEnvelopePoint ); if ( m_nSelectedEnvelopePoint == 0 ){ m_nX = 0; @@ -315,15 +324,14 @@ void TargetWaveDisplay::mouseMoveEvent(QMouseEvent *ev) updateEnvelope(); updateMouseSelection(ev); update(); - HydrogenApp::get_instance()->getSampleEditor()->setUnclean(); + emit envelopeEdited ( m_EditMode ); } void TargetWaveDisplay::mousePressEvent(QMouseEvent *ev) { - m_EditMode = getEnvelopeEditMode(); - Sample::VelocityEnvelope & envelope = (m_EditMode == TargetWaveDisplay::VELOCITY) ? m_VelocityEnvelope : m_PanEnvelope; + Sample::VelocityEnvelope & envelope = (m_EditMode == SampleEditor::VelocityEnvelope) ? m_VelocityEnvelope : m_PanEnvelope; updateMouseSelection(ev); @@ -367,7 +375,7 @@ void TargetWaveDisplay::mousePressEvent(QMouseEvent *ev) updateMouseSelection(ev); update(); - HydrogenApp::get_instance()->getSampleEditor()->setUnclean(); + emit envelopeEdited ( m_EditMode ); } @@ -378,19 +386,5 @@ void TargetWaveDisplay::mouseReleaseEvent(QMouseEvent *ev) { updateMouseSelection(ev); update(); - HydrogenApp::get_instance()->getSampleEditor()->returnAllTargetDisplayValues(); -} - - -static TargetWaveDisplay::EnvelopeEditMode getEnvelopeEditMode() -{ - int editType = HydrogenApp::get_instance()->getSampleEditor()->EditTypeComboBox->currentIndex(); - if (editType == 0) { - return TargetWaveDisplay::VELOCITY; - } else if (editType == 1) { - return TargetWaveDisplay::PAN; - } else { - // combo options added - return TargetWaveDisplay::PAN; - } + emit doneEditingEnvelope( m_EditMode ); } diff --git a/src/gui/src/SampleEditor/TargetWaveDisplay.h b/src/gui/src/SampleEditor/TargetWaveDisplay.h index 00a48a52c..bd2c3f714 100644 --- a/src/gui/src/SampleEditor/TargetWaveDisplay.h +++ b/src/gui/src/SampleEditor/TargetWaveDisplay.h @@ -30,7 +30,7 @@ #include #include -class SampleEditor; +#include "SampleEditor.h" namespace H2Core { @@ -47,11 +47,7 @@ class TargetWaveDisplay : public QWidget, public H2Core::Object pSample, double gain ); void updateDisplay( std::shared_ptr pLayer ); void updateDisplayPointer(); void paintLocatorEventTargetDisplay( int pos, bool last_event); @@ -59,6 +55,13 @@ class TargetWaveDisplay : public QWidget, public H2Core::Object