void filesDropped (const StringArray& files, int /*x*/, int /*y*/) override
 {
     lastFileDropped = File (files[0]);
     sendChangeMessage();
 }
String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup,
                                                const bool treatAsChosenDevice)
{
    jassert (&newSetup != &currentSetup);    // this will have no effect

    if (newSetup == currentSetup && currentAudioDevice != nullptr)
        return String::empty;

    if (! (newSetup == currentSetup))
        sendChangeMessage();

    stopDevice();

    const String newInputDeviceName (numInputChansNeeded == 0 ? String::empty : newSetup.inputDeviceName);
    const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName);

    String error;
    AudioIODeviceType* type = getCurrentDeviceTypeObject();

    if (type == nullptr || (newInputDeviceName.isEmpty() && newOutputDeviceName.isEmpty()))
    {
        deleteCurrentDevice();

        if (treatAsChosenDevice)
            updateXml();

        return String::empty;
    }

    if (currentSetup.inputDeviceName != newInputDeviceName
         || currentSetup.outputDeviceName != newOutputDeviceName
         || currentAudioDevice == nullptr)
    {
        deleteCurrentDevice();
        scanDevicesIfNeeded();

        if (newOutputDeviceName.isNotEmpty()
             && ! type->getDeviceNames (false).contains (newOutputDeviceName))
        {
            return "No such device: " + newOutputDeviceName;
        }

        if (newInputDeviceName.isNotEmpty()
             && ! type->getDeviceNames (true).contains (newInputDeviceName))
        {
            return "No such device: " + newInputDeviceName;
        }

        currentAudioDevice = type->createDevice (newOutputDeviceName, newInputDeviceName);

        if (currentAudioDevice == nullptr)
            error = "Can't open the audio device!\n\nThis may be because another application is currently using the same device - if so, you should close any other applications and try again!";
        else
            error = currentAudioDevice->getLastError();

        if (error.isNotEmpty())
        {
            deleteCurrentDevice();
            return error;
        }

        if (newSetup.useDefaultInputChannels)
        {
            inputChannels.clear();
            inputChannels.setRange (0, numInputChansNeeded, true);
        }

        if (newSetup.useDefaultOutputChannels)
        {
            outputChannels.clear();
            outputChannels.setRange (0, numOutputChansNeeded, true);
        }

        if (newInputDeviceName.isEmpty())
            inputChannels.clear();

        if (newOutputDeviceName.isEmpty())
            outputChannels.clear();
    }

    if (! newSetup.useDefaultInputChannels)
        inputChannels = newSetup.inputChannels;

    if (! newSetup.useDefaultOutputChannels)
        outputChannels = newSetup.outputChannels;

    currentSetup = newSetup;

    currentSetup.sampleRate = chooseBestSampleRate (newSetup.sampleRate);
    currentSetup.bufferSize = chooseBestBufferSize (newSetup.bufferSize);

    error = currentAudioDevice->open (inputChannels,
                                      outputChannels,
                                      currentSetup.sampleRate,
                                      currentSetup.bufferSize);

    if (error.isEmpty())
    {
        currentDeviceType = currentAudioDevice->getTypeName();

        currentAudioDevice->start (&callbackHandler);

        currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
        currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
        currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
        currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();

        for (int i = 0; i < availableDeviceTypes.size(); ++i)
            if (availableDeviceTypes.getUnchecked (i)->getTypeName() == currentDeviceType)
                *(lastDeviceTypeConfigs.getUnchecked (i)) = currentSetup;

        if (treatAsChosenDevice)
            updateXml();
    }
    else
    {
        deleteCurrentDevice();
    }

    return error;
}
//==============================================================================
void JucerDocument::changed()
{
    sendChangeMessage();
    IntrojucerApp::getCommandManager().commandStatusChanged();
    startTimer (800);
}
Beispiel #4
0
void xsync::run()
{
	timeElapsed = 0;
	timeNow = 0;
	midiQuarterNote = midiEighthNote = midiSixteenthNote = 0;
	midiTicks = 0;

	/* async updates, like GUI */
	if (updateAsync)
	{
		((AsyncUpdater *)updateAsync)->triggerAsyncUpdate();
	}

	/* sync updates, like midi manager */
	sendChangeMessage (this);

	while (1)
	{
		timeNow =  Time::getMillisecondCounter();
		Time::waitForMillisecondCounter (timeNow + 3);

		timeElapsed = timeElapsed + (Time::getMillisecondCounter() - timeNow);

		if (timeElapsed >= timeMidiTick)
		{
			if (threadShouldExit())
			{
				stopSync();
				return;
			}

			if (midiTicks == 6 || midiTicks == 12 || midiTicks == 18 || midiTicks == 0)
			{
				midiSixteenthNote++;

				if (midiSixteenthNote == 2 || midiSixteenthNote == 4)
				{
					midiEighthNote++;

					if (midiEighthNote == 2 || midiEighthNote == 4)
					{
						midiQuarterNote++;

						if (midiQuarterNote == 4)
						{
							midiQuarterNote = 0;
						}
						
						if (midiEighthNote == 4)
							midiEighthNote = 0;
					}
				}

				if (midiSixteenthNote == 4)
					midiSixteenthNote = 0;

				/* async updates, like GUI */
				if (updateAsync)
				{
					((AsyncUpdater *)updateAsync)->triggerAsyncUpdate();
				}

				/* sync updates, like midi manager */
				sendChangeMessage (this);
			}

			timeElapsed = 0;
			
			midiTicks++;

			if (midiTicks == 23)
				midiTicks = 0;
		}

		if (threadShouldExit())
		{
			stopSync();
			return;
		}
	}
}
void DemoJuceFilter::processBlock (AudioSampleBuffer& buffer,
                                   MidiBuffer& midiMessages)
{
/*
    // for each of our input channels, we'll attenuate its level by the
    // amount that our volume parameter is set to.
    for (int channel = 0; channel < getNumInputChannels(); ++channel)
    {
        buffer.applyGain (channel, 0, buffer.getNumSamples(), gain);
        
        // mix in opposite ratio of noise (i.e. generator)
        float* sampleData = buffer.getSampleData(channel);
         for (int sample = 0; sample < buffer.getNumSamples(); sample++)
            sampleData[sample] = (rand() / static_cast<float>(RAND_MAX)) * (1.0 - gain) + sampleData[sample];
    }

    // 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());
    }
*/
    // if any midi messages come in, use them to update the keyboard state object. This
    // object sends notification to the UI component about key up/down changes
    keyboardState.processNextMidiBuffer (midiMessages,
                                         0, buffer.getNumSamples(),
                                         true);

    // have a go at getting the current time from the host, and if it's changed, tell
    // our UI to update itself.
    AudioPlayHead::CurrentPositionInfo pos;

    if (getPlayHead() != 0 && getPlayHead()->getCurrentPosition (pos))
    {
        if (memcmp (&pos, &lastPosInfo, sizeof (pos)) != 0)
        {
            lastPosInfo = pos;
            sendChangeMessage (this);
        }
    }
    else
    {
        zeromem (&lastPosInfo, sizeof (lastPosInfo));
        lastPosInfo.timeSigNumerator = 4;
        lastPosInfo.timeSigDenominator = 4;
        lastPosInfo.bpm = 120;
    }
    
    if (ptrPlug && ladspa)
    {
      int blockSize = buffer.getNumSamples();
      
        // convert midi messages internally
        midiManager.convertMidiMessages (midiMessages, blockSize);

        // connect ports
//        for (int i = 0; i < ins.size (); i++)
//            ladspa->connect_port (plugin, ins [i], inputBuffer->getSampleData (i));
        for (int i = 0; i < outs.size (); i++)
		{
            ladspa->connect_port (plugin, outs [i], buffer.getSampleData (i));
//			std::cerr << " connecting output " << i << std::endl;
		}

        if (ptrPlug->run_synth)
        {
            ptrPlug->run_synth (plugin,
                                blockSize,
                                midiManager.getMidiEvents (),
                                midiManager.getMidiEventsCount ());

			// now paste the data into the right channel
			// not generic, this assumes we are a mono plugin and we've claimed 2 output channels
			buffer.copyFrom(1, 0, buffer, 0, 0, blockSize);			

			return;
        }
        else if (ptrPlug->run_synth_adding)
        {
            buffer.clear ();
            ptrPlug->run_synth_adding (plugin,
                                       blockSize,
                                       midiManager.getMidiEvents (),
                                       midiManager.getMidiEventsCount ());

			// now paste the data into the right channel
			// not generic, this assumes we are a mono plugin and we've claimed 2 output channels
			buffer.copyFrom(1, 0, buffer, 0, 0, blockSize);			

			return;
        }

        // run ladspa if present as 
        if (ladspa->run)
        {
            ladspa->run (plugin, blockSize);
        }
        else if (ladspa->run_adding)
        {
            buffer.clear ();
            ladspa->run_adding (plugin, blockSize);
        }
        else
        {
            buffer.clear ();
        }
		
    }
    
}
void FileBasedDocument::changed()
{
    changedSinceSave = true;
    sendChangeMessage();
}
Beispiel #7
0
void CtrlrSysExEditor::labelTextChanged (Label* labelThatHasChanged)
{
    sendChangeMessage();
}
void CabbageEnvelopeHandleComponent::mouseUp (const MouseEvent& e)
{
    changeMessage = "updateOnMouseUp";
    sendChangeMessage();
}
void MumuAudioFlangerAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    //Get BPM/////////////////
    AudioPlayHead::CurrentPositionInfo pos; //temp position to store current ops
    
    //If playhead is active then store its position info in temporary position object
    if (getPlayHead() != nullptr && getPlayHead()->getCurrentPosition(pos)){
        // If our BPM has changed, print our bpm
        if (pos.bpm != lastPosInfo.bpm) {
            //std::cout << pos.bpm << std::endl;
        }
        lastPosInfo = pos;
    }
    ///////////////////////////
    
    // In case we have more outputs than inputs, this code clears any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    // I've added this to avoid people getting screaming feedback
    // when they first compile the plugin, but obviously you don't need to
    // this code if your algorithm already fills all the output channels.
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
        buffer.clear (i, 0, buffer.getNumSamples());

    // 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.getWritePointer (channel);
        m_bufferSize = buffer.getNumSamples();

        for ( int i = 0; i < buffer.getNumSamples(); i++ )
        {
            if(channel == 0)
            {
                float lfoValue = 0;
                
                if (button1 == 1)
                {
                    lfoValue = SineLFOL.calcSineLFO(centerValue, m_fModDepth);
                }
                
                if (button2 == 1)
                {
                    lfoValue = TriLFOL.calcTriLFO(centerValue, m_fModDepth);
                }
                
                FourPDelayL.setDelayTime(m_sampleRate, lfoValue);
                FourPDelayL.setPlayheads();
                channelData[i] = FourPDelayL.process(channelData[i]);
                
                channelData[i] = (m_HPF_Left.doBiQuad(channelData[i]) * -1) + m_LPF_Left.doBiQuad(channelData[i]);
            }
            else if(channel == 1)
            {
                float lfoValue = 0;
                
                if (button1 == 1)
                {
                    lfoValue = SineLFOR.calcSineLFO(centerValue, m_fModDepth);
                }
                
                if (button2 == 1)
                {
                    lfoValue = TriLFOR.calcTriLFO(centerValue, m_fModDepth);
                }

                FourPDelayR.setDelayTime(m_sampleRate, lfoValue);
                FourPDelayR.setPlayheads();
                channelData[i] = FourPDelayR.process(channelData[i]);

                channelData[i] = (m_HPF_Right.doBiQuad(channelData[i]) * -1) + m_LPF_Right.doBiQuad(channelData[i]);
            }
        }
     }
    
    currentSampleBuffer = buffer;
    sendChangeMessage();

}
Beispiel #10
0
void MidiControllerAutomationHandler::restoreFromValueTree(const ValueTree &v)
{
	if (v.getType() != Identifier("MidiAutomation")) return;

	clear();

	for (int i = 0; i < v.getNumChildren(); i++)
	{
		ValueTree cc = v.getChild(i);

		int controller = cc.getProperty("Controller", 1);

		auto& aArray = automationData[controller];

		AutomationData a;

		a.ccNumber = controller;
		a.processor = ProcessorHelpers::getFirstProcessorWithName(mc->getMainSynthChain(), cc.getProperty("Processor"));
		a.macroIndex = cc.getProperty("MacroIndex");

		auto attributeString = cc.getProperty("Attribute", a.attribute).toString();

		const bool isParameterId = attributeString.containsAnyOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
		
		// The parameter was stored correctly as ID
		if (isParameterId && a.processor.get() != nullptr)
		{
			const Identifier pId(attributeString);

			for (int j = 0; j < a.processor->getNumParameters(); j++)
			{
				if (a.processor->getIdentifierForParameterIndex(j) == pId)
				{
					a.attribute = j;
					break;
				}
			}
		}
		else
		{
			// This tries to obtain the correct id.
			auto presetVersion = v.getRoot().getProperty("Version").toString();

			const Identifier pId = UserPresetHelpers::getAutomationIndexFromOldVersion(presetVersion, attributeString.getIntValue());

			if (pId.isNull())
			{
				a.attribute = attributeString.getIntValue();
			}
			else
			{
				for (int j = 0; j < a.processor->getNumParameters(); j++)
				{
					if (a.processor->getIdentifierForParameterIndex(j) == pId)
					{
						a.attribute = j;
						break;
					}
				}
			}
		}

		double start = cc.getProperty("Start");
		double end = cc.getProperty("End");
		double skew = cc.getProperty("Skew", a.parameterRange.skew);
		double interval = cc.getProperty("Interval", a.parameterRange.interval);

		auto fullStart = cc.getProperty("FullStart", start);
		auto fullEnd = cc.getProperty("FullEnd", end);

		a.parameterRange = NormalisableRange<double>(start, end, interval, skew);
		a.fullRange = NormalisableRange<double>(fullStart, fullEnd, interval, skew);
		
		a.used = true;
		a.inverted = cc.getProperty("Inverted", false);

		aArray.addIfNotAlreadyThere(a);
	}

	sendChangeMessage();

	refreshAnyUsedState();
}
void MumuAudioFlangerAudioProcessor::releaseResources()
{
    // When playback stops, you can use this as an opportunity to free up any
    // spare memory, etc.
    sendChangeMessage();
}
void KnownPluginList::removeType (const int index)
{
    types.remove (index);
    sendChangeMessage();
}
void MidiKeyboardComponent::resized()
{
    int w = getWidth();
    int h = getHeight();

    if (w > 0 && h > 0)
    {
        if (orientation != horizontalKeyboard)
            std::swap (w, h);

        blackNoteLength = roundToInt (h * 0.7f);

        int kx2, kw2;
        getKeyPos (rangeEnd, kx2, kw2);

        kx2 += kw2;

        if ((int) firstKey != rangeStart)
        {
            int kx1, kw1;
            getKeyPos (rangeStart, kx1, kw1);

            if (kx2 - kx1 <= w)
            {
                firstKey = (float) rangeStart;
                sendChangeMessage();
                repaint();
            }
        }

        const bool showScrollButtons = canScroll && (((int) firstKey) > rangeStart || kx2 > w + xOffset * 2);

        scrollDown->setVisible (showScrollButtons);
        scrollUp->setVisible (showScrollButtons);

        xOffset = 0;

        if (showScrollButtons)
        {
            const int scrollButtonW = jmin (12, w / 2);

            if (orientation == horizontalKeyboard)
            {
                scrollDown->setBounds (0, 0, scrollButtonW, getHeight());
                scrollUp->setBounds (getWidth() - scrollButtonW, 0, scrollButtonW, getHeight());
            }
            else if (orientation == verticalKeyboardFacingLeft)
            {
                scrollDown->setBounds (0, 0, getWidth(), scrollButtonW);
                scrollUp->setBounds (0, getHeight() - scrollButtonW, getWidth(), scrollButtonW);
            }
            else
            {
                scrollDown->setBounds (0, getHeight() - scrollButtonW, getWidth(), scrollButtonW);
                scrollUp->setBounds (0, 0, getWidth(), scrollButtonW);
            }

            int endOfLastKey, kw;
            getKeyPos (rangeEnd, endOfLastKey, kw);
            endOfLastKey += kw;

            float mousePositionVelocity;
            const int spaceAvailable = w - scrollButtonW * 2;
            const int lastStartKey = remappedXYToNote (Point<int> (endOfLastKey - spaceAvailable, 0), mousePositionVelocity) + 1;

            if (lastStartKey >= 0 && ((int) firstKey) > lastStartKey)
            {
                firstKey = (float) jlimit (rangeStart, rangeEnd, lastStartKey);
                sendChangeMessage();
            }

            int newOffset = 0;
            getKeyPos (((int) firstKey), newOffset, kw);
            xOffset = newOffset - scrollButtonW;
        }
        else
        {
            firstKey = (float) rangeStart;
        }

        repaint();
    }
}
void AudioDeviceManager::audioDeviceListChanged()
{
    sendChangeMessage();
}
void RemoteDirectoryListBoxModel::setCURLSession(CURLEasySession *sessionToControl)
{
	curlSession = sessionToControl;
	setContents(curlSession->getDirectoryListing());
	sendChangeMessage();
}
Beispiel #16
0
void SmugMug::clearLogFile()
{
	smugLog.clear();
	sendChangeMessage();
}
void CtrlrUpdateManager::checkForUpdates()
{
	sendChangeMessage();
}
Beispiel #18
0
void Value::ValueSource::handleAsyncUpdate()
{
    sendChangeMessage (true);
}
Beispiel #19
0
void PianoRoll::mouseUp (const MouseEvent& e)
{
	int highnote,lownote;
	if (lasso.getWidth()>0) 
	{
		lownote = (int)((float)(getHeight()-lasso.getY())*128.f/(float)getHeight());
		highnote = (int)((float)(getHeight()-(lasso.getY()+lasso.getHeight()))*128.f/(float)getHeight());
		if (lownote>highnote) swapVariables(lownote,highnote);
		for (int index=0;index<(sequence->getNumEvents());index++) {
			MidiMessage m = sequence->getEventPointer(index)->message;
			DBG("eventtime=" + String(sequence->getEventTime(index)));
			if (m.isNoteOn()) {DBG("note=" + String(m.getNoteNumber()));}
			DBG("lassostart=" + String(pixelsToPpq((float)lasso.getX(),false)));
			DBG("lassoend=" + String(pixelsToPpq((float)(lasso.getX()+lasso.getWidth()),false)));
			if (m.isNoteOn() 
				&& sequence->getEventTime(index)>=pixelsToPpq((float)lasso.getX(),false) 
				&& sequence->getEventTime(index)<=pixelsToPpq((float)(lasso.getX()+lasso.getWidth()),false)
				&& m.getNoteNumber()>=lownote 
				&& m.getNoteNumber()<=highnote)
			{
				addToSelection(sequence->getEventPointer(index));
			}
		}
		lasso.setSize(0,0);
		repaint();
		noteLayer->repaint();
	}
	if (hoveringNoteIndex != No_Note) {
		if (hoveringNoteIndex<-2) hoveringNoteIndex+=9999;
		if (e.mods.isPopupMenu() && hoveringNoteIndex!=-2)
		{
			//right click, delete notes
			plugin->getCallbackLock().enter();
			for (int i=selectedNotes.size();--i>=0;)
				sequence->deleteEvent(sequence->getIndexOf(selectedNotes.getUnchecked(i)),true);			
			sequence->updateMatchedPairs();
			plugin->getCallbackLock().exit();
			clearSelection();
		}
		else {
			if (draggingNoteTimeDelta!=0 || draggingNoteTransposition!=0)
			{
				plugin->getCallbackLock().enter();
				if (draggingNoteTimeDelta!=0.0) {
					for (int i=0;i<selectedNotes.size();i++) {
						selectedNotes.getUnchecked(i)->message.addToTimeStamp(draggingNoteTimeDelta);
						selectedNotes.getUnchecked(i)->noteOffObject->message.addToTimeStamp(draggingNoteTimeDelta);
						//sequence->moveEvent(sequence->getIndexOf(selectedNotes.getUnchecked(i)),draggingNoteTimeDelta,true);
					}
					draggingNoteTimeDelta=0.0;
				}
				if (draggingNoteTransposition!=0) {
					for (int i=0;i<selectedNotes.size();i++)
						sequence->transposeEvent(sequence->getIndexOf(selectedNotes.getUnchecked(i)),draggingNoteTransposition);
					draggingNoteTransposition=0;
				}
				sequence->updateMatchedPairs(true);
				plugin->getCallbackLock().exit();
			}
			else if (wasResizing || e.mods.isAltDown())
			{
				//resize notes
				wasResizing=false;
				for (int i=selectedNoteLengths.size();--i>=0;)
				{
					if (selectedNotes.getUnchecked(i)!=0 && selectedNotes.getUnchecked(i)->noteOffObject!=0) {
						selectedNoteLengths.getReference(i).updateLength();
					}
					else {
						selectedNotes.remove(i);
						selectedNoteLengths.remove(i);
					}
				}
				plugin->getCallbackLock().enter();
				sequence->updateMatchedPairs(true);
				plugin->getCallbackLock().exit();
			}
		}
		hoveringNoteIndex = No_Note;
		hoveringNote=0;
		sendChangeMessage();
		noteLayer->repaint();
	}
}
void PatternRecording::recordPattern(MidiBuffer &midiMessages, const int &numSamples)
{
    // if we are recording the pattern, just rip the
    // MIDI messages from the incoming buffer
    if (isPatternRecording)
    {
        // get the iterator for the incoming buffer
        // so we can check through the messages
        MidiBuffer::Iterator i(midiMessages);
        MidiMessage message (0xf4, 0.0);
        int time;

        // if we are still during the precount, do nothing
        if (patternPrecountPosition > numSamples)
            patternPrecountPosition -= numSamples;

        // if the precount finishes during this buffer
        else if (patternPrecountPosition > 0)
        {
            // TODO: overdub could be option here?
            midiPattern.clear();

            const int numSamplesToAdd = numSamples - patternPrecountPosition;

            // DBG("#1 recording " << numSamplesToAdd << " of midi, pos: " << patternPrecountPosition);

            // get messages from the main MIDI message queue
            while(i.getNextEvent(message, time))
            {
                // and add them if they occur after the precount runs out
                if (time > patternPrecountPosition)
                {
                    midiPattern.addEvent(message, time - patternPrecountPosition);

                    // store noteOffs to fire at end
                    if (message.isNoteOn())
                    {
                        MidiMessage tempNoteOff = MidiMessage::noteOff(message.getChannel(), message.getNoteNumber(), message.getVelocity());
                        noteOffs.addEvent(tempNoteOff, 0);
                    }
                }
            }

            // the precount has finished
            patternPrecountPosition = 0;
            // we are now numSamplesToAdd into the buffer
            patternPosition = numSamplesToAdd;
        }
        else
        {
            // if we are during recording (and not near the end), just
            // add the current input into the record buffer
            if (numSamples + patternPosition < patternLengthInSamples)
            {
                // DBG("#2 recording " << numSamples << " of midi, pos: " << patternPosition);

                // get messages from the main MIDI message queue
                while(i.getNextEvent(message, time))
                {
                    midiPattern.addEvent(message, time + patternPosition);

                    // store noteOffs to fire at end
                    if (message.isNoteOn())
                    {
                        MidiMessage tempNoteOff = MidiMessage::noteOff(message.getChannel(), message.getNoteNumber(), message.getVelocity());
                        noteOffs.addEvent(tempNoteOff, 0);
                    }
                }

                //midiPattern.addEvents(midiMessages, 0, numSamples, -patternPosition);
                patternPosition += numSamples;
            }
            // otherwise we are finishing up
            else
            {
                const int numSamplesLeftToRecord = patternLengthInSamples - patternPosition;

                // add remaining messages from the main MIDI message queue
                while(i.getNextEvent(message, time))
                {
                    if (time < numSamplesLeftToRecord)
                        midiPattern.addEvent(message, time + patternPosition);

                    // store noteOffs to fire at end
                    if (message.isNoteOn())
                    {
                        MidiMessage tempNoteOff = MidiMessage::noteOff(message.getChannel(), message.getNoteNumber(), message.getVelocity());
                        noteOffs.addEvent(tempNoteOff, 0);
                    }
                }

                // add the note offs to clear any "phantom notes"
                midiPattern.addEvents(noteOffs, 0, 1, patternLengthInSamples - 1);

                // we are no longer recording
                isPatternRecording = false;

                // if we finish recording, let any listeners know
                // so they can redraw representations of the pattern
                sendChangeMessage();

                DBG("pattern " << patternBank << " finished recording.");


                // start playing back from the start straight away
                isPatternStopping = false;
                isPatternPlaying = true;
                patternPosition = 0;

                // fill the remaining buffer with the newly recorded sequence
                const int samplesRemaining = numSamples - numSamplesLeftToRecord;
                if (patternPosition + samplesRemaining < patternLengthInSamples)
                {
                    midiMessages.addEvents(midiPattern, patternPosition, samplesRemaining, numSamplesLeftToRecord);
                    patternPosition += samplesRemaining;
                }

            }

            // Let the PatternStripControl know to recache pattern
            sendChangeMessage();
        }
    }
}
void DirectoryContentsList::changed()
{
    sendChangeMessage();
}
 void valueChanged (Value&) override    { sendChangeMessage (true); }
