void SampleEditor::on_PlayOrigPushButton_clicked() { if (PlayOrigPushButton->text() == "Stop" ){ testpTimer(); return; } const int selectedlayer = InstrumentEditorPanel::get_instance()->getSelectedLayer(); Song *pSong = Hydrogen::get_instance()->getSong(); Instrument *pInstr = pSong->get_instrument_list()->get( Hydrogen::get_instance()->getSelectedInstrumentNumber() ); /* *preview_instrument deletes the last used preview instrument, therefore we have to construct a temporary *instrument. Otherwise pInstr would be deleted if consumed by preview_instrument. */ Instrument *tmpInstrument = Instrument::load_instrument( pInstr->get_drumkit_name(), pInstr->get_name() ); Sample *pNewSample = Sample::load( pInstr->get_layer( selectedlayer )->get_sample()->get_filepath() ); if ( pNewSample ){ int length = ( ( pNewSample->get_frames() / pNewSample->get_sample_rate() + 1) * 100 ); AudioEngine::get_instance()->get_sampler()->preview_instrument( tmpInstrument ); AudioEngine::get_instance()->get_sampler()->preview_sample( pNewSample, length ); m_pslframes = pNewSample->get_frames(); } m_pMainSampleWaveDisplay->paintLocatorEvent( StartFrameSpinBox->value() / m_divider + 24 , true); m_pSampleAdjustView->setDetailSamplePosition( __loops.start_frame, m_pZoomfactor , 0); m_pTimer->start(40); // update ruler at 25 fps m_pRealtimeFrameEnd = Hydrogen::get_instance()->getRealtimeFrames() + m_pslframes; PlayOrigPushButton->setText( QString( "Stop") ); }
void InstrumentEditor::rubberbandbpmchangeEvent() { if( !Preferences::get_instance()->getRubberBandBatchMode() /*&& Preferences::get_instance()->__usetimeline */){ //we return also if time-line is activated. this wont work. // INFOLOG( "Tempo change: Recomputing rubberband samples is disabled" ); return; } // INFOLOG( "Tempo change: Recomputing rubberband samples." ); Hydrogen *pEngine = Hydrogen::get_instance(); Song *song = pEngine->getSong(); assert(song); if(song){ InstrumentList *songInstrList = song->get_instrument_list(); assert(songInstrList); for ( unsigned nInstr = 0; nInstr < songInstrList->size(); ++nInstr ) { Instrument *pInstr = songInstrList->get( nInstr ); assert( pInstr ); if ( pInstr ){ for ( int nLayer = 0; nLayer < MAX_LAYERS; nLayer++ ) { InstrumentLayer *pLayer = pInstr->get_layer( nLayer ); if ( pLayer ) { Sample *pSample = pLayer->get_sample(); if ( pSample ) { if( pSample->get_rubberband().use ) { //INFOLOG( QString("Instrument %1 Layer %2" ).arg(nInstr).arg(nLayer)); Sample *newSample = Sample::load( pSample->get_filepath(), pSample->get_loops(), pSample->get_rubberband(), *pSample->get_velocity_envelope(), *pSample->get_pan_envelope() ); if( !newSample ){ continue; } delete pSample; // insert new sample from newInstrument AudioEngine::get_instance()->lock( RIGHT_HERE ); pLayer->set_sample( newSample ); AudioEngine::get_instance()->unlock(); } } } } } } } }
void SampleEditor::on_PlayPushButton_clicked() { if (PlayPushButton->text() == "Stop" ){ testpTimer(); return; } const float pan_L = 0.5f; const float pan_R = 0.5f; const int nLength = -1; const float fPitch = 0.0f; const int selectedLayer = InstrumentEditorPanel::get_instance()->getSelectedLayer(); Song *pSong = Hydrogen::get_instance()->getSong(); Instrument *pInstr = pSong->get_instrument_list()->get( Hydrogen::get_instance()->getSelectedInstrumentNumber() ); Note *pNote = new Note( pInstr, 0, pInstr->get_layer( selectedLayer )->get_end_velocity() - 0.01, pan_L, pan_R, nLength, fPitch); AudioEngine::get_instance()->get_sampler()->note_on(pNote); setSamplelengthFrames(); createPositionsRulerPath(); m_pPlayButton = true; m_pMainSampleWaveDisplay->paintLocatorEvent( StartFrameSpinBox->value() / m_divider + 24 , true); m_pSampleAdjustView->setDetailSamplePosition( __loops.start_frame, m_pZoomfactor , 0); if( __rubberband.use == false ){ m_pTimer->start(40); // update ruler at 25 fps } m_pRealtimeFrameEnd = Hydrogen::get_instance()->getRealtimeFrames() + m_pslframes; //calculate the new rubberband sample length if( __rubberband.use ){ m_prealtimeframeendfortarget = Hydrogen::get_instance()->getRealtimeFrames() + (m_pslframes * m_pRatio + 0.1); }else { m_prealtimeframeendfortarget = m_pRealtimeFrameEnd; } m_pTargetDisplayTimer->start(40); // update ruler at 25 fps PlayPushButton->setText( QString( "Stop") ); }
/// Render a note /// Return 0: the note is not ended /// Return 1: the note is ended unsigned Sampler::__render_note( Note* pNote, unsigned nBufferSize, Song* pSong ) { //infoLog( "[renderNote] instr: " + pNote->getInstrument()->m_sName ); assert( pSong ); unsigned int nFramepos; Hydrogen* pEngine = Hydrogen::get_instance(); AudioOutput* audio_output = pEngine->getAudioOutput(); if ( pEngine->getState() == STATE_PLAYING ) { nFramepos = audio_output->m_transport.m_nFrames; } else { // use this to support realtime events when not playing nFramepos = pEngine->getRealtimeFrames(); } Instrument *pInstr = pNote->get_instrument(); if ( !pInstr ) { ERRORLOG( "NULL instrument" ); return 1; } float fLayerGain = 1.0; float fLayerPitch = 0.0; // scelgo il sample da usare in base alla velocity Sample *pSample = NULL; for ( unsigned nLayer = 0; nLayer < MAX_LAYERS; ++nLayer ) { InstrumentLayer *pLayer = pInstr->get_layer( nLayer ); if ( pLayer == NULL ) continue; if ( ( pNote->get_velocity() >= pLayer->get_start_velocity() ) && ( pNote->get_velocity() <= pLayer->get_end_velocity() ) ) { pSample = pLayer->get_sample(); fLayerGain = pLayer->get_gain(); fLayerPitch = pLayer->get_pitch(); break; } } if ( !pSample ) { QString dummy = QString( "NULL sample for instrument %1. Note velocity: %2" ).arg( pInstr->get_name() ).arg( pNote->get_velocity() ); WARNINGLOG( dummy ); return 1; } if ( pNote->get_sample_position() >= pSample->get_frames() ) { WARNINGLOG( "sample position out of bounds. The layer has been resized during note play?" ); return 1; } int noteStartInFrames = ( int ) ( pNote->get_position() * audio_output->m_transport.m_nTickSize ) + pNote->get_humanize_delay(); int nInitialSilence = 0; if ( noteStartInFrames > ( int ) nFramepos ) { // scrivo silenzio prima dell'inizio della nota nInitialSilence = noteStartInFrames - nFramepos; int nFrames = nBufferSize - nInitialSilence; if ( nFrames < 0 ) { int noteStartInFramesNoHumanize = ( int )pNote->get_position() * audio_output->m_transport.m_nTickSize; if ( noteStartInFramesNoHumanize > ( int )( nFramepos + nBufferSize ) ) { // this note is not valid. it's in the future...let's skip it.... ERRORLOG( QString( "Note pos in the future?? Current frames: %1, note frame pos: %2" ).arg( nFramepos ).arg(noteStartInFramesNoHumanize ) ); //pNote->dumpInfo(); return 1; } // delay note execution //INFOLOG( "Delaying note execution. noteStartInFrames: " + to_string( noteStartInFrames ) + ", nFramePos: " + to_string( nFramepos ) ); return 0; } } float cost_L = 1.0f; float cost_R = 1.0f; float cost_track_L = 1.0f; float cost_track_R = 1.0f; if ( pInstr->is_muted() || pSong->__is_muted ) { // is instrument muted? cost_L = 0.0; cost_R = 0.0; if ( Preferences::get_instance()->m_nJackTrackOutputMode == 0 ) { // Post-Fader cost_track_L = 0.0; cost_track_R = 0.0; } } else { // Precompute some values... cost_L = cost_L * pNote->get_velocity(); // note velocity cost_L = cost_L * pNote->get_pan_l(); // note pan cost_L = cost_L * fLayerGain; // layer gain cost_L = cost_L * pInstr->get_pan_l(); // instrument pan cost_L = cost_L * pInstr->get_gain(); // instrument gain cost_L = cost_L * pInstr->get_volume(); // instrument volume if ( Preferences::get_instance()->m_nJackTrackOutputMode == 0 ) { // Post-Fader cost_track_L = cost_L * 2; } cost_L = cost_L * pSong->get_volume(); // song volume cost_L = cost_L * 2; // max pan is 0.5 cost_R = cost_R * pNote->get_velocity(); // note velocity cost_R = cost_R * pNote->get_pan_r(); // note pan cost_R = cost_R * fLayerGain; // layer gain cost_R = cost_R * pInstr->get_pan_r(); // instrument pan cost_R = cost_R * pInstr->get_gain(); // instrument gain cost_R = cost_R * pInstr->get_volume(); // instrument volume if ( Preferences::get_instance()->m_nJackTrackOutputMode == 0 ) { // Post-Fader cost_track_R = cost_R * 2; } cost_R = cost_R * pSong->get_volume(); // song pan cost_R = cost_R * 2; // max pan is 0.5 } // direct track outputs only use velocity if ( Preferences::get_instance()->m_nJackTrackOutputMode == 1 ) { cost_track_L = cost_track_L * pNote->get_velocity(); cost_track_L = cost_track_L * fLayerGain; cost_track_R = cost_track_L; } // Se non devo fare resample (drumkit) posso evitare di utilizzare i float e gestire il tutto in // maniera ottimizzata // constant^12 = 2, so constant = 2^(1/12) = 1.059463. // float nStep = 1.0;1.0594630943593 float fTotalPitch = pNote->get_total_pitch() + fLayerPitch; //_INFOLOG( "total pitch: " + to_string( fTotalPitch ) ); if( ( int )pNote->get_sample_position() == 0 ) { if( Hydrogen::get_instance()->getMidiOutput() != NULL ){ Hydrogen::get_instance()->getMidiOutput()->handleQueueNote( pNote ); } } if ( fTotalPitch == 0.0 && pSample->get_sample_rate() == audio_output->getSampleRate() ) { // NO RESAMPLE return __render_note_no_resample( pSample, pNote, nBufferSize, nInitialSilence, cost_L, cost_R, cost_track_L, cost_track_R, pSong ); } else { // RESAMPLE return __render_note_resample( pSample, pNote, nBufferSize, nInitialSilence, cost_L, cost_R, cost_track_L, cost_track_R, fLayerPitch, pSong ); } }