示例#1
0
void MidiSelectProcessor::processBlock (AudioSampleBuffer &buffer, MidiBuffer &midiMessages)
{
    // Do nothing to buffer; just let it pass through

    MidiBuffer inputMessages(midiMessages);
    midiMessages.clear();
    
    MidiBuffer::Iterator it(inputMessages);
    while (true) {
        MidiMessage message(0xf0);
        int samplePosition;
        if (!it.getNextEvent(message, samplePosition)) {
            break;
        }
        
        if (message.isNoteOn()) {
            if (findNextNote()) {
            	// We know it's safe to add to the list if findNextNote() returns true
                transformations[message.getNoteNumber()] = currentNote;
                message.setNoteNumber(currentNote);
                midiMessages.addEvent(message, samplePosition);
            }
            else {
                // This will just get skipped, but we must make note of that to also skip
                // the upcomming note off event
                transformations[message.getNoteNumber()] = -1;
            }
        }
        
        else if (message.isNoteOff()) {
            auto transformIt = transformations.find(message.getNoteNumber());
            if (transformIt == transformations.end()) {
                // I have no recollection of this note
                continue;
            }
            
            if (transformIt->second == -1) {
                // We discarded the note on, discard the note off too
                transformations.erase(transformIt);
                continue;
            }
            
            // Okay, make the note off match the note on, then add
            message.setNoteNumber(transformIt->second);
            midiMessages.addEvent(message, samplePosition);
            transformations.erase(transformIt);
        }
        
        else {
            // We don't mess with other events (yet), so pass on through
            midiMessages.addEvent(message, samplePosition);
        }
    }
}
示例#2
0
void GenericProcessor::addEvent(MidiBuffer& eventBuffer,
							    uint8 type,
							    int sampleNum,
							    uint8 eventId,
							    uint8 eventChannel,
							    uint8 numBytes,
							    uint8* eventData)
{
	uint8 *data = new uint8[4+numBytes];

	data[0] = type;    // event type
    data[1] = nodeId;  // processor ID automatically added
    data[2] = eventId; // event ID
    data[3] = eventChannel; // event channel
    memcpy(&data[4], eventData, numBytes);

    eventBuffer.addEvent(data, 		// spike data
                          sizeof(data), // total bytes
                          sampleNum);     // sample index

    //if (type == TTL)
    //	std::cout << "Adding event for channel " << (int) eventChannel << " with ID " << (int) eventId << std::endl;

	delete data;
}
void MidiKeyboardState::processNextMidiBuffer (MidiBuffer& buffer,
                                               const int startSample,
                                               const int numSamples,
                                               const bool injectIndirectEvents)
{
    MidiBuffer::Iterator i (buffer);
    MidiMessage message;
    int time;

    const ScopedLock sl (lock);

    while (i.getNextEvent (message, time))
        processNextMidiEvent (message);

    if (injectIndirectEvents)
    {
        MidiBuffer::Iterator i2 (eventsToAdd);
        const int firstEventToAdd = eventsToAdd.getFirstEventTime();
        const double scaleFactor = numSamples / (double) (eventsToAdd.getLastEventTime() + 1 - firstEventToAdd);

        while (i2.getNextEvent (message, time))
        {
            const int pos = jlimit (0, numSamples - 1, roundToInt ((time - firstEventToAdd) * scaleFactor));
            buffer.addEvent (message, startSample + pos);
        }
    }

    eventsToAdd.clear();
}
示例#4
0
void addCtrlrMidiMessageToBuffer (MidiBuffer &bufferToAddTo, CtrlrMidiMessage &m)
{
	for (int i=0; i<m.getNumMessages(); i++)
	{
		bufferToAddTo.addEvent (m.getReference(i).m, 1);
	}
}
void SoftSynthAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    MidiBuffer processedMidi;
    int time;
    MidiMessage m;
    
    for (MidiBuffer::Iterator i(midiMessages); i.getNextEvent(m, time);) {
        if (m.isNoteOn()) {
            m = MidiMessage::noteOn(m.getChannel(), m.getNoteNumber(), m.getVelocity());
            synth.keyPressed(m.getNoteNumber(), m.getVelocity());
        } else if (m.isNoteOff()) {
            m = MidiMessage::noteOff(m.getChannel(), m.getNoteNumber(), m.getVelocity());
            synth.keyReleased(m.getNoteNumber());
        }
        
        processedMidi.addEvent(m, time);
    }
    
    auto synthBuffer = synth.getNextBuffer(buffer.getNumSamples());
    float *leftData = buffer.getWritePointer(0);
    float *rightData = buffer.getWritePointer(1);
    for (int i = 0; i < buffer.getNumSamples(); ++i) {
        leftData[i] = synthBuffer[i];
        rightData[i] = synthBuffer[i];
    }
    
    midiMessages.swapWith(processedMidi);
}
//==============================================================================
void MidiManipulator::processEvents (MidiBuffer& midiMessages, const int blockSize)
{
    MidiBuffer midiOutput;

    if (! midiMessages.isEmpty ())
    {
		int timeStamp;
		MidiMessage message (0xf4, 0.0);
	    MidiBuffer::Iterator it (midiMessages);

        if (filter)
        {
	        while (it.getNextEvent (message, timeStamp))
	        {
                if (filter->filterEvent (message))
                    midiOutput.addEvent (message, timeStamp);
	        }
	    }
	    else
	    {
	        midiOutput = midiMessages;
	    }

        midiMessages.clear ();
    }

    if (transform)
    {
        transform->processEvents (midiOutput, blockSize);
    }

    midiMessages = midiOutput;
}
void
CfpluginAudioProcessor::MidiPanic(MidiBuffer& midiMessages)
{
	for(int i = 1; i <= 16; ++i) {
		midiMessages.addEvent(MidiMessage::allNotesOff(i), 0);
		midiMessages.addEvent(MidiMessage::allSoundOff(i), 0);
	}
}
//==============================================================================
void BeatboxVoxAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
	const auto totalNumInputChannels = getTotalNumInputChannels();
	const auto totalNumOutputChannels = getTotalNumOutputChannels();
	const auto sampleRate = getSampleRate();
	const auto numSamples = buffer.getNumSamples();

	//Reset the noise synth if triggered
	midiMessages.addEvent(MidiMessage::noteOff(1, noiseNoteNumber), 0);

	classifier.processAudioBuffer(buffer.getReadPointer(0), numSamples);

	
	//This is used for configuring the onset detector settings from the GUI
	if (classifier.noteOnsetDetected())
	{
		if (usingOSDTestSound.load())
		{
			triggerOSDTestSound(midiMessages);
		}
		else if (classifier.getNumBuffersDelayed() > 0)
		{
			triggerNoise(midiMessages);
		}
	}

	const auto sound = classifier.classify();

	switch (sound)
	{
		case soundLabel::KickDrum:
			triggerKickDrum(midiMessages);
			break;
		case soundLabel::SnareDrum:
			triggerSnareDrum(midiMessages);
			break;
		case soundLabel::HiHat:
			triggerHiHat(midiMessages);
			break;
		default: break;
	}


	/** Now classification complete clear the input buffer/signal. 
	 *	We only want synth response output, no a blend of input vocal
	 *	signal + synth output.
	 **/
	buffer.clear();

	if (usingOSDTestSound.load())
		osdTestSynth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());
	else
		drumSynth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());

	//Not outputting midi so clear after rendering synths
	midiMessages.clear();
}
示例#9
0
/**
* Send midi note off message into buffer at given sample position.
*/
void StepSequencer::sendMidiNoteOffMessage(MidiBuffer& midiMessages, int sample)
{
    if (currStepOnOff[static_cast<int>(params.seqLastPlayedStep.get())]->getStep() == eOnOffToggle::eOn)
    {
        MidiMessage m = MidiMessage::noteOff(1, lastPlayedNote);
        midiMessages.addEvent(m, sample);
    }
    seqNoteIsPlaying = false;
}
示例#10
0
void Loop::sendCurrentNoteToBuffer(MidiBuffer& buffer, int sample_number, int velocity)
{
	MidiMessage m = this->getEventPointer(currentIndex)->message;
	//playingNote[m.getNoteNumber()][m.getChannel()-1][0] = jlimit(0,127,m.getNoteNumber()+getTransposition());
	m.setNoteNumber(jlimit(0,127,m.getNoteNumber()+getTransposition()));
	m.setVelocity((((float)velocity*midiScaler * velocitySensitivity) + (1.f-velocitySensitivity)));
	if (outChannel>0) m.setChannel(outChannel);
	buffer.addEvent(m,sample_number);
	indexOfLastNoteOn=currentIndex;
}
示例#11
0
void GenericProcessor::setNumSamples(MidiBuffer& events, int sampleIndex) {

	uint8 data[2];

	data[0] = BUFFER_SIZE; 	// most-significant byte
    data[1] = nodeId; 		// least-significant byte

    events.addEvent(data, 		// spike data
                    2, 			// total bytes
                    sampleIndex); // sample index

}
void MidiMessageCollector::removeNextBlockOfMessages (MidiBuffer& destBuffer,
                                                      const int numSamples)
{
   #if JUCE_DEBUG
    jassert (hasCalledReset); // you need to call reset() to set the correct sample rate before using this object
   #endif

    jassert (numSamples > 0);

    auto timeNow = Time::getMillisecondCounterHiRes();
    auto msElapsed = timeNow - lastCallbackTime;

    const ScopedLock sl (midiCallbackLock);
    lastCallbackTime = timeNow;

    if (! incomingMessages.isEmpty())
    {
        int numSourceSamples = jmax (1, roundToInt (msElapsed * 0.001 * sampleRate));
        int startSample = 0;
        int scale = 1 << 16;

        const uint8* midiData;
        int numBytes, samplePosition;

        MidiBuffer::Iterator iter (incomingMessages);

        if (numSourceSamples > numSamples)
        {
            // if our list of events is longer than the buffer we're being
            // asked for, scale them down to squeeze them all in..
            const int maxBlockLengthToUse = numSamples << 5;

            if (numSourceSamples > maxBlockLengthToUse)
            {
                startSample = numSourceSamples - maxBlockLengthToUse;
                numSourceSamples = maxBlockLengthToUse;
                iter.setNextSamplePosition (startSample);
            }

            scale = (numSamples << 10) / numSourceSamples;

            while (iter.getNextEvent (midiData, numBytes, samplePosition))
            {
                samplePosition = ((samplePosition - startSample) * scale) >> 10;

                destBuffer.addEvent (midiData, numBytes,
                                     jlimit (0, numSamples - 1, samplePosition));
            }
        }
        else
        {
示例#13
0
/**
* Send midi note on message into buffer at given sample position.
*/
void StepSequencer::sendMidiNoteOnMessage(MidiBuffer & midiMessages, int sample)
{
    if (currStepOnOff[currSeqNote]->getStep() == eOnOffToggle::eOn)
    {
        // emphasis on step 1
        float seqVelocity = 0.5f;
        //if (seqNote == 0)
        //{
        //    seqVelocity = 0.85f;
        //}

        MidiMessage m = MidiMessage::noteOn(1, static_cast<int>(currMidiStepSeq[currSeqNote]->get()), seqVelocity);
        midiMessages.addEvent(m, sample);
    }
    seqNoteIsPlaying = true;
    params.seqLastPlayedStep.set(jmax(0.0f, jmin(static_cast<float>(currSeqNote), 7.0f)));
    lastPlayedNote = static_cast<int>(currMidiStepSeq[currSeqNote]->get());
}
示例#14
0
void MetronomeProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    const int numSamples = buffer.getNumSamples();
    int channel;

	// convert special metronome bip and bop (0xf2 00 and 0xf2 01) into note on/off messages

	MidiBuffer metronomeMidiBuffer;
	MidiBuffer::Iterator iter(midiMessages);
	MidiMessage message;
	int pos;
	while (iter.getNextEvent(message,pos))
	{
		if (message.getRawDataSize()==2 && message.isSongPositionPointer())
		{
			char raw[4] = {0,0,0,0};

			char* data = (char*)message.getRawData();
			if (data[1]==0)
			{
				// bip
				MidiMessage b = MidiMessage::noteOn(1,80,64.0f);
				memcpy(raw,b.getRawData(),4);
			}
			else
			{
				// bop
				MidiMessage b = MidiMessage::noteOn(1,70,64.0f);
				memcpy(raw,b.getRawData(),4);
			}

			if (raw[0])
			{
				MidiMessage m(raw[0],raw[1],raw[2]);
				//printf("m %d %d %d at %d\n",m.getRawData()[0],m.getRawData()[1],m.getRawData()[2],pos);

				metronomeMidiBuffer.addEvent(m,pos);
			}
		}
	}

    // and now get the synth to process these midi events and generate its output.
    synth.renderNextBlock (buffer, metronomeMidiBuffer, 0, numSamples);
}
void Pfm2AudioProcessor::handleIncomingMidiBuffer(MidiBuffer &buffer, int numberOfSamples) {
    if (!buffer.isEmpty()) {
        MidiBuffer newBuffer;
        MidiMessage midiMessage;
        int samplePosition;
        MidiBuffer::Iterator midiIterator(buffer);
        while (midiIterator.getNextEvent(midiMessage, samplePosition)) {
            bool copyMessageInNewBuffer = true;

            if (midiMessage.isController() && midiMessage.getChannel() == currentMidiChannel) {
                switch (midiMessage.getControllerNumber()) {
                case 99:
                    currentNrpn.paramMSB = midiMessage.getControllerValue();
                    copyMessageInNewBuffer = false;
                    break;
                case 98:
                    currentNrpn.paramLSB = midiMessage.getControllerValue();
                    copyMessageInNewBuffer = false;
                    break;
                case 6:
                    currentNrpn.valueMSB = midiMessage.getControllerValue();
                    copyMessageInNewBuffer = false;
                    break;
                case 38:
                {
                    currentNrpn.valueLSB = midiMessage.getControllerValue();
                    copyMessageInNewBuffer = false;
                    int param = (int)(currentNrpn.paramMSB << 7) + currentNrpn.paramLSB;
                    int value = (int)(currentNrpn.valueMSB << 7) + currentNrpn.valueLSB;

                    const MessageManagerLock mmLock;
                    handleIncomingNrpn(param, value);
                    break;
                }
                }
            }
            if (copyMessageInNewBuffer) {
                newBuffer.addEvent(midiMessage, samplePosition);
            }
        }
        buffer.swapWith(newBuffer);
    }
}
示例#16
0
  void getNextAudioBlock (AudioSourceChannelInfo const& bufferToFill)
  {
    int const numSamples = bufferToFill.numSamples;

    // the synth always adds its output
    //bufferToFill.clearActiveBufferRegion();

    m_midi.clear ();

    if (m_active)
    {
      double const samplesPerBeat = m_sampleRate * 60 / m_tempo;

      // Adjust phase so the beat is on or after the beginning of the output
      double beat;
      if (m_phase > 0)
        beat = 1 - m_phase;
      else
        beat = 0 - m_phase;

      // Set notes in midi buffer
      for (;;beat += 1)
      {
        // Calc beat pos
        int pos = static_cast <int> (beat * samplesPerBeat);

        if (pos < numSamples)
        {
          m_midi.addEvent (MidiMessage::noteOn (1, 84, 1.f), pos);
        }
        else
        {
          break;
        }
      }
    }

    m_synth.renderNextBlock (*bufferToFill.buffer,
                            m_midi,
                            0,
                            bufferToFill.numSamples);
  }
示例#17
0
/**
* If any seqStepNote changed or is muted then send noteOff message for the old note.
*/
void StepSequencer::midiNoteChanged(MidiBuffer & midiMessages)
{
    for (int i = 0; i < seqNumSteps; ++i)
    {
        // compare with current sequence
        if ((prevMidiStepSeq[i] != static_cast<int>(currMidiStepSeq[i]->get())) || (prevStepOnOff[i] != currStepOnOff[i]->getStep()))
        {
            if (i == static_cast<int>(params.seqLastPlayedStep.get()))
            {
                MidiMessage m = MidiMessage::noteOff(1, prevMidiStepSeq[i]);
                midiMessages.addEvent(m, 0);
            }
        }
    }

    // save new sequence
    for (int i = 0; i < 8; ++i)
    {
        prevMidiStepSeq[i] = static_cast<int>(currMidiStepSeq[i]->get());
        prevStepOnOff[i] = currStepOnOff[i]->getStep();
    }
}
示例#18
0
void CtrlrPanelProcessor::processBlock(MidiBuffer &midiMessages, MidiBuffer &leftoverBuffer, const AudioPlayHead::CurrentPositionInfo &info)
{
	if (owner.getMidiOptionBool(panelMidiInputFromHostCompare))
	{
		owner.getMIDIInputThread().handleMIDIFromHost(midiMessages);
	}

	leftoverBuffer.clear();

    processLua(midiMessages, info);

	MidiBuffer::Iterator i(midiMessages);
	MidiMessage m;
	int time;

	while (i.getNextEvent(m,time))
	{
		_MIN("VST INPUT", m, time);
		if (owner.getMidiOptionBool(panelMidiThruH2D) == true)
		{
			if (owner.getMidiOptionBool(panelMidiThruH2DChannelize))
			{
				m.setChannel (owner.getMidiChannel(panelMidiOutputChannelDevice));
			}

			owner.sendMidi(m);
		}

		if (owner.getMidiOptionBool(panelMidiThruH2H) == true)
		{
			if (owner.getMidiOptionBool(panelMidiThruH2HChannelize))
			{
				m.setChannel (owner.getMidiChannel(panelMidiOutputChannelHost));
			}

			leftoverBuffer.addEvent (m, time);
		}
	}
}
示例#19
0
/**
* Stop stepSequencer and reset not GUI variables.
*/
void StepSequencer::stopSeq(MidiBuffer& midiMessages)
{
    // stop and reset only if not already stopped
    if (!seqStopped)
    {
        params.seqLastPlayedStep.set(0.0f);
        currSeqNote = 0;
        lastPlayedNote = 0;
        seqNoteAdd = 1;
        nextPlaySample = 0;
        noteOffSample = 0;
        seqNextStep = 0.0;
        stopNoteTime = 0.0;
        lastPlayHeadPosition = 0.0;
        seqStopped = true;
        seqNoteIsPlaying = false;

        // stop all midimessages from sequencer
        MidiMessage m = MidiMessage::allNotesOff(1);
        midiMessages.addEvent(m, 0);
    }
}
示例#20
0
void GateTrigger::processBlock (AudioSampleBuffer& buffer, 
                                MidiBuffer& midiMessages)
{
    float threshold = library->getThreshold();
    int64 releaseTicks = library->getReleaseTicks();
    float velocityScale = library->getVelocityScale();
    
    int windowSize = buffer.getNumSamples();
    for (int i = 0; i < buffer.getNumSamples(); i += windowSize) {
        float rms = 0;
        for (int chan = 0; chan < buffer.getNumChannels(); chan++) {
            rms += buffer.getMagnitude (chan, i, jmin(windowSize, buffer.getNumSamples() - i)); 
        }
        rms = rms / buffer.getNumChannels() * 100;
        if (rms - lastRms > threshold) {
            if (Time::getHighResolutionTicks() - lastTriggerTick > releaseTicks) {
                Pattern* pattern = sequencer->getPattern();
                Instrument* instrument = pattern->getActiveInstrument();
                // play note
                float velocity = (rms - lastRms) / velocityScale;
                DBG("RMS: " + String(rms) + " lastRMS: " + String(lastRms) + " velocity: " + String(velocity));
                int noteNumber = instrument->getNoteNumber();
                MidiMessage m = MidiMessage::noteOn (1, noteNumber, velocity);
                midiMessages.addEvent (m, i);
                // insert into sequencer pattern
                int step = round(sequencer->getPreciseStep());
                step = step % pattern->getNumSteps();
                Cell* cell = pattern->getCellAt (0, step);
                delayedInserterThread->insertNote (cell, velocity, instrument);
                // Retrigger the reset timer
                resetTimer->retrigger();
                lastTriggerTick = Time::getHighResolutionTicks();
            }
        }
        lastRms = rms;
    }   
}
示例#21
0
void CtrlrPanelProcessor::processBlock(MidiBuffer &midiMessages, MidiBuffer &leftoverBuffer)
{	
	if (owner.getMidiOptionBool(panelMidiInputFromHostCompare))
	{
		owner.getMIDIInputThread().handleMIDIFromHost(midiMessages);
	}

	MidiBuffer::Iterator i(midiMessages);
	MidiMessage m;
	int time;

	while (i.getNextEvent(m,time))
	{		
		_MIN("VST INPUT", m);

		if (owner.getMidiOptionBool(panelMidiThruH2D) == true)
		{
			if (owner.getMidiOptionBool(panelMidiThruH2DChannelize))
			{
				m.setChannel (owner.getMidiChannel(panelMidiOutputChannelDevice));				
			}

			owner.sendMidi(m);
		}			

		if (owner.getMidiOptionBool(panelMidiThruH2H) == true)
		{
			if (owner.getMidiOptionBool(panelMidiThruH2HChannelize))
			{
				m.setChannel (owner.getMidiChannel(panelMidiOutputChannelHost));
			}

			leftoverBuffer.addEvent (m, m.getTimeStamp());
		}
	}
}
void Sequencer::processBlock (AudioSampleBuffer& buffer,
                              MidiBuffer& midiMessages)
{
	AudioPlayHead::CurrentPositionInfo pos (pluginAudioProcessor->lastPosInfo);	
	
	// If we aren't playing...
	if (! pos.isPlaying) {
		if (noteOffs.size() > 0) {
			// Send any upcoming note-off events
			Array<NoteOff*> notesToRemove; 
			for (int i = 0; i < noteOffs.size(); i++) {
				int noteNumber = noteOffs[i]->noteNumber;
				MidiMessage m2 = MidiMessage::noteOff (1, noteNumber);
				midiMessages.addEvent (m2, 0);			
				playingNotes.set (noteNumber, false);

				notesToRemove.add (noteOffs[i]);
			}
			for (int i = 0; i < notesToRemove.size(); i++) {
				// Remove the event from the note-off event list
				// (We do this in two steps so that the noteOffs array isn't modified inside a loop)
				noteOffs.removeObject (notesToRemove[i], true);
			}			
		}
		return;
	}
	
	double ppq = pos.ppqPosition;
	double timeInSeconds = pos.timeInSeconds;
	double bpm = pos.bpm;
	//if (primary) {
		SharedState::getInstance()->setPpqPosition (ppq);
		SharedState::getInstance()->setTimeInSeconds (timeInSeconds);
		SharedState::getInstance()->setBpm (bpm);
	//}
	
	/*
	 int numerator = pos.timeSigNumerator;
	 int denominator = pos.timeSigDenominator;
	 
	 const int ppqPerBar = (numerator * 4 / denominator); // e.g. 4 if 4/4
	 const double beats = (fmod (ppq, ppqPerBar) / ppqPerBar) * numerator;
	 
	 const int bar = ((int) ppq) / ppqPerBar + 1;
	 const int beat = ((int) beats) + 1;
	 const int ticks = ((int) (fmod (beats, 1.0) * 960.0));	
	 */
	
	double tickCountPrecise = fmod (ppq * speed * ticksPerCol, getTotalCols() * ticksPerCol);
	tickCount = (int)tickCountPrecise;
	
	lastPlayheadColPrecise = tickCountPrecise / ticksPerCol;
	jassert (lastPlayheadColPrecise >= 0.0)
	jassert (lastPlayheadColPrecise <= 16.0)
	//if (primary) {
		SharedState::getInstance()->setPlayheadColPrecise (lastPlayheadColPrecise);
	//}		
	
	if (tickCount != lastTickCount) {
		lastTickCount = tickCount;
		
		// Check if we should be degrading...
		int panelIndex = pluginAudioProcessor->getPanelIndex();
      int state = SharedState::getInstance()->getState(panelIndex);
      if (state == Panel::DEGRADING_SLOW ||
          state == Panel::DEGRADING_FAST) {
         // degrade at most once per tempo sweep, in column 0
         if (getPlayheadCol() == 0) {
            if (!columnZeroDegradeUpdate) {
               SharedState::getInstance()->degradeStep(panelIndex);
               columnZeroDegradeUpdate = true;
            }
         } else {
            columnZeroDegradeUpdate = false;
         }
      } else {
         columnZeroDegradeUpdate = false;
         if (state == Panel::ACTIVE) {
            if (SharedState::kDegradeAfterInactiveSec > 0 &&
                (SharedState::getInstance()->getLastTouchElapsedMs(panelIndex) >= 
                 SharedState::kDegradeAfterInactiveSec * 1000)) {
               DBG(String(Time::currentTimeMillis()) + " "
                   + "Start degrading panel " + String(panelIndex));
               SharedState::getInstance()->startDegrade(panelIndex);
            }
         }
      }
		
		// Update starfield if necessary
		if (SharedState::getInstance()->getStarFieldActive()) {
         // bug:67 - for production running, we could assert that the following is true:
         //    SharedState::getInstance()->allAttracting()
         // but that won't work if someone turns on the star field by hand via the sequencer GUI
			if (pluginAudioProcessor->getPanelIndex() == 0) {
				SharedState::getInstance()->updateStarField();
			}
		}
		
		bool playCol = false;  // play the current column of notes?
		float velocity = 0.9f;		
		
		// Swing...
		// If we're on an odd column
		if (getPlayheadCol() % 2 != 0) {
			// If we've waited for enough ticks for the swing
			if (tickCount == (getPlayheadCol() * ticksPerCol) + swingTicks) {
				playCol = true;
			}
		} else {
			// Else we're on an even column
			// If we're on the first tick of the column...
			if (tickCount % ticksPerCol == 0) {
				playCol = true;
			}
		}
		
		// Calculate the latency
		double beatsPerSec = bpm * speed * ticksPerCol / 60.0;
		double secPerBeat = 1.0 / beatsPerSec;	
		
		double tickOffset = tickCountPrecise - tickCount;
		int tickOffsetSamples = tickOffset * secPerBeat * sampleRate;
		tickOffsetSamples = jmax (buffer.getNumSamples() - tickOffsetSamples - 1, 0);
		
		// Send any upcoming note-off events
		Array<NoteOff*> notesToRemove; 
		for (int i = 0; i < noteOffs.size(); i++) {
			if (noteOffs[i]->tick == tickCount) {
				int noteNumber = noteOffs[i]->noteNumber;
				MidiMessage m2 = MidiMessage::noteOff (1, noteNumber);
				midiMessages.addEvent (m2, tickOffsetSamples);			
				playingNotes.set (noteNumber, false);

				notesToRemove.add (noteOffs[i]);
			}
		}
		for (int i = 0; i < notesToRemove.size(); i++) {
			// Remove the event from the note-off event list
			// (We do this in two steps so that the noteOffs array isn't modified inside a loop)
			noteOffs.removeObject (notesToRemove[i], true);
		}		
		
		// If we should play the current column of notes
		if (playCol) {
			int panelIndex = pluginAudioProcessor->getPanelIndex();
			int tabIndex = pluginAudioProcessor->getTabIndex();

			for (int i = 0; i < getTotalRows(); i++) {
				Cell* cell = getCellAt (panelIndex, tabIndex, i, getPlayheadCol());
            if (cell->isOn()) {
               int noteNumber = cell->getNoteNumber();
					// If this note is currently playing
					if (playingNotes[noteNumber] == true) {
						Array<NoteOff*> notesToRemove;
						// Remove any pending note-offs
						for (int j = 0; j < noteOffs.size(); j++) {
							if (noteOffs[j]->noteNumber == noteNumber) {
								notesToRemove.add (noteOffs[j]);
							}
						}
						for (int j = 0; j < notesToRemove.size(); j++) {
							noteOffs.removeObject (notesToRemove[j], true);
						}
						// Send a note-off before retriggering
						MidiMessage m = MidiMessage::noteOff (1, noteNumber);
						midiMessages.addEvent (m, tickOffsetSamples);
						playingNotes.set (noteNumber, false);

					}
					// Play this note
					MidiMessage m = MidiMessage::noteOn (1, noteNumber, velocity);
					midiMessages.addEvent (m, tickOffsetSamples);
					playingNotes.set (noteNumber, true);
					
					// Add an upcoming note-off event
					NoteOff* no;
					noteOffs.add (no = new NoteOff());
					no->tick = (tickCount + noteLength) % (ticksPerCol * getTotalCols());
					no->noteNumber = noteNumber;
				}
			}
		}
	}
}
//==============================================================================
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);
	}
}
示例#24
0
		virtual void menuItemSelected(int menuItemID, int)
		{
			if (menuItemID == 200)
			{
				WildcardFileFilter wildcardFilter("*.mid", String::empty, "Midi files");
				FileBrowserComponent browser(FileBrowserComponent::canSelectFiles | FileBrowserComponent::openMode, 
					lastOpenedFile.exists() ? lastOpenedFile : File(String("C:\\Users\\GeorgeKrueger\\Documents")), &wildcardFilter, nullptr);
				FileChooserDialogBox dialogBox("Open a midi file",
					"Please choose a midi file to open...",
					browser,
					false,
					Colours::lightgrey);

				if (dialogBox.show())
				{
					File selectedFile = browser.getSelectedFile(0);
					lastOpenedFile = selectedFile;
					FileInputStream fileStream(selectedFile);
					juce::MidiFile midiFile;
					midiFile.readFrom(fileStream);
					int numTracks = midiFile.getNumTracks();
					midiFile.convertTimestampTicksToSeconds();
					String msg;
					msg << "Opened midi file: " << selectedFile.getFileName() << " Tracks: " << numTracks << "\n";
					log(msg);

					for (int i = 0; i < numTracks; ++i)
					{
						const MidiMessageSequence* msgSeq = midiFile.getTrack(i);
						
						OwnedArray<PluginDescription> results;
						String plugFile = "C:\\VST\\FMMF.dll";
						VSTPluginFormat vstFormat;
						vstFormat.findAllTypesForFile(results, plugFile);
						if (results.size() > 0) {
							msg.clear();
							msg << "Found " << results.size() << " plugin(s) matching file " << plugFile << "\n";
							log(msg);

							int secsToRender = 10;
							double sampleRate = 44100;
							int totalSizeInSamples = static_cast<int>(44100 * secsToRender);
							AudioPluginInstance* plugInst = vstFormat.createInstanceFromDescription(*results[0], sampleRate, totalSizeInSamples);
							if (!plugInst) {
								msg.clear();
								msg << "Failed to load plugin " << plugFile << "\n";
								log(msg);
								continue;
							}

							int numInputChannels = plugInst->getTotalNumInputChannels();
							int numOutputChannels = plugInst->getTotalNumOutputChannels();
							msg.clear();
							msg << "Plugin input channels: " << numInputChannels << " output channels: " << numOutputChannels 
								<< " Current program: " << plugInst->getCurrentProgram() << "\n";
							log(msg);

							int maxChannels = std::max(numInputChannels, numOutputChannels);
							AudioBuffer<float> buffer(maxChannels, totalSizeInSamples);
							
							MidiBuffer midiMessages;
							for (int j = 0; j < msgSeq->getNumEvents(); ++j)
							{
								MidiMessageSequence::MidiEventHolder* midiEventHolder = msgSeq->getEventPointer(j);
								MidiMessage midiMsg = midiEventHolder->message;
								int samplePos = static_cast<int>(midiMsg.getTimeStamp() * sampleRate);
								midiMessages.addEvent(midiMsg, samplePos);
							}

							plugInst->prepareToPlay(sampleRate, totalSizeInSamples);
							plugInst->processBlock(buffer, midiMessages);

							/*File txtOutFile("C:\\Users\\GeorgeKrueger\\Documents\\GitHub\\soundserver2\\out.txt");
							FileOutputStream* txtOutStream = txtOutFile.createOutputStream();
							for (int j = 0; j < 44100; ++j)
							{
								float sample = buffer.getSample(0, j);
								txtOutStream->writeFloat(sample);
								txtOutStream->writeText(" ", true, false);
							}*/

							File outputFile("C:\\Users\\GeorgeKrueger\\Documents\\GitHub\\soundserver2\\out.wav");
							if (outputFile.exists()) {
								outputFile.deleteFile();
							}
							FileOutputStream* fileOutputStream = outputFile.createOutputStream();
							WavAudioFormat wavFormat;
							StringPairArray metadataValues;
							juce::AudioFormatWriter* wavFormatWriter = wavFormat.createWriterFor(
								fileOutputStream, sampleRate, 2, 16, metadataValues, 0);
							bool writeAudioDataRet = wavFormatWriter->writeFromAudioSampleBuffer(buffer, 0, buffer.getNumSamples());
							wavFormatWriter->flush();

							msg.clear();
							msg << "Done writing to output file " << outputFile.getFileName() << " . Write return value: " 
								<< (int)writeAudioDataRet << "\n";
							log(msg);

							delete wavFormatWriter;
							delete plugInst;
						}
						else {
							msg.clear();
							msg << "Could not find plugin from file " << plugFile << "\n";
							log(msg);
						}
					}
				}
			}
		}