Beispiel #23
0
//==============================================================================
bool UndoManager::perform (UndoableAction* const command_, const String& actionName)
{
    if (command_ != 0)
    {
        ScopedPointer<UndoableAction> command (command_);

        if (actionName.isNotEmpty())
            currentTransactionName = actionName;

        if (reentrancyCheck)
        {
            jassertfalse;    // don't call perform() recursively from the UndoableAction::perform() or
                             // undo() methods, or else these actions won't actually get done.

            return false;
        }
        else if (command->perform())
        {
            OwnedArray<UndoableAction>* commandSet = transactions [nextIndex - 1];

            if (commandSet != 0 && ! newTransaction)
            {
                UndoableAction* lastAction = commandSet->getLast();

                if (lastAction != 0)
                {
                    UndoableAction* coalescedAction = lastAction->createCoalescedAction (command);

                    if (coalescedAction != 0)
                    {
                        command = coalescedAction;
                        totalUnitsStored -= lastAction->getSizeInUnits();
                        commandSet->removeLast();
                    }
                }
            }
            else
            {
                commandSet = new OwnedArray<UndoableAction>();
                transactions.insert (nextIndex, commandSet);
                transactionNames.insert (nextIndex, currentTransactionName);
                ++nextIndex;
            }

            totalUnitsStored += command->getSizeInUnits();
            commandSet->add (command.release());
            newTransaction = false;

            while (nextIndex < transactions.size())
            {
                const OwnedArray <UndoableAction>* const lastSet = transactions.getLast();

                for (int i = lastSet->size(); --i >= 0;)
                    totalUnitsStored -= lastSet->getUnchecked (i)->getSizeInUnits();

                transactions.removeLast();
                transactionNames.remove (transactionNames.size() - 1);
            }

            while (nextIndex > 0
                   && totalUnitsStored > maxNumUnitsToKeep
                   && transactions.size() > minimumTransactionsToKeep)
            {
                const OwnedArray <UndoableAction>* const firstSet = transactions.getFirst();

                for (int i = firstSet->size(); --i >= 0;)
                    totalUnitsStored -= firstSet->getUnchecked (i)->getSizeInUnits();

                jassert (totalUnitsStored >= 0); // something fishy going on if this fails!

                transactions.remove (0);
                transactionNames.remove (0);
                --nextIndex;
            }

            sendChangeMessage();

            return true;
        }
    }

    return false;
}
 void valueChanged (Value&)
 {
     sendChangeMessage (true);
 }
