Exemple #1
0
void TempoAtGrid (COMMAND_T* ct)
{
	// Get tempo map and grid
	BR_Envelope tempoMap(GetTempoEnv());
	if (!tempoMap.CountSelected())
		return;
	double grid; GetConfig("projgriddiv", grid);

	// Loop through selected points
	Undo_BeginBlock2(NULL);
	int count = tempoMap.Count()-1;
	for (int i = 0; i < tempoMap.CountSelected(); ++i)
	{
		// Get tempo points
		int id = tempoMap.GetSelected(i);
		double t0, t1, b0, b1;
		int s0;

		tempoMap.GetPoint(id, &t0, &b0, &s0, NULL);
		tempoMap.GetPoint(id+1, &t1, &b1, NULL, NULL);

		// If last tempo point is selected, fake second point as if it's at the end of project (markers and regions included)
		if (id == count)
		{
			b1 = b0;
			t1 = EndOfProject(true, true);
		}

		// "fake" bpm for second point (needed for TempoAtPosition)
		if (s0 == SQUARE)
			b1 = b0;

		// Grid diving starts again from the start of the measure in which tempo marker is so we need to calculate
		// the offset between where grid line really is and where it would be if we just divided QN with grid spacing.
		double beat; int measure; GetTempoTimeSigMarker(NULL, id, NULL, &measure, &beat, NULL, NULL, NULL, NULL);
		double offset =  grid - fmod(TimeMap_timeToQN(TimeMap2_beatsToTime(0, 0, &measure)), grid);

		// Find first grid line and then loop through the rest creating tempo points
		double pGridLn = t0, gridLn = TimeMap_timeToQN(t0);
		gridLn = TimeMap_QNToTime(gridLn-offset - fmod(gridLn,grid)); // it can be before tempo point but next while should correct that
		while (true)
		{
			// Search for the next grid line
			while (gridLn < pGridLn + MAX_GRID_DIV) // MAX_GRID_DIV acts as safety net to prevent accidental multiple points around grid lines/tempo points
				gridLn = TimeMap_QNToTime(TimeMap_timeToQN(gridLn) + grid);

			// Create points until the next point
			if (gridLn < t1 - MAX_GRID_DIV)
				tempoMap.CreatePoint(tempoMap.Count(), gridLn, TempoAtPosition(b0, b1, t0, t1, gridLn), s0, 0, false);
			else
				break;
			pGridLn = gridLn;
		}
	}
	tempoMap.Commit();
	Undo_EndBlock2(NULL, SWS_CMD_SHORTNAME(ct), UNDO_STATE_ALL);
}
Exemple #2
0
void BR_MidiItemTimePos::Restore (double timeOffset /*=0*/)
{
	SetMediaItemInfo_Value(item, "C_BEATATTACHMODE", 0);
	for (size_t i = 0; i < savedMidiTakes.size(); ++i)
	{
		BR_MidiItemTimePos::MidiTake* midiTake = &savedMidiTakes[i];
		MediaItem_Take* take = midiTake->take;

		int noteCount, ccCount, textCount;
		if (MIDI_CountEvts(take, &noteCount, &ccCount, &textCount))
		{
			for (int i = 0; i < noteCount; ++i) MIDI_DeleteNote(take, 0);
			for (int i = 0; i < ccCount;   ++i) MIDI_DeleteCC(take, 0);
			for (int i = 0; i < textCount; ++i) MIDI_DeleteTextSysexEvt(take, 0);
		}

		if (looped && loopStart != -1 && loopEnd != -1)
		{
			SetMediaItemTakeInfo_Value(take, "D_STARTOFFS", 0);
			MIDI_SetItemExtents(item, TimeMap_timeToQN(loopStart), TimeMap_timeToQN(loopEnd));

			SetMediaItemInfo_Value(item , "B_LOOPSRC", 1); // because MIDI_SetItemExtents() disables looping
			TrimItem(item, position, position + length, true);
			SetMediaItemTakeInfo_Value(take, "D_STARTOFFS", loopedOffset);
		}
		else
		{
			TrimItem(item, position, position + length, true);
		}

		for (size_t i = 0; i < midiTake->noteEvents.size(); ++i)
			midiTake->noteEvents[i].InsertEvent(take, timeOffset);

		for (size_t i = 0; i < midiTake->ccEvents.size(); ++i)
			midiTake->ccEvents[i].InsertEvent(take, timeOffset);

		for (size_t i = 0; i < midiTake->sysEvents.size(); ++i)
			midiTake->sysEvents[i].InsertEvent(take, timeOffset);
	}

	SetMediaItemInfo_Value(item, "C_BEATATTACHMODE", timeBase);
}