//==============================================================================
void MidiTransform::processEvents (MidiBuffer& midiMessages, const int blockSize)
{
    int timeStamp;
    MidiMessage message (0xf4, 0.0);
    MidiBuffer::Iterator it (midiMessages);

    MidiBuffer midiOutput;

    switch (command)
    {
    case MidiTransform::KeepEvents:
            break;
    case MidiTransform::DiscardEvents:
        {
            midiMessages.clear ();
            break;
        }
    case MidiTransform::RemapChannel:
        {
            while (it.getNextEvent (message, timeStamp))
            {
                message.setChannel (channelNumber);
                midiOutput.addEvent (message, timeStamp);
            }
            midiMessages = midiOutput;
            break;
        }
    case MidiTransform::ScaleNotes:
        {
            while (it.getNextEvent (message, timeStamp))
            {
                if (message.isNoteOnOrOff ())
                {
                    message.setNoteNumber (roundFloatToInt (message.getNoteNumber () * noteScale));
                    midiOutput.addEvent (message, timeStamp);
                }
            }
            midiMessages = midiOutput;
            break;
        }
    case MidiTransform::InvertNotes:
        {
            while (it.getNextEvent (message, timeStamp))
            {
                if (message.isNoteOnOrOff ())
                {
                    message.setNoteNumber (127 - message.getNoteNumber ());
                    midiOutput.addEvent (message, timeStamp);
                }
            }
            midiMessages = midiOutput;
        }
    case MidiTransform::TransposeNotes:
        {
            while (it.getNextEvent (message, timeStamp))
            {
                if (message.isNoteOnOrOff ())
                {
                    message.setNoteNumber (jmax (0, jmin (127, message.getNoteNumber () - noteTranspose)));
                    midiOutput.addEvent (message, timeStamp);
                }
            }
            midiMessages = midiOutput;
            break;
        }
    case MidiTransform::ScaleVelocity:
        {
            while (it.getNextEvent (message, timeStamp))
            {
                if (message.isNoteOn ())
                {
                    message.setVelocity ((message.getVelocity () / 127.0f) * velocityScale);
                    midiOutput.addEvent (message, timeStamp);
                }
            }
            midiMessages = midiOutput;
            break;
        }
    case MidiTransform::InvertVelocity:
        {
            while (it.getNextEvent (message, timeStamp))
            {
                if (message.isNoteOn ())
                {
                    message.setVelocity ((uint8) (127 - message.getVelocity ()));
                    midiOutput.addEvent (message, timeStamp);
                }
            }
            midiMessages = midiOutput;
            break;
        }
    case MidiTransform::TransposeVelocity:
        {
            while (it.getNextEvent (message, timeStamp))
            {
                if (message.isNoteOn ())
                {
                    message.setVelocity (jmax (0, jmin (127, message.getVelocity () - velocityTranspose)));
                    midiOutput.addEvent (message, timeStamp);
                }
            }
            midiMessages = midiOutput;
            break;
        }
    case MidiTransform::TriggerCC:
        {
            break;
        }
    case MidiTransform::TriggerNote:
        {
            break;
        }
    }
}
示例#26
0
bool handlePluginRequest(const PluginRequestParameters &params, OutputStream &ostream,
                         ThreadSafePlugin *plugin = nullptr) {
    if (!plugin) {
        // It's very possible that all of this was a premature optimization.
        // For VSTs at least, code loading and caching is handled by ModuleHandle::findOrCreateModule,
        // and each instantiation only requires a couple of disc hits for working directory setting.
        // On the other hand, we want to make sure that each audio request has a "fresh" instance.
        // The easiest way to do this is by bypassing the instance pool and instantiating on demand.

#if PLUGIN_POOL_SIZE

        // Recurse with a plugin from the pool, locking on it.
        // Keep trying with a delay until a timeout occurs.
        const int TIMEOUT = 5000, WAIT = 200;
        int64 startTime = Time::currentTimeMillis();

        while (Time::currentTimeMillis() < startTime + TIMEOUT) {
            int i = 0;
            while ((plugin = pluginPool[i++])) {
                const ScopedTryLock pluginTryLock(plugin->crit);
                if (pluginTryLock.isLocked()) {
                    DBG << "Handling with plugin " << i << endl;
                    return handlePluginRequest(params, ostream, plugin);
                }
            }
            DBG << "Trying again in " << WAIT << endl;
            Thread::sleep(WAIT);
        }

        // If we were unable to obtain a lock, return failure.
        DBG << "Timeout" << endl;
        return false;

#else

        ThreadSafePlugin temporaryPlugin(createSynthInstance());
        return handlePluginRequest(params, ostream, &temporaryPlugin);

#endif
    }
    else {
        // Re-acquire or acquire the lock.
        const ScopedLock pluginLock(plugin->crit);
        AudioPluginInstance *instance = plugin->instance; // unmanaged, for simplicity

        // Attempt to reset the plugin in all ways possible.
        instance->reset();
        // Setting default parameters here causes miniTERA to become unresponsive to parameter settings.
        // It's possible that it's effectively pressing some interface buttons that change the editor mode entirely.
        // It's not necessary anyways if the plugin instance has been freshly created (see above).
        // pluginParametersOldNewFallback(instance, nullptr, &pluginDefaults); // note that the defaults may be empty
        instance->setCurrentProgram(0);

        // Load preset if specified, before listing or modifying parameters!
        if (params.presetNumber >= 0 && params.presetNumber < instance->getNumPrograms()) {
            DBG << "Setting program/preset: " << params.presetNumber << endl;
            instance->setCurrentProgram(params.presetNumber);
        }
        int currentProgram = instance->getCurrentProgram();
        DBG << "Current program/preset: " << currentProgram << " - " << instance->getProgramName(currentProgram) << endl;

        // Set parameters, starting with named, then indexed
        pluginParametersSet(instance, params.parameters);
        pluginParametersSetIndexed(instance, params.indexedParameters);

        // If parameters requested, output them and return
        if (params.listParameters) {
            DBG << "Rendering parameter list: # parameters " << instance->getNumPrograms() << endl;

            // Output each parameter setting in two places:
            // an indexed array and a dictionary by name
            // All DynamicObjects created will be freed when their var's leave scope.
            DynamicObject *outer = new DynamicObject();
            DynamicObject *innerParams = new DynamicObject();
            var indexedParamVar;
            {
                for (int i = 0, n = instance->getNumParameters(); i < n; ++i) {
                    String name = instance->getParameterName(i);
                    float val = instance->getParameter(i);
                    innerParams->setProperty(name, val);

                    DynamicObject *indexedInnerObj = new DynamicObject();
                    indexedInnerObj->setProperty("index", i);
                    indexedInnerObj->setProperty("name", name);
                    indexedInnerObj->setProperty("value", val);
                    indexedParamVar.append(var(indexedInnerObj)); // frees indexedInnerObj when this scope ends
                }
            }
            outer->setProperty(Identifier("parameters"), var(innerParams));
            outer->setProperty(Identifier("indexedParameters"), indexedParamVar);

            // List presets/programs.
            var progVar;
            {
                for (int i = 0, n = instance->getNumPrograms(); i < n; ++i) {
                    progVar.append(var(instance->getProgramName(i)));
                }
            }
            outer->setProperty(Identifier("presets"), progVar);

            var outerVar(outer);
            JSON::writeToStream(ostream, outerVar);
            // DBG << JSON::toString(outerVar, true /* allOnOneLine */) << endl;

            return true;
        }

        // Now attempt to render audio.
        AudioFormatManager formatManager;
        formatManager.registerBasicFormats();
        OptionalScopedPointer<AudioFormat> outputFormat(formatManager.findFormatForFileExtension(params.getFormatName()), false);
        if (!outputFormat) return false;

        instance->setNonRealtime(true);
        instance->prepareToPlay(params.sampleRate, params.blockSize);
        instance->setNonRealtime(true);

        // The writer takes ownership of the output stream; the  writer will delete it when the writer leaves scope.
        // Therefore, we pass a special pointer class that does not allow the writer to delete it.
        OutputStream *ostreamNonDeleting = new NonDeletingOutputStream(&ostream);
        ScopedPointer<AudioFormatWriter> writer(outputFormat->createWriterFor(ostreamNonDeleting,
                                                params.sampleRate, params.nChannels, params.bitDepth,
                                                StringPairArray(), 0));

        // Create a MIDI buffer
        MidiBuffer midiBuffer;
        midiBuffer.addEvent(MidiMessage::noteOn(params.midiChannel, (uint8)params.midiPitch, (uint8)params.midiVelocity),
                            0 /* time */);
        midiBuffer.addEvent(MidiMessage::allNotesOff(params.midiChannel),
                            params.noteSeconds * params.sampleRate);

        AudioSampleBuffer buffer(params.nChannels, params.blockSize);
        int numBuffers = (int)(params.renderSeconds * params.sampleRate / params.blockSize);
        for (int i = 0; i < numBuffers; ++i) {
            // DBG << "Processing block " << i << "..." << flush;
            instance->processBlock(buffer, midiBuffer);
            // DBG << " left RMS level " << buffer.getRMSLevel(0, 0, params.blockSize) << endl;
            writer->writeFromAudioSampleBuffer(buffer, 0 /* offset into buffer */, params.blockSize);
        }

        instance->reset();

        return true;
    }
}
示例#27
0
文件: midiOut.cpp 项目: Amcut/pizmidi
void MidiOutFilter::processBlock (AudioSampleBuffer& buffer,
                                   MidiBuffer& midiMessages)
{
    for (int i = 0; i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }

    const double SR=getSampleRate();
	const double iSR=1.0/SR;
    AudioPlayHead::CurrentPositionInfo pos;
    if (getPlayHead() != 0 && getPlayHead()->getCurrentPosition (pos))
    {
        if (memcmp (&pos, &lastPosInfo, sizeof (pos)) != 0)
        {
            if(param[kMTC]>=0.5f) {
                double frameRate=24.0;
                int mtcFrameRate=0;

                const double samplesPerPpq=60.0*SR/pos.bpm;
                const double samplesPerClock = SR/(4.0*frameRate);
                const long double seconds = (long double)(pos.ppqPosition*60.0f/pos.bpm) /*+ smpteOffset*/;
                const long double absSecs = fabs (seconds);
                const bool neg  = seconds < 0.0;

                int hours, mins, secs, frames;
                if (frameRate==29.97) {
                    int64 frameNumber = int64(absSecs*29.97);
                    frameNumber +=  18*(frameNumber/17982) + 2*(((frameNumber%17982) - 2) / 1798);

                    hours  = int((((frameNumber / 30) / 60) / 60) % 24);
                    mins   = int(((frameNumber / 30) / 60) % 60);
                    secs   = int((frameNumber / 30) % 60);
                    frames = int(frameNumber % 30);
                }
                else {
                    hours  = (int) (absSecs / (60.0 * 60.0));
                    mins   = ((int) (absSecs / 60.0)) % 60;
                    secs   = ((int) absSecs) % 60;
                    frames = (int)(int64(absSecs*frameRate) % (int)frameRate);
                }
                if (pos.isPlaying)
                {
                    double i=0.0;
                    const double clockppq = fmod(absSecs*frameRate*4.0,(long double)1.0);
                    samplesToNextMTC = (int)(samplesPerClock * (clockppq+i));
                    i+=1.0;
                    if (!wasPlaying) {
                        //this is so the song position pointer will be sent before any
                        //other data at the beginning of the song
                        MidiBuffer temp = midiMessages;
                        midiMessages.clear();

                        if (samplesToNextMTC<buffer.getNumSamples()) {
                            int mtcData;
                            switch (mtcNumber)
                            {
                            case 0: mtcData=frames&0x0f; break;
                            case 1: mtcData=(frames&0xf0)>>4; break;
                            case 2: mtcData=secs&0x0f; break;
                            case 3: mtcData=(secs&0xf0)>>4; break;
                            case 4: mtcData=mins&0x0f; break;
                            case 5: mtcData=(mins&0xf0)>>4; break;
                            case 6: mtcData=hours&0x0f; break;
                            case 7: mtcData=(hours&0x10)>>4 | mtcFrameRate; break;
                            }
                            MidiMessage midiclock(0xf1,(mtcNumber<<4)|(mtcData));
                            ++mtcNumber;
                            mtcNumber&=0x07;
                            midiMessages.addEvent(midiclock,samplesToNextMTC);
                            samplesToNextMTC = (int)(samplesPerClock * (clockppq+i));
                            i+=1.0;
                            startMTCAt=-999.0;
                            sendmtc=true;
                        }

                        midiMessages.addEvents(temp,0,buffer.getNumSamples(),0);
                    }
                    if (startMTCAt >-999.0 && (int)(samplesPerPpq*(startMTCAt-pos.ppqPosition))<buffer.getNumSamples()) {
                            samplesToNextMTC = (int)(samplesPerPpq*(startMTCAt-pos.ppqPosition));
                            int mtcData;
                            switch (mtcNumber)
                            {
                            case 0: mtcData=frames&0x0f; break;
                            case 1: mtcData=(frames&0xf0)>>4; break;
                            case 2: mtcData=secs&0x0f; break;
                            case 3: mtcData=(secs&0xf0)>>4; break;
                            case 4: mtcData=mins&0x0f; break;
                            case 5: mtcData=(mins&0xf0)>>4; break;
                            case 6: mtcData=hours&0x0f; break;
                            case 7: mtcData=(hours&0x10)>>4 | mtcFrameRate; break;
                            }
                            MidiMessage midiclock(0xf1,(mtcNumber<<4)|(mtcData));
                            ++mtcNumber;
                            mtcNumber&=0x07;
                            midiMessages.addEvent(midiclock,samplesToNextMTC);
                            samplesToNextMTC = (int)(samplesPerClock * (clockppq+i));
                            i+=1.0;
                            startMTCAt=-999.0;
                            sendmtc=true;
                    }
void CfpluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
	RTContext rt; // Debug RT stuff in debug mode

	auto timeAtStartOfBlock = time::now();

	{
		// This will allocate IFF there is an error.
		// Can't put the non-rt specifier within the while...
		NonRTSection nonRt;
		while (globals_.ErrorBuffer()->dequeue(errorString_)) {
			juce::NativeMessageBox::showMessageBoxAsync(
				juce::AlertWindow::WarningIcon,
				juce::String("Error!"),
				juce::String(errorString_.c_str()));
		}
	}

	/************************************************************************************/

	// Update UI on every run, TODO make this happen every n times?
	changeBroadcaster.sendChangeMessage();

	if (resetting_.load()) { return; }

	/************************************************************************************/

	if (!follower_) { return; }
	unsigned trackCount = follower_->StartNewBlock();

	if (trackCount == 0) {
		MidiPanic(midiMessages);
		return;
	}

	// Track 0 is supposed to be the tempo track
	for (unsigned i = 1; i < trackCount; ++i) {
		follower_->GetTrackEventsForBlock(i, eventBuffer_);
		auto events = eventBuffer_.AllEvents();
		events.ForEach([this, &midiMessages, i](samples_t sample, ScoreEventPtr message)
		{
			assert(sample.value() >= 0);
			assert(sample.value() < samplesPerBlock_);

			MidiMessage const & msg = midi_event_cast(message)->Message();

			// Prohibit all but note on and off for now 
			if (!msg.isNoteOnOrOff()) { 
				return;
			}

			// truncating is probably the right thing to do...
			midiMessages.addEvent(msg, static_cast<unsigned>(sample.value()));
		});
	}

	/*****************************************************************************************/

	// This is the place where you'd normally do the guts of your plugin's
    // audio processing...
	/*
    for (int channel = 0; channel < getNumInputChannels(); ++channel)
    {
        float* channelData = buffer.getSampleData (channel);
    }
	*/

    // In case we have more outputs than inputs, we'll clear any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
	/*
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }
	*/

	// However, we reset all channels
	for (int i = 0; i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }

	/******************************/

	time_quantity elapsedTime = time_cast<time_quantity>(time::now() - timeAtStartOfBlock);
	time_quantity blockSize((samplesPerBlock_ * score::samples) / (samplerate_ * score::samples_per_second));
	if (elapsedTime > (0.3 * blockSize)) {
		LOG("Possible xrun! Process callback took %1% (max: %2%)", elapsedTime, blockSize);
	}
}
示例#29
0
void LumaPlug::processBlock (AudioSampleBuffer& buffer,
                                   MidiBuffer& midiMessages)
{
	// we don't want any midi input events
	midiMessages.clear();
	
	bool isRunning = false;
	AudioPlayHead* playHead = getPlayHead();
	if (playHead)
	{
		//printf("playhead: 0x%x\n", playHead);
		AudioPlayHead::CurrentPositionInfo posInfo;
		playHead->getCurrentPosition(posInfo);
		isRunning = posInfo.isPlaying || posInfo.isRecording;
		luma_->SetBPM(posInfo.bpm);
	}
	
	if (isRunning && !luma_->IsRunning())
	{
		std::string error;
		bool setScriptOK = luma_->SetScript(scriptText_.toUTF8(), error);
		if (!setScriptOK && getActiveEditor())
		{
			((LumaPlugEditor*)getActiveEditor())->Log(error.c_str());
		}
//		else if (getActiveEditor())
//		{
//			((LumaPlugEditor*)getActiveEditor())->Log("Play");
//		}
		luma_->Start();
	}
	else if (!isRunning && luma_->IsRunning())
	{
		luma_->Stop();
//		if (getActiveEditor())
//		{
//			((LumaPlugEditor*)getActiveEditor())->Log("Stop");
//		}
	}

    if (luma_->IsRunning())
	{
		double sampleRate = getSampleRate();
		int numSamples = buffer.getNumSamples();
		float elapsed = (float(numSamples) / float(sampleRate)) * 1000.0;
		//printf("Elapsed: %f\n", elapsed);
		vector<shared_ptr<LumaEvent> > events;
		vector<float> offsets;
		luma_->Update(elapsed, events, offsets);
		
		if (events.size() > 0)
		{
			for (unsigned int i = 0; i < events.size(); i++)
			{
				//printf("New Event.  Offset = %d, OffsetSamples = %d, Type = %d\n\n", 
				//	offsets[i], midiEvent->deltaFrames, events[i]->GetType());
				
				int eventOffset = lroundf( ( float(offsets[i]) / 1000.0 ) * sampleRate );
				
				if (events[i]->GetType() == kLumaEvent_NoteOn)
				{
					NoteOnEvent* noteOn = (NoteOnEvent*)events[i].get();
					MidiMessage msg = MidiMessage::noteOn(1, noteOn->GetPitch(), (juce::uint8)noteOn->GetVelocity());
					midiMessages.addEvent(msg, eventOffset);
				}
				else if (events[i]->GetType() == kLumaEvent_NoteOff)
				{
					NoteOffEvent* noteOff = (NoteOffEvent*)events[i].get();
					MidiMessage msg = MidiMessage::noteOff(1, noteOff->GetPitch());
					midiMessages.addEvent(msg, eventOffset);
				}
				else
				{
					fprintf(stderr, "LumaVST: Unknown event type: %d\n", events[i]->GetType());
				}
			}
			
			// clear the used luma events
			events.clear();
		}
	}
	
	/*
	Simple test of sending midi from the plugin
	
	static int count = 0;
	count += buffer.getNumSamples();
	if (count >= 20000)
	{
		//MidiMessage msg = MidiMessage::noteOff(0, 60);
		//midiMessages.addEvent(msg, 0);
	
		MidiMessage msg = MidiMessage::noteOn(1, 60, (juce::uint8)100);
		midiMessages.addEvent(msg, 0);
		
		count = 0;
	}
	*/
}
示例#30
0
void MiditoOscAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    static float cv[8], shiftcv[8];
    static bool _calibMode;
    
    MidiBuffer processedMidi;
    MidiMessage m;
    int time;
    
    char oscBuffer[IP_MTU_SIZE];
    osc::OutboundPacketStream p(oscBuffer, IP_MTU_SIZE);
    
    if (calibMode) // Calibration Mode A440Hz(MIDI number 69)
    {
        p << osc::BeginBundleImmediate
        << osc::BeginMessage( "/fader1" )
        << calibMap[69] << osc::EndMessage
        << osc::BeginMessage( "/fader2" )
        << calibMap[69] << osc::EndMessage
        << osc::BeginMessage( "/fader3" )
        << calibMap[69] << osc::EndMessage
        << osc::BeginMessage( "/fader4" )
        << calibMap[69] << osc::EndMessage
        << osc::BeginMessage( "/fader5" )
        << calibMap[69] << osc::EndMessage
        << osc::BeginMessage( "/fader6" )
        << calibMap[69] << osc::EndMessage
        << osc::BeginMessage( "/fader7" )
        << calibMap[69] << osc::EndMessage
        << osc::BeginMessage( "/fader8" )
        << calibMap[69] << osc::EndMessage
        << osc::BeginMessage( "/gate1" )
        << 1 << osc::EndMessage
        << osc::BeginMessage( "/gate2" )
        << 1 << osc::EndMessage
        << osc::EndBundle;
        
        sendOSCData(p);
        
        _calibMode = true;
        
        return;
        
    } else {
        
        if (_calibMode)
        {
            p << osc::BeginBundleImmediate
            << osc::BeginMessage( "/gate1" )
            << 0 << osc::EndMessage
            << osc::BeginMessage( "/gate2" )
            << 0 << osc::EndMessage
            << osc::EndBundle;
            
            sendOSCData(p);
            
            _calibMode = false;
            
        }
    }
    
    for (MidiBuffer::Iterator i (midiMessages); i.getNextEvent (m, time);)
    {
        p.Clear();
        usleep(30);
        
        if (m.isNoteOn())
        {
            if (monoMode) // mono Mode
            {
                uint32_t midiCh = m.getChannel();
                
                if (midiCh == 0 || midiCh > 7)
                {
                    midiCh = 1;
                }
                
                cv[midiCh - 1] = calibMap[m.getNoteNumber()];
                
                switch (midiCh)
                {
                    case 1:
                        p << osc::BeginMessage("/fader1")
                        << cv[0] << osc::EndMessage;
                        break;
                        
                    case 2:
                        p << osc::BeginMessage("/fader2")
                        << cv[1] << osc::EndMessage;
                        break;
                        
                    case 3:
                        p << osc::BeginMessage("/fader3")
                        << cv[2] << osc::EndMessage;
                        break;
                        
                    case 4:
                        p << osc::BeginMessage("/fader4")
                        << cv[3] << osc::EndMessage;
                        break;
                        
                    case 5:
                        p << osc::BeginMessage("/fader5")
                        << cv[4] << osc::EndMessage;
                        break;
                        
                    case 6:
                        p << osc::BeginMessage("/fader6")
                        << cv[5] << osc::EndMessage;
                        break;
                        
                    case 7:
                        p << osc::BeginMessage("/fader7")
                        << cv[6] << osc::EndMessage;
                        break;
                        
                    case 8:
                        p << osc::BeginMessage("/fader8")
                        << cv[7] << osc::EndMessage;
                        break;
                        
                    default:
                        break;
                }
                
                sendOSCData(p);
                
            } else if (shiftMode) { // shift Mode
                
                cv[0] = calibMap[m.getNoteNumber()];
                
                for (int i = 7; i > 0; i--)
                {
                    shiftcv[i] = shiftcv[i-1];
                }
                
                p << osc::BeginBundleImmediate
                << osc::BeginMessage( "/fader1" )
                << cv[0] << osc::EndMessage
                << osc::BeginMessage( "/fader2" )
                << shiftcv[1] << osc::EndMessage
                << osc::BeginMessage( "/fader3" )
                << shiftcv[2] << osc::EndMessage
                << osc::BeginMessage( "/fader4" )
                << shiftcv[3] << osc::EndMessage
                << osc::BeginMessage( "/fader5" )
                << shiftcv[4] << osc::EndMessage
                << osc::BeginMessage( "/fader6" )
                << shiftcv[5] << osc::EndMessage
                << osc::BeginMessage( "/fader7" )
                << shiftcv[6] << osc::EndMessage
                << osc::BeginMessage( "/fader8" )
                << shiftcv[7] << osc::EndMessage
                << osc::BeginMessage( "/gate1" )
                << 1 << osc::EndMessage
                << osc::BeginMessage( "/gate2" )
                << 1 << osc::EndMessage
                << osc::EndBundle;
                
                sendOSCData(p);
                
                shiftcv[0] = cv[0];
                
            } else { // poly Mode
                
                cv[ch] = calibMap[m.getNoteNumber()];
                
                if (currentMaxPoly == 1)
                {
                    cv[1] = cv[0];
                }
                
                p << osc::BeginBundleImmediate
                << osc::BeginMessage( "/fader1" )
                << cv[0] << osc::EndMessage
                << osc::BeginMessage( "/fader2" )
                << cv[1] << osc::EndMessage
                << osc::BeginMessage( "/fader3" )
                << cv[2] << osc::EndMessage
                << osc::BeginMessage( "/fader4" )
                << cv[3] << osc::EndMessage
                << osc::BeginMessage( "/fader5" )
                << cv[4] << osc::EndMessage
                << osc::BeginMessage( "/fader6" )
                << cv[5] << osc::EndMessage
                << osc::BeginMessage( "/fader7" )
                << m.getFloatVelocity() << osc::EndMessage
                << osc::BeginMessage( "/gate1" )
                << 1 << osc::EndMessage
                << osc::BeginMessage( "/gate2" )
                << 1 << osc::EndMessage
                << osc::EndBundle;
                
                sendOSCData(p);
                
                ch++;
                gateCount++;
                
                if (ch >= currentMaxPoly)
                {
                    ch = 0;
                }
                
            }
            
        } else if (m.isNoteOff()) {
            
            if (monoMode)
            {
                switch (m.getChannel())
                {
                    case 1:
                        p << osc::BeginMessage( "/gate1" )
                        << 0 << osc::EndMessage;
                        break;
                        
                    case 2:
                        p << osc::BeginMessage( "/gate2" )
                        << 0 << osc::EndMessage;
                        break;
                        
                    case 3:
                        p << osc::BeginMessage( "/gate3" )
                        << 0 << osc::EndMessage;
                        break;
                        
                    case 4:
                        p << osc::BeginMessage( "/gate4" )
                        << 0 << osc::EndMessage;
                        break;
                        
                    default:
                        break;
                }
                
                sendOSCData(p);
                
            } else if (shiftMode) {
                
                p << osc::BeginBundleImmediate
                << osc::BeginMessage( "/gate1" )
                << 0 << osc::EndMessage
                << osc::BeginMessage( "/gate2" )
                << 0 << osc::EndMessage
                << osc::EndBundle;
                
                sendOSCData(p);
                
            } else {
                
                gateCount --;
                
                if (gateCount <= 0)
                {
                    p << osc::BeginBundleImmediate
                    << osc::BeginMessage( "/gate1" )
                    << 0 << osc::EndMessage
                    << osc::BeginMessage( "/gate2" )
                    << 0 << osc::EndMessage
                    << osc::EndBundle;
                    
                    sendOSCData(p);
                    
                    gateCount = 0;
                }
                
                ch--;
                
                if (ch == -1)
                {
                    ch = 0;
                }
                
            }
            
        } else if (m.isControllerOfType(1)) { // Modulation Wheel
            
            float modulation = m.getControllerValue();
            
            if (!monoMode && !shiftMode)
            {
                p << osc::BeginMessage("/fader8")
                << (modulation / 127) << osc::EndMessage;
                
                sendOSCData(p);
            }
            
        }
        
        processedMidi.addEvent (m, time);
    }
    
    midiMessages.swapWith (processedMidi);
    
    buffer.clear();
    
    for (int channel = 0; channel < getNumInputChannels(); ++channel)
    {
        float* channelData = 0;
    }
}