//==============================================================================
void LoopingAudioSource::setLoopTimes (double startTime, double endTime)
{
    jassert (endTime > startTime); // end time has to be after start!
    
    {
        const ScopedLock sl (loopPosLock);
        
        loopStartTime = startTime;
        loopEndTime = endTime;
        
        loopStartSample = (int64) (startTime * currentSampleRate);
        loopEndSample = (int64) (endTime * currentSampleRate);
    }

    // need to update read position based on new limits
    setNextReadPosition (getNextReadPosition());
}
void AudioTransportSource::setPosition (double newPosition)
{
    if (sampleRate > 0.0)
        setNextReadPosition ((int64) (newPosition * sampleRate));
}
void AudioTransportSourceMod::setPosition (double newPosition)
{
    if (sampleRate > 0.0)
        setNextReadPosition (roundToInt (newPosition * sampleRate));
}
Exemple #4
0
void CDPlayer::sliderValueChanged(Slider* sliderThatWasMoved)
{
    // Possible loss of precision is acceptable for very large values because user can't select specific value that precise.
    setNextReadPosition(static_cast<int64>(sliderThatWasMoved->getValue()));
}
Exemple #5
0
CDPlayer::CDPlayer(MixerComponent* mixer, OutputChannelNames* outputChannelNames, SoloBusSettings& soloBusSettings, TimeSliceThread& thread, PluginLoader& pluginLoader, float gain, bool solo, bool mute)
    : m_mixer(mixer)
    , m_outputChannelNames(outputChannelNames)
    , m_soloBusSettings(soloBusSettings)
    , m_gain(1.0f)
    , m_solo(solo)
    , m_soloMute(false)
    , m_mute(mute)
    , m_pluginLoader(pluginLoader)
    , m_thread(thread)
    , m_playButton("Play")
    , m_pauseButton("Pause")
    , m_stopButton("Stop")
    , m_skipBackwardButton("Skip Backward")
    , m_skipForwardButton("Skip Forward")
    , m_configureButton("Configure")
#if JUCE_WINDOWS
    , m_ejectButton("Eject")
