Process metronome every MIDI tick (#7483)
This commit is contained in:
@@ -87,7 +87,6 @@ AudioEngine::AudioEngine( bool renderOnly ) :
|
||||
m_oldAudioDev( nullptr ),
|
||||
m_audioDevStartFailed( false ),
|
||||
m_profiler(),
|
||||
m_metronomeActive(false),
|
||||
m_clearSignal(false)
|
||||
{
|
||||
for( int i = 0; i < 2; ++i )
|
||||
@@ -345,8 +344,6 @@ void AudioEngine::renderStageNoteSetup()
|
||||
Mixer * mixer = Engine::mixer();
|
||||
mixer->prepareMasterMix();
|
||||
|
||||
handleMetronome();
|
||||
|
||||
// create play-handles for new notes, samples etc.
|
||||
Engine::getSong()->processNextBuffer();
|
||||
|
||||
@@ -459,55 +456,6 @@ void AudioEngine::swapBuffers()
|
||||
zeroSampleFrames(m_outputBufferWrite.get(), m_framesPerPeriod);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioEngine::handleMetronome()
|
||||
{
|
||||
static tick_t lastMetroTicks = -1;
|
||||
|
||||
Song * song = Engine::getSong();
|
||||
Song::PlayMode currentPlayMode = song->playMode();
|
||||
|
||||
bool metronomeSupported =
|
||||
currentPlayMode == Song::PlayMode::MidiClip
|
||||
|| currentPlayMode == Song::PlayMode::Song
|
||||
|| currentPlayMode == Song::PlayMode::Pattern;
|
||||
|
||||
if (!metronomeSupported || !m_metronomeActive || song->isExporting())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// stop crash with metronome if empty project
|
||||
if (song->countTracks() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tick_t ticks = song->getPlayPos(currentPlayMode).getTicks();
|
||||
tick_t ticksPerBar = TimePos::ticksPerBar();
|
||||
int numerator = song->getTimeSigModel().getNumerator();
|
||||
|
||||
if (ticks == lastMetroTicks)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ticks % (ticksPerBar / 1) == 0)
|
||||
{
|
||||
addPlayHandle(new SamplePlayHandle("misc/metronome02.ogg"));
|
||||
}
|
||||
else if (ticks % (ticksPerBar / numerator) == 0)
|
||||
{
|
||||
addPlayHandle(new SamplePlayHandle("misc/metronome01.ogg"));
|
||||
}
|
||||
|
||||
lastMetroTicks = ticks;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AudioEngine::clear()
|
||||
{
|
||||
m_clearSignal = true;
|
||||
|
||||
@@ -40,6 +40,7 @@ set(LMMS_SRCS
|
||||
core/LinkedModelGroups.cpp
|
||||
core/LocklessAllocator.cpp
|
||||
core/MeterModel.cpp
|
||||
core/Metronome.cpp
|
||||
core/MicroTimer.cpp
|
||||
core/Microtuner.cpp
|
||||
core/MixHelpers.cpp
|
||||
|
||||
41
src/core/Metronome.cpp
Normal file
41
src/core/Metronome.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Metronome.cpp
|
||||
*
|
||||
* Copyright (c) 2024 saker
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Metronome.h"
|
||||
|
||||
#include "Engine.h"
|
||||
#include "SamplePlayHandle.h"
|
||||
|
||||
namespace lmms {
|
||||
void Metronome::processTick(int currentTick, int ticksPerBar, int beatsPerBar, size_t bufferOffset)
|
||||
{
|
||||
const auto ticksPerBeat = ticksPerBar / beatsPerBar;
|
||||
if (currentTick % ticksPerBeat != 0 || !m_active) { return; }
|
||||
|
||||
const auto handle = currentTick % ticksPerBar == 0 ? new SamplePlayHandle("misc/metronome02.ogg")
|
||||
: new SamplePlayHandle("misc/metronome01.ogg");
|
||||
handle->setOffset(bufferOffset);
|
||||
Engine::audioEngine()->addPlayHandle(handle);
|
||||
}
|
||||
} // namespace lmms
|
||||
@@ -332,6 +332,8 @@ void Song::processNextBuffer()
|
||||
{
|
||||
// First frame of tick: process automation and play tracks
|
||||
processAutomations(trackList, getPlayPos(), framesToPlay);
|
||||
processMetronome(frameOffsetInPeriod);
|
||||
|
||||
for (const auto track : trackList)
|
||||
{
|
||||
track->play(getPlayPos(), framesToPlay, frameOffsetInPeriod, clipNum);
|
||||
@@ -426,6 +428,17 @@ void Song::processAutomations(const TrackList &tracklist, TimePos timeStart, fpp
|
||||
}
|
||||
}
|
||||
|
||||
void Song::processMetronome(size_t bufferOffset)
|
||||
{
|
||||
const auto currentPlayMode = playMode();
|
||||
const auto supported = currentPlayMode == PlayMode::MidiClip
|
||||
|| currentPlayMode == PlayMode::Song
|
||||
|| currentPlayMode == PlayMode::Pattern;
|
||||
|
||||
if (!supported || m_exporting) { return; }
|
||||
m_metronome.processTick(currentTick(), ticksPerBar(), m_timeSigModel.getNumerator(), bufferOffset);
|
||||
}
|
||||
|
||||
void Song::setModified(bool value)
|
||||
{
|
||||
if( !m_loadingProject && m_modified != value)
|
||||
@@ -1542,6 +1555,4 @@ void Song::setKeymap(unsigned int index, std::shared_ptr<Keymap> newMap)
|
||||
emit keymapListChanged(index);
|
||||
Engine::audioEngine()->doneChangeInModel();
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "ExportProjectDialog.h"
|
||||
#include "FileBrowser.h"
|
||||
#include "FileDialog.h"
|
||||
#include "Metronome.h"
|
||||
#include "MixerView.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "ImportFilter.h"
|
||||
@@ -430,7 +431,7 @@ void MainWindow::finalize()
|
||||
this, SLOT(onToggleMetronome()),
|
||||
m_toolBar );
|
||||
m_metronomeToggle->setCheckable(true);
|
||||
m_metronomeToggle->setChecked(Engine::audioEngine()->isMetronomeActive());
|
||||
m_metronomeToggle->setChecked(Engine::getSong()->metronome().active());
|
||||
|
||||
m_toolBarLayout->setColumnMinimumWidth( 0, 5 );
|
||||
m_toolBarLayout->addWidget( project_new, 0, 1 );
|
||||
@@ -1173,7 +1174,7 @@ void MainWindow::updateConfig( QAction * _who )
|
||||
|
||||
void MainWindow::onToggleMetronome()
|
||||
{
|
||||
Engine::audioEngine()->setMetronomeActive( m_metronomeToggle->isChecked() );
|
||||
Engine::getSong()->metronome().setActive(m_metronomeToggle->isChecked());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user