Пример #1
0
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") ); 
}
Пример #2
0
 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();
	
							}
						}
					}
				}
			}
		}
	}

}
Пример #3
0
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") ); 
	
}
Пример #4
0
/// 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 );
	}
}