#endif
    , m_remappingAudioSource(&m_transportSource, soloBusSettings, false)
    , m_digitalDisplay(String::empty, "00:00:00")
    , m_slider(Slider::LinearHorizontal, Slider::NoTextBox)
    , m_tracksTable([&](int trackIndex) {
        setNextReadPosition(m_reader->getPositionOfTrackStart(trackIndex));
        m_transportSource.start();
        startTimer(50);
        m_pluginLoader.playingStateChanged(getName().toRawUTF8(), true);
    })
{
    // play button
    Image normalImage = ImageFileFormat::loadFrom(BinaryData::mediaplaybackstart_png, BinaryData::mediaplaybackstart_pngSize);
    m_playButton.addListener(this);
    m_playButton.setEnabled(false);
    m_playButton.setImages(true, true, true,
                            normalImage, 0.7f, Colours::transparentBlack,
                            normalImage, 1.0f, Colours::transparentBlack,
                            normalImage, 1.0f, Colours::pink.withAlpha(0.8f),
                            0.0f);
    addAndMakeVisible(m_playButton);

    // pause button
    m_pauseButton.addListener(this);
    m_pauseButton.setEnabled(false);
    normalImage = ImageFileFormat::loadFrom(BinaryData::mediaplaybackpause_png, BinaryData::mediaplaybackpause_pngSize);
    m_pauseButton.setImages(true, true, true,
                             normalImage, 0.7f, Colours::transparentBlack,
                             normalImage, 1.0f, Colours::transparentBlack,
                             normalImage, 1.0f, Colours::pink.withAlpha(0.8f),
                             0.0f);
    addAndMakeVisible(m_pauseButton);

    // stop button
    m_stopButton.addListener(this);
    m_stopButton.setEnabled(false);
    normalImage = ImageFileFormat::loadFrom(BinaryData::mediaplaybackstop_png, BinaryData::mediaplaybackstop_pngSize);
    m_stopButton.setImages(true, true, true,
                            normalImage, 0.7f, Colours::transparentBlack,
                            normalImage, 1.0f, Colours::transparentBlack,
                            normalImage, 1.0f, Colours::pink.withAlpha(0.8f),
                            0.0f);
    addAndMakeVisible(m_stopButton);

    // skip backward button
    m_skipBackwardButton.addListener(this);
    m_skipBackwardButton.setEnabled(false);
    normalImage = ImageFileFormat::loadFrom(BinaryData::mediaskipbackward_png, BinaryData::mediaskipbackward_pngSize);
    m_skipBackwardButton.setImages(true, true, true,
                                    normalImage, 0.7f, Colours::transparentBlack,
                                    normalImage, 1.0f, Colours::transparentBlack,
                                    normalImage, 1.0f, Colours::pink.withAlpha(0.8f),
                                    0.0f);
    addAndMakeVisible(m_skipBackwardButton);

    // skip forward button
    m_skipForwardButton.addListener(this);
    m_skipForwardButton.setEnabled(false);
    normalImage = ImageFileFormat::loadFrom(BinaryData::mediaskipforward_png, BinaryData::mediaskipforward_pngSize);
    m_skipForwardButton.setImages(true, true, true,
                                   normalImage, 0.7f, Colours::transparentBlack,
                                   normalImage, 1.0f, Colours::transparentBlack,
                                   normalImage, 1.0f, Colours::pink.withAlpha(0.8f),
                                   0.0f);
    addAndMakeVisible(m_skipForwardButton);

#if JUCE_WINDOWS
    // eject button
    m_ejectButton.addListener(this);
    m_ejectButton.setEnabled(false);
    normalImage = ImageFileFormat::loadFrom(BinaryData::mediaeject_png, BinaryData::mediaeject_pngSize);
    m_ejectButton.setImages(true, true, true,
                             normalImage, 0.7f, Colours::transparentBlack,
                             normalImage, 1.0f, Colours::transparentBlack,
                             normalImage, 1.0f, Colours::pink.withAlpha(0.8f),
                             0.0f);
    addAndMakeVisible(m_ejectButton);
#endif

    // configuration button
    normalImage = ImageFileFormat::loadFrom(BinaryData::configure_png, BinaryData::configure_pngSize);
    m_configureButton.setImages(true, true, true,
                                 normalImage, 0.7f, Colours::transparentBlack,
                                 normalImage, 1.0f, Colours::transparentBlack,
                                 normalImage, 1.0f, Colours::pink.withAlpha(0.8f),
                                 0.0f);
    addAndMakeVisible(m_configureButton);
    m_configureButton.addMouseListener(this, false);

    // playback time display
    addAndMakeVisible(m_digitalDisplay);

    // CD combo box
    m_availableCDsComboBox.addListener(this);
    addAndMakeVisible(m_availableCDsComboBox);

    addAndMakeVisible(m_slider);
    m_slider.addListener(this);
    m_slider.setEnabled(false);

    // playlist
    addAndMakeVisible(m_tracksTable);
    m_tracksTable.setColour(ListBox::outlineColourId, Colours::grey);
    m_tracksTable.setOutlineThickness(1);

    m_remappingAudioSource.setNumberOfChannelsToProduce(outputChannelNames->getNumberOfChannels());
    m_remappingAudioSource.setOutputChannelMapping(0, 0);
    m_remappingAudioSource.setOutputChannelMapping(1, 1);
    m_mixer->getMixerAudioSource().addInputSource(&m_remappingAudioSource, false);

    mixer->registerPlayer(this);
    setGain(gain);

    addKeyListener(this);
    setBounds(0, 0, 600, 300);

    m_soloBusSettings.addListener(this);
}
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;
}