void RecorderSlaveBlock::eachFrame() {
    if (m_recording) {
        // recording
        if (m_linkNode->getValue() < LuminosusConstants::triggerThreshold) {
            stopRecording();
            return;
        }

        double value = m_inputNode->getValue();
        m_data.append(value);
        m_outputNode->setValue(value);
        emit dataChanged();
        return;
    }

    if (m_playing && !m_data.isEmpty()) {
        // playing
        double value = m_data[m_playbackPosition % m_data.size()];
        m_outputNode->setValue(value);

        // either progress frame or stop:
        if (m_playbackPosition + 1 >= m_data.size() || m_linkNode->getValue() < LuminosusConstants::triggerThreshold) {
            m_playing.setValue(false);
            m_playbackPosition = 0;
            emit playbackPositionChanged();
        } else {
            m_playbackPosition = (m_playbackPosition + 1) % m_data.size();
            emit playbackPositionChanged();
        }
    }
}
コード例 #2
0
ファイル: SampleTrack.cpp プロジェクト: LMMS/lmms
SampleTCO::SampleTCO( Track * _track ) :
	TrackContentObject( _track ),
	m_sampleBuffer( new SampleBuffer ),
	m_isPlaying( false )
{
	saveJournallingState( false );
	setSampleFile( "" );
	restoreJournallingState();

	// we need to receive bpm-change-events, because then we have to
	// change length of this TCO
	connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ),
					this, SLOT( updateLength() ), Qt::DirectConnection );
	connect( Engine::getSong(), SIGNAL( timeSignatureChanged( int,int ) ),
					this, SLOT( updateLength() ) );

	//care about positionmarker
	TimeLineWidget * timeLine = Engine::getSong()->getPlayPos( Engine::getSong()->Mode_PlaySong ).m_timeLine;
	if( timeLine )
	{
		connect( timeLine, SIGNAL( positionMarkerMoved() ), this, SLOT( playbackPositionChanged() ) );
	}
	//playbutton clicked or space key / on Export Song set isPlaying to false
	connect( Engine::getSong(), SIGNAL( playbackStateChanged() ),
			this, SLOT( playbackPositionChanged() ), Qt::DirectConnection );
	//care about loops
	connect( Engine::getSong(), SIGNAL( updateSampleTracks() ),
			this, SLOT( playbackPositionChanged() ), Qt::DirectConnection );
	//care about mute TCOs
	connect( this, SIGNAL( dataChanged() ), this, SLOT( playbackPositionChanged() ) );
	//care about mute track
	connect( getTrack()->getMutedModel(), SIGNAL( dataChanged() ),
			this, SLOT( playbackPositionChanged() ), Qt::DirectConnection );
	//care about TCO position
	connect( this, SIGNAL( positionChanged() ), this, SLOT( updateTrackTcos() ) );

	switch( getTrack()->trackContainer()->type() )
	{
		case TrackContainer::BBContainer:
			setAutoResize( true );
			break;

		case TrackContainer::SongContainer:
			// move down
		default:
			setAutoResize( false );
			break;
	}
	updateTrackTcos();
}
コード例 #3
0
ファイル: LfoController.cpp プロジェクト: asmw/lmms
LfoController::LfoController( Model * _parent ) :
	Controller( Controller::LfoController, _parent, tr( "LFO Controller" ) ),
	m_baseModel( 0.5, 0.0, 1.0, 0.001, this, tr( "Base value" ) ),
	m_speedModel( 2.0, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Oscillator speed" ) ),
	m_amountModel( 1.0, -1.0, 1.0, 0.005, this, tr( "Oscillator amount" ) ),
	m_phaseModel( 0.0, 0.0, 360.0, 4.0, this, tr( "Oscillator phase" ) ),
	m_waveModel( Oscillator::SineWave, 0, Oscillator::NumWaveShapes,
			this, tr( "Oscillator waveform" ) ),
	m_multiplierModel( 0, 0, 2, this, tr( "Frequency Multiplier" ) ),
	m_duration( 1000 ),
	m_phaseOffset( 0 ),	
	m_currentPhase( 0 ),
	m_sampleFunction( &Oscillator::sinSample ),
	m_userDefSampleBuffer( new SampleBuffer )
{
	setSampleExact( true );
	connect( &m_waveModel, SIGNAL( dataChanged() ),
			this, SLOT( updateSampleFunction() ) );
	
	connect( &m_speedModel, SIGNAL( dataChanged() ),
			this, SLOT( updateDuration() ) );
	connect( &m_multiplierModel, SIGNAL( dataChanged() ),
			this, SLOT( updateDuration() ) );
	connect( engine::mixer(), SIGNAL( sampleRateChanged() ), 
			this, SLOT( updateDuration() ) );
	
	connect( engine::getSong(), SIGNAL( playbackStateChanged() ),
			this, SLOT( updatePhase() ) );
	connect( engine::getSong(), SIGNAL( playbackPositionChanged() ),
			this, SLOT( updatePhase() ) );
			
	updateDuration();
}
コード例 #4
0
void SampleTCO::setSampleFile( const QString & _sf )
{
	m_sampleBuffer->setAudioFile( _sf );
	updateLength();

	emit sampleChanged();
	emit playbackPositionChanged();
}
コード例 #5
0
ファイル: SampleTrack.cpp プロジェクト: liushuyu/lmms
void SampleTCO::setSampleFile( const QString & _sf )
{
	m_sampleBuffer->setAudioFile( _sf );
	setStartTimeOffset( 0 );
	changeLength( (int) ( m_sampleBuffer->frames() / Engine::framesPerTick() ) );

	emit sampleChanged();
	emit playbackPositionChanged();
}
コード例 #6
0
ファイル: song.cpp プロジェクト: CallisteHanriat/lmms
void song::setPlayPos( tick_t _ticks, PlayModes _play_mode )
{
	m_elapsedTicks += m_playPos[_play_mode].getTicks() - _ticks;
	m_elapsedMilliSeconds += (((( _ticks - m_playPos[_play_mode].getTicks()))*60*1000/48)/getTempo());
	m_playPos[_play_mode].setTicks( _ticks );
	m_playPos[_play_mode].setCurrentFrame( 0.0f );

// send a signal if playposition changes during playback
	if( isPlaying() ) 
	{
		emit playbackPositionChanged();
	}
}
コード例 #7
0
ファイル: Song.cpp プロジェクト: RebeccaDeField/lmms
void Song::setPlayPos( tick_t ticks, PlayModes playMode )
{
	tick_t ticksFromPlayMode = m_playPos[playMode].getTicks();
	m_elapsedTicks += ticksFromPlayMode - ticks;
	m_elapsedMilliSeconds += MidiTime::ticksToMilliseconds( ticks - ticksFromPlayMode, getTempo() );
	m_playPos[playMode].setTicks( ticks );
	m_playPos[playMode].setCurrentFrame( 0.0f );

// send a signal if playposition changes during playback
	if( isPlaying() )
	{
		emit playbackPositionChanged();
		emit updateSampleTracks();
	}
}
AudioPlaybackBlock::AudioPlaybackBlock(MainController* controller, QString uid)
    : BlockBase(controller, uid)
    , m_playNode(nullptr)
    , m_pauseNode(nullptr)
    , m_toggleNode(nullptr)
    , m_activeNode(nullptr)
    , m_endNode(nullptr)
    , m_positionNode(nullptr)
    , m_filePath("")
    , m_lastPlayNodeValue(0.0)
    , m_lastPauseNodeValue(0.0)
    , m_lastToggleNodeValue(0.0)
    , m_alwaysStartAtBegin(false)
    , m_loop(false)
    , m_toggleMode(true)
    , m_player(this)
{
    m_widthIsResizable = true;

    m_playNode = createInputNode("playNode");
    m_pauseNode = createInputNode("pauseNode");
    m_toggleNode = createInputNode("toggleNode");
    connect(m_playNode, SIGNAL(dataChanged()), this, SLOT(onPlayNodeValueChanged()));
    connect(m_pauseNode, SIGNAL(dataChanged()), this, SLOT(onPauseNodeValueChanged()));
    connect(m_toggleNode, SIGNAL(dataChanged()), this, SLOT(onToggleNodeValueChanged()));

    m_activeNode = createOutputNode("activeNode");
    m_endNode = createOutputNode("endNode");
    m_positionNode = createOutputNode("positionNode");

    // setup Timer to be able to send a short pulse when end of file is reached:
    m_endPulseTimer.setSingleShot(true);
    m_endPulseTimer.setInterval(100);
    connect(&m_endPulseTimer, SIGNAL(timeout()), this, SLOT(onEndPulseTimeout()));

    connect(&m_player, SIGNAL(endOfFile()), this, SLOT(onEndOfFile()));
    connect(&m_player, SIGNAL(isPlayingChanged()), this, SIGNAL(isPlayingChanged()));
    connect(&m_player, SIGNAL(isPlayingChanged()), this, SLOT(onIsPlayingChanged()));
    connect(&m_player, SIGNAL(positionChanged()), this, SIGNAL(playbackPositionChanged()));
    connect(&m_player, SIGNAL(positionChanged()), this, SLOT(onPlaybackPositionChanged()));
    connect(&m_player, SIGNAL(lengthChanged()), this, SIGNAL(lengthChanged()));

    connect(&m_waveform, SIGNAL(pointsChanged()), this, SIGNAL(waveformChanged()));
    connect(&m_waveform, SIGNAL(availableChanged()), this, SIGNAL(waveformChanged()));
}
コード例 #9
0
ファイル: SampleTrack.cpp プロジェクト: LMMS/lmms
void SampleTCO::setSampleFile( const QString & _sf )
{
	int length;
	if ( _sf.isEmpty() )
	{	//When creating an empty sample pattern make it a bar long
		float nom = Engine::getSong()->getTimeSigModel().getNumerator();
		float den = Engine::getSong()->getTimeSigModel().getDenominator();
		length = DefaultTicksPerTact * ( nom / den );
	}
	else
	{	//Otherwise set it to the sample's length
		m_sampleBuffer->setAudioFile( _sf );
		length = sampleLength();
	}
	changeLength(length);

	setStartTimeOffset( 0 );

	emit sampleChanged();
	emit playbackPositionChanged();
}
コード例 #10
0
void MidiPlayer::run()
{
    // Workaround to fix errors with the Microsoft GS Wavetable Synth on
    // Windows 10 - see http://stackoverflow.com/a/32553208/586978
#ifdef _WIN32
    CoInitializeEx(nullptr, COINIT_MULTITHREADED);
    BOOST_SCOPE_EXIT(this_) {
        CoUninitialize();
    } BOOST_SCOPE_EXIT_END
#endif

    boost::signals2::scoped_connection connection(
        mySettingsManager.subscribeToChanges([&]() {
            auto settings = mySettingsManager.getReadHandle();
            myMetronomeEnabled = settings->get(Settings::MetronomeEnabled);
        }));

    setIsPlaying(true);

    MidiFile::LoadOptions options;
    options.myEnableMetronome = true;
    options.myRecordPositionChanges = true;

    // Load MIDI settings.
    int api;
    int port;
    {
        auto settings = mySettingsManager.getReadHandle();
        myMetronomeEnabled = settings->get(Settings::MetronomeEnabled);

        api = settings->get(Settings::MidiApi);
        port = settings->get(Settings::MidiPort);

        options.myMetronomePreset = settings->get(Settings::MetronomePreset) +
                                    Midi::MIDI_PERCUSSION_PRESET_OFFSET;
        options.myStrongAccentVel =
            settings->get(Settings::MetronomeStrongAccent);
        options.myWeakAccentVel = settings->get(Settings::MetronomeWeakAccent);
        options.myVibratoStrength = settings->get(Settings::MidiVibratoLevel);
        options.myWideVibratoStrength =
            settings->get(Settings::MidiWideVibratoLevel);
    }

    MidiFile file;
    file.load(myScore, options);

    const int ticks_per_beat = file.getTicksPerBeat();

    // Merge the MIDI evvents for each track.
    MidiEventList events;
    for (MidiEventList &track : file.getTracks())
    {
        track.convertToAbsoluteTicks();
        events.concat(track);
    }

    // TODO - since each track is already sorted, an n-way merge should be faster.
    std::stable_sort(events.begin(), events.end());
    events.convertToDeltaTicks();

    // Initialize RtMidi and set the port.
    MidiOutputDevice device;
    if (!device.initialize(api, port))
    {
        emit error(tr("Error initializing MIDI output device."));
        return;
    }

    bool started = false;
    int beat_duration = Midi::BEAT_DURATION_120_BPM;
    const SystemLocation start_location(myStartLocation.getSystemIndex(),
                                        myStartLocation.getPositionIndex());
    SystemLocation current_location = start_location;

    for (auto event = events.begin(); event != events.end(); ++event)
    {
        if (!isPlaying())
            break;

        if (event->isTempoChange())
            beat_duration = event->getTempo();

        // Skip events before the start location, except for events such as
        // instrument changes. Tempo changes are tracked above.
        if (!started)
        {
            if (event->getLocation() < start_location)
            {
                if (event->isProgramChange())
                    device.sendMessage(event->getData());

                continue;
            }
            else
            {
                performCountIn(device, event->getLocation(), beat_duration);

                started = true;
            }
        }

        const int delta = event->getTicks();
        assert(delta >= 0);

        const int duration_us = boost::rational_cast<int>(
            boost::rational<int>(delta, ticks_per_beat) * beat_duration);

        usleep(duration_us * (100.0 / myPlaybackSpeed));

        // Don't play metronome events if the metronome is disabled.
        if (event->isNoteOnOff() && event->getChannel() == METRONOME_CHANNEL &&
            !myMetronomeEnabled)
        {
            continue;
        }

        device.sendMessage(event->getData());

        // Notify listeners of the current playback position.
        if (event->getLocation() != current_location)
        {
            const SystemLocation &new_location = event->getLocation();

            // Don't move backwards unless a repeat occurred.
            if (new_location < current_location && !event->isPositionChange())
                    continue;

            if (new_location.getSystem() != current_location.getSystem())
                emit playbackSystemChanged(new_location.getSystem());

            emit playbackPositionChanged(new_location.getPosition());

            current_location = new_location;
        }
    }
}