static void findKeySigEvents (MidiFile& midiFile, StringPairArray& midiMetadata)
    {
        MidiMessageSequence keySigEvents;
        midiFile.findAllKeySigEvents (keySigEvents);
        const int numKeySigEvents = keySigEvents.getNumEvents();

        MemoryOutputStream keySigSequence;

        for (int i = 0; i < numKeySigEvents; ++i)
        {
            const MidiMessage& message (keySigEvents.getEventPointer (i)->message);
            const int key = jlimit (0, 14, message.getKeySignatureNumberOfSharpsOrFlats() + 7);
            const bool isMajor = message.isKeySignatureMajorKey();

            static const char* majorKeys[] = { "Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#" };
            static const char* minorKeys[] = { "Ab", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#", "G#", "D#", "A#" };

            String keySigString (isMajor ? majorKeys[key]
                                         : minorKeys[key]);

            if (! isMajor)
                keySigString << 'm';

            if (i == 0)
                midiMetadata.set (CoreAudioFormat::keySig, keySigString);

            if (numKeySigEvents > 1)
                keySigSequence << keySigString << ',' << keySigEvents.getEventTime (i) << ';';
        }

        if (keySigSequence.getDataSize() > 0)
            midiMetadata.set ("key signature sequence", keySigSequence.toUTF8());
    }
    static void findTimeSigEvents (MidiFile& midiFile, StringPairArray& midiMetadata)
    {
        MidiMessageSequence timeSigEvents;
        midiFile.findAllTimeSigEvents (timeSigEvents);
        const int numTimeSigEvents = timeSigEvents.getNumEvents();

        MemoryOutputStream timeSigSequence;

        for (int i = 0; i < numTimeSigEvents; ++i)
        {
            int numerator, denominator;
            timeSigEvents.getEventPointer(i)->message.getTimeSignatureInfo (numerator, denominator);

            String timeSigString;
            timeSigString << numerator << '/' << denominator;

            if (i == 0)
                midiMetadata.set (CoreAudioFormat::timeSig, timeSigString);

            if (numTimeSigEvents > 1)
                timeSigSequence << timeSigString << ',' << timeSigEvents.getEventTime (i) << ';';
        }

        if (timeSigSequence.getDataSize() > 0)
            midiMetadata.set ("time signature sequence", timeSigSequence.toUTF8());
    }
    static void findTempoEvents (MidiFile& midiFile, StringPairArray& midiMetadata)
    {
        MidiMessageSequence tempoEvents;
        midiFile.findAllTempoEvents (tempoEvents);

        const int numTempoEvents = tempoEvents.getNumEvents();
        MemoryOutputStream tempoSequence;

        for (int i = 0; i < numTempoEvents; ++i)
        {
            const double tempo = getTempoFromTempoMetaEvent (tempoEvents.getEventPointer (i));

            if (tempo > 0.0)
            {
                if (i == 0)
                    midiMetadata.set (CoreAudioFormat::tempo, String (tempo));

                if (numTempoEvents > 1)
                    tempoSequence << String (tempo) << ',' << tempoEvents.getEventTime (i) << ';';
            }
        }

        if (tempoSequence.getDataSize() > 0)
            midiMetadata.set ("tempo sequence", tempoSequence.toUTF8());
    }
Exemplo n.º 4
0
void MidiMessageSequence::extractSysExMessages (MidiMessageSequence& destSequence) const
{
    for (int i = 0; i < list.size(); ++i)
    {
        const MidiMessage& mm = list.getUnchecked(i)->message;

        if (mm.isSysEx())
            destSequence.addEvent (mm);
    }
}
Exemplo n.º 5
0
//==============================================================================
void MidiMessageSequence::extractMidiChannelMessages (const int channelNumberToExtract,
                                                      MidiMessageSequence& destSequence,
                                                      const bool alsoIncludeMetaEvents) const
{
    for (int i = 0; i < list.size(); ++i)
    {
        const MidiMessage& mm = list.getUnchecked(i)->message;

        if (mm.isForChannel (channelNumberToExtract) || (alsoIncludeMetaEvents && mm.isMetaEvent()))
            destSequence.addEvent (mm);
    }
}
//==============================================================================
void MidiSequencePlugin::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
	MidiSequencePluginBase::processBlock(buffer, midiMessages);
	MidiMessageSequence sourceMidi = *midiSequence;
	
	std::vector<int> doneTheseControllers;

    if (transport->isPlaying () && getBoolValue(PROP_SEQENABLED, true))
    {
		const int blockSize = buffer.getNumSamples ();
		MidiBuffer* midiBuffer = midiBuffers.getUnchecked (0);

        const int frameCounter = transport->getPositionInFrames ();
        const int framesPerBeat = transport->getFramesPerBeat ();
        const int nextBlockFrameNumber = frameCounter + blockSize;
		const int seqIndex = getLoopRepeatIndex();
		const double beatCount = getLoopBeatPosition();
		const double frameLenBeatCount = (nextBlockFrameNumber - frameCounter) / (double)framesPerBeat;		
		double frameEndBeatCount = beatCount + frameLenBeatCount;
		if (frameEndBeatCount > getLengthInBeats())
			frameEndBeatCount -= getLengthInBeats();

		// loop for each controller we need to interpolate
		MidiMessage* lastCtrlEvent = NULL;
		do 
		{
			lastCtrlEvent = NULL;
			
			// hunt for a controller event before now
			int i;
			for (i = 0;	i < sourceMidi.getNumEvents (); i++)
			{
				int timeStampInSeq = roundFloatToInt (sourceMidi.getEventTime (i) * framesPerBeat);
				int timeStamp = timeStampInSeq + (seqIndex * getLengthInBeats() * framesPerBeat);

				MidiMessage* midiMessage = &sourceMidi.getEventPointer (i)->message;
				if (timeStamp >= nextBlockFrameNumber || !midiMessage) 
					break; // event is after now, leave

				//if (midiMessage->isController() && (std::find(doneTheseControllers.begin(), doneTheseControllers.end(), midiMessage->getControllerNumber()) == doneTheseControllers.end()))
				//	lastCtrlEvent = midiMessage;
			}

			// hunt for a matching event after that one
			if (lastCtrlEvent)
			{
				// store the controller number so we know which controllers we've done
				doneTheseControllers.push_back(lastCtrlEvent->getControllerNumber());

				MidiMessage* nextCtrlEvent = NULL;
				for (;	i < sourceMidi.getNumEvents (); i++)
				{
					MidiMessage* midiMessage = &sourceMidi.getEventPointer (i)->message;
					if (midiMessage->isController() && midiMessage->getControllerNumber() == lastCtrlEvent->getControllerNumber())
					{
						nextCtrlEvent = midiMessage;
						break;
					}
				}
			
				// render an interpolated event!...
				if (nextCtrlEvent)
				{
					double bt = nextCtrlEvent->getTimeStamp();
					double at = lastCtrlEvent->getTimeStamp();
					double deltaBeats = bt - at;
					int a = lastCtrlEvent->getControllerValue();
					int b = nextCtrlEvent->getControllerValue();
					double now = beatCount + (frameEndBeatCount - beatCount) / 2.0;
					double interpRemainBeats = deltaBeats - (now - at);
					if (deltaBeats > 0)
					{
						double nextPart = interpRemainBeats / deltaBeats;
						nextPart = 1 - nextPart;
						double interpdVal = a + nextPart * (b - a);
						MidiMessage interpy = MidiMessage::controllerEvent(lastCtrlEvent->getChannel(), lastCtrlEvent->getControllerNumber(), static_cast<int>(interpdVal));
						midiBuffer->addEvent (interpy, (nextBlockFrameNumber - frameCounter) / 2);
					}
					else
					{
						DBG ("Negative delta beats when rendering automation!!");
			        }
				}
			
			} 
			
			// now we also need to do that again if there are multiple events per frame AND we are interpolating multiple times per frame
			// (at the moment only interpolating once per audio frame)
		} while (lastCtrlEvent != NULL);
	}
}
Exemplo n.º 7
0
MidiReader::TrackReaderImpl::TrackReaderImpl(MidiMessageSequence const & sequence)
	: sequence_(sequence)
	, count_(sequence.getNumEvents())
	, current_(0)
{}
MidiMessageSequence* MidiStochaster::createMelody(int minOctaveOffset, int maxOctaveOffset, double speedFactor) {
    
    int currentOctaveOffset;
    if (minOctaveOffset <= 0) {
        currentOctaveOffset = 0;
    } else { 
        currentOctaveOffset = minOctaveOffset;
    }
    
    int randInt1 = randomInt(100, 200);
    double stopProbability = (double) randInt1 / (randInt1 + 1);
    int randInt2 = randomInt(4, 10);
    double octaveSwitchProbability = (double) randInt2 / (randInt2 + 1);
    
    
    double currentTime = 0.0;
    MidiMessageSequence* melody = new MidiMessageSequence(starter);
    if (!goodSource) {
        return melody;
    }
    
    while (randomDouble(0,1) < stopProbability) {
        int notePitch = pitches->at(randomInt(0, pitches->size() - 1)) + 12 * currentOctaveOffset;
        while (notePitch < 0) {
            notePitch+=12;
            currentOctaveOffset++;
            minOctaveOffset++;
        }
        while (notePitch > 127) {
            notePitch-=12;
            currentOctaveOffset--;
            maxOctaveOffset--;
        }
        int noteVelocity = randomInt(lowVelocity, highVelocity);
        int noteLength = randomDouble(lowNoteLength, highNoteLength) * (1.0 / speedFactor);
        int nextRestLength;
        if (randomDouble(0,1) < negRestProbability) {
            nextRestLength = randomDouble(lowNegRestLength, highNegRestLength) * 1.0 / speedFactor;
        } else {
            nextRestLength = randomDouble(lowRestLength, highRestLength) * 1.0 / speedFactor;
        }
        
        MidiMessage noteDown = MidiMessage::noteOn(1, notePitch, (uint8_t) noteVelocity);
        noteDown.setTimeStamp(currentTime);
        MidiMessage noteUp = MidiMessage::noteOff(1, notePitch);
        noteUp.setTimeStamp(currentTime + noteLength);

        melody->addEvent(noteDown);
        melody->addEvent(noteUp);
        melody->updateMatchedPairs();
        
        currentTime += noteLength + nextRestLength;
        
        if (randomDouble(0,1) > octaveSwitchProbability) {
            currentOctaveOffset = randomInt(minOctaveOffset, maxOctaveOffset);
        }
    }
        
    return melody;
    
    
}
Exemplo n.º 9
0
void MidiThread::run() {
	midiPort = MidiOutput::openDevice(0);

	map<double, double>::iterator tempoIterator = tempos.begin();
	double tickLength = tempoIterator->second;
	double initTempo = 60000 / (tickLength * ppq);
	tempoIterator++;
	map<double, std::pair<int, int>>::iterator timeSigIterator = timeSigs.begin();
	int timeSigNumerator = timeSigIterator->second.first;
	int timeSigDenominator = timeSigIterator->second.second;
	timeSigIterator++;

	MidiMessage message;

	// MIDI click intro
	File clickFile("Click120.mid");
	ScopedPointer<FileInputStream> clickStream = clickFile.createInputStream();
	double eventTick;
	double prevTick = 0;
	double prevDelta = 0;
	int now = Time::getMillisecondCounter();
	if (clickStream) {
		click.readFrom(*clickStream);
		short clickPpq = click.getTimeFormat();
		MidiMessageSequence clickSequence = MidiMessageSequence();
		clickSequence = *click.getTrack(0);
		int i = 0;
		while (i < clickSequence.getNumEvents()) {
			message = clickSequence.getEventPointer(i)->message;
			eventTick = message.getTimeStamp();
			double origBpm = 60000 / (tickLength * clickPpq);
			double delta = prevDelta + ((eventTick - prevTick) * (origBpm / initTempo)) * tickLength;
			Time::waitForMillisecondCounter(now + delta);
			midiPort->sendMessageNow(message);
			i++;
			prevTick = eventTick;
			prevDelta = delta;
		}
	}

	now = Time::getMillisecondCounter();
	prevTick = 0;
	prevDelta = 0;
	int currentBar = 1;
	int currentBeat = 1;
	int currentTick = 0;
	int quartersPerBar = timeSigNumerator * (timeSigDenominator / 4);
	int tickStartOfBar = 0;
	int tickStartNextBar = quartersPerBar * ppq;
	currentBpm = initTempo;
	int i = 0;
	while (i < midiSequence.getNumEvents() && !threadShouldExit()) {
		std::stringstream ss;
		ss << currentBpm;
		content->updateBpm(ss.str());

		message = midiSequence.getEventPointer(i)->message;
		eventTick = message.getTimeStamp(); // number of midi ticks until note
		if (tempoIterator != tempos.end() && eventTick >= tempoIterator->first) {
			tickLength = tempoIterator->second;
			tempoIterator++;
		}
		if (timeSigIterator != timeSigs.end() && eventTick >= timeSigIterator->first) {
			timeSigNumerator = timeSigIterator->second.first;
			timeSigDenominator = timeSigIterator->second.second;
			quartersPerBar = timeSigNumerator * (4 / timeSigDenominator);
			timeSigIterator++;
		}
		if (eventTick >= tickStartNextBar) {
			tickStartOfBar = tickStartNextBar;
			tickStartNextBar = tickStartOfBar + quartersPerBar * ppq;
			currentBar = currentBar + static_cast<int> (std::floor((eventTick - tickStartOfBar) / (ppq * quartersPerBar))) + 1;
		}
		currentBeat = static_cast<int> (std::floor((eventTick - tickStartOfBar)/ ppq)) % timeSigNumerator + 1;
		currentTick = static_cast<int> (eventTick) % ppq;
		if (!message.isMetaEvent() && (currentTick == 0 || currentTick == 120 || currentTick == 240 || currentTick == 360)) {
			std::stringstream ss;
			ss << currentBar << ":" << currentBeat << ":" << setfill('0') << setw(3) << currentTick;
			content->updateBbt(ss.str());
		}

		double origBpm = 60000 / (tickLength * ppq);
		double delta = prevDelta + ((eventTick - prevTick) * (origBpm / currentBpm)) * tickLength;
		Time::waitForMillisecondCounter(now + delta);
		midiPort->sendMessageNow(message);
		i++;
		prevTick = eventTick;
		prevDelta = delta;
	}
	delete midiPort;
	return;
}