void LoopMachine::getNextAudioBlockFixedBpm(const AudioSourceChannelInfo& bufferToFill) {
    auto& transport = audioEngine.getTransport();
    bool mainTransportPlaying = transport.isPlaying();
    if (fixedBpmTransport.isPlaying() != mainTransportPlaying) {
        if (mainTransportPlaying)
            fixedBpmTransport.play();
        else
            fixedBpmTransport.stop();
    }
    
    fixedBpmTransport.updateTransport(bufferToFill.numSamples);
    
    bufferToFill.clearActiveBufferRegion();
    
    if (fixedBpmTransport.isPlaying()) {
        float frameStartTicks = fixedBpmTransport.getFrameStartTicks();
        float frameEndTicks = fixedBpmTransport.getFrameEndTicks();
        
        float nextTick = (float) ((int)frameStartTicks + 1);
        float fadeLengthTicks = fixedBpmTransport.millisToTicks(FADE_TIME_MS);
        
        float fadeStartTicks = nextTick - fadeLengthTicks;
        float fadeEndTicks = nextTick;
        
        if (frameStartTicks < fadeStartTicks && frameEndTicks >= fadeStartTicks)
            drainRingBuffer();
//        std::cout << "MPD: CPP: LoopMachine::getNextAudioBlock: reality check! " << ((int)nextTick/4) << std::endl;
        for (int groupIx = 0; groupIx < groupIxToLoopInfo.size(); groupIx++) {
            
            int state = audioState[groupIx];
            int prevState = prevAudioState[groupIx];
            
            if (state == LOOP_INACTIVE && prevState == LOOP_INACTIVE) {
                // we were doing nothing last period, and we're still doing nothing: do nothing
            } else if (state == LOOP_INACTIVE && prevState != LOOP_INACTIVE) {
                // for this loop group, we are fading out: going from an active loop to silence.
                processFadeOut(groupIx, prevState, frameStartTicks, frameEndTicks, fadeStartTicks, fadeEndTicks, bufferToFill);
            } else if (!wasPlaying || (state != LOOP_INACTIVE && prevState == LOOP_INACTIVE)) {
                // for this loop group, we are fading in: going from silence to signal.
				setReaderPos(groupIx, state, fadeStartTicks, frameStartTicks);
                processFadeIn(groupIx, state, frameStartTicks, frameEndTicks, fadeStartTicks, fadeEndTicks, bufferToFill);
            } else if (prevState != state) {
                // for this loop group, the loop being played has switched: do a crossfade
                processFadeOut(groupIx, prevState, frameStartTicks, frameEndTicks, fadeStartTicks, fadeEndTicks, bufferToFill);
				setReaderPos(groupIx, state, fadeStartTicks, frameStartTicks);
                processFadeIn(groupIx, state, frameStartTicks, frameEndTicks, fadeStartTicks, fadeEndTicks, bufferToFill);
            } else {
                // we're playing the same thing as in the last period.
				if (!wasPlaying) {
                    auto src = (*groupIxToLoopInfo[groupIx])[state];
                    src->reader->setNextReadPosition(0);
                }
               processBlock(groupIx, state, 0, bufferToFill.numSamples, bufferToFill);
            }
        }
        
        if (frameStartTicks < fadeEndTicks && frameEndTicks >= fadeEndTicks) {
			bool changes = false;
			for (int groupIx = 0; groupIx < groupIxToLoopInfo.size(); groupIx++) {
				int state = audioState[groupIx];
				
				if (state != LOOP_INACTIVE) {
					auto type = (*groupIxToLoopInfo[groupIx])[state]->type;
					auto src = (*groupIxToLoopInfo[groupIx])[state]->reader;
					
					if (type == LoopType::ONE_SHOT && audioState[groupIx] != LOOP_INACTIVE && src != nullptr && src->getNextReadPosition() >= src->getTotalLength()) {
						// (groupIx, prevState) is done playing.
						// now we need to plop a message in the ring buffer
						
						audioState[groupIx] = LOOP_INACTIVE;
						userState[groupIx] = LOOP_INACTIVE;
						int ix = ++endReserveIx & RINGBUF_SIZE_M1; // == ++reserveIx % RINGBUF_SIZE
						endringbuf[ix][0] = groupIx;
						endringbuf[ix][1] = state;
						endCommitIx++;
						changes = true;
						src->setNextReadPosition(0);
//						std::cout << "MPD: handling messaages audio thread" << std::endl;
					}
				}
			}
			if (changes)
				sendChangeMessage();
			
            std::memcpy(prevAudioState, audioState, sizeof(audioState));
            wasPlaying = true;
        }
        
//        bufferToFill.buffer->applyGain(0, 0, bufferToFill.numSamples, 0.5);
//        bufferToFill.buffer->applyGain(1, 0, bufferToFill.numSamples, 0.5);
        
//        wasPlaying = true;
    }
    
    if (wasPlaying && !fixedBpmTransport.isPlaying())
        wasPlaying = false;
}