mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 02:40:00 +01:00
Initial implementation of Metronome from Ableton LINK
Added submodule for github ableton link, and compiled draft of Metronome class.
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -19,3 +19,6 @@
|
|||||||
[submodule "ext/glm"]
|
[submodule "ext/glm"]
|
||||||
path = ext/glm
|
path = ext/glm
|
||||||
url = https://github.com/g-truc/glm.git
|
url = https://github.com/g-truc/glm.git
|
||||||
|
[submodule "ext/link"]
|
||||||
|
path = ext/link
|
||||||
|
url = https://github.com/Ableton/link.git
|
||||||
|
|||||||
@@ -137,6 +137,13 @@ set(BUILD_STATIC_LIBS ON)
|
|||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ext/glm)
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ext/glm)
|
||||||
message(STATUS "Compiling 'GLM' OpenGL mathematics https://glm.g-truc.net -- ${CMAKE_CURRENT_SOURCE_DIR}/ext/glm")
|
message(STATUS "Compiling 'GLM' OpenGL mathematics https://glm.g-truc.net -- ${CMAKE_CURRENT_SOURCE_DIR}/ext/glm")
|
||||||
|
|
||||||
|
#
|
||||||
|
# Ableton LINK
|
||||||
|
#
|
||||||
|
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ext/link)
|
||||||
|
include(${CMAKE_CURRENT_SOURCE_DIR}/ext/link/AbletonLinkConfig.cmake)
|
||||||
|
message(STATUS "Compiling Ableton 'Link' https://github.com/Ableton/link -- ${CMAKE_CURRENT_SOURCE_DIR}/ext/link")
|
||||||
|
|
||||||
#
|
#
|
||||||
# GLAD
|
# GLAD
|
||||||
#
|
#
|
||||||
@@ -254,6 +261,7 @@ include_directories(
|
|||||||
${STB_INCLUDE_DIR}
|
${STB_INCLUDE_DIR}
|
||||||
${DIRENT_INCLUDE_DIR}
|
${DIRENT_INCLUDE_DIR}
|
||||||
${OSCPACK_INCLUDE_DIR}
|
${OSCPACK_INCLUDE_DIR}
|
||||||
|
${link_HEADERS}
|
||||||
)
|
)
|
||||||
|
|
||||||
link_directories(
|
link_directories(
|
||||||
@@ -328,6 +336,7 @@ set(VMIX_SRCS
|
|||||||
Connection.cpp
|
Connection.cpp
|
||||||
ActionManager.cpp
|
ActionManager.cpp
|
||||||
Overlay.cpp
|
Overlay.cpp
|
||||||
|
Metronome.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -509,6 +518,7 @@ target_link_libraries(${VMIX_BINARY} LINK_PRIVATE
|
|||||||
${GSTREAMER_GL_LIBRARY}
|
${GSTREAMER_GL_LIBRARY}
|
||||||
Threads::Threads
|
Threads::Threads
|
||||||
PNG::PNG
|
PNG::PNG
|
||||||
|
Ableton::Link
|
||||||
${PLATFORM_LIBS}
|
${PLATFORM_LIBS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
155
Metronome.cpp
Normal file
155
Metronome.cpp
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include <ableton/Link.hpp>
|
||||||
|
|
||||||
|
#include "Metronome.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace ableton
|
||||||
|
{
|
||||||
|
|
||||||
|
class Engine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Engine(Link& link)
|
||||||
|
: mLink(link)
|
||||||
|
, mQuantum(4.)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void startPlaying()
|
||||||
|
{
|
||||||
|
auto sessionState = mLink.captureAppSessionState();
|
||||||
|
sessionState.setIsPlayingAndRequestBeatAtTime(true, now(), 0., mQuantum);
|
||||||
|
mLink.commitAppSessionState(sessionState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopPlaying()
|
||||||
|
{
|
||||||
|
auto sessionState = mLink.captureAppSessionState();
|
||||||
|
sessionState.setIsPlaying(false, now());
|
||||||
|
mLink.commitAppSessionState(sessionState);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isPlaying() const
|
||||||
|
{
|
||||||
|
return mLink.captureAppSessionState().isPlaying();
|
||||||
|
}
|
||||||
|
|
||||||
|
double beatTime() const
|
||||||
|
{
|
||||||
|
auto sessionState = mLink.captureAppSessionState();
|
||||||
|
return sessionState.beatAtTime(now(), mQuantum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTempo(double tempo)
|
||||||
|
{
|
||||||
|
auto sessionState = mLink.captureAppSessionState();
|
||||||
|
sessionState.setTempo(tempo, now());
|
||||||
|
mLink.commitAppSessionState(sessionState);
|
||||||
|
}
|
||||||
|
|
||||||
|
double quantum() const
|
||||||
|
{
|
||||||
|
return mQuantum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setQuantum(double quantum)
|
||||||
|
{
|
||||||
|
mQuantum = quantum;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isStartStopSyncEnabled() const
|
||||||
|
{
|
||||||
|
return mLink.isStartStopSyncEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setStartStopSyncEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
mLink.enableStartStopSync(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::chrono::microseconds now() const
|
||||||
|
{
|
||||||
|
return mLink.clock().micros();
|
||||||
|
}
|
||||||
|
|
||||||
|
Link& mLink;
|
||||||
|
double mQuantum;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct State
|
||||||
|
{
|
||||||
|
std::atomic<bool> running;
|
||||||
|
Link link;
|
||||||
|
Engine engine;
|
||||||
|
double beats, phase, tempo;
|
||||||
|
State() : running(true), link(120.), engine(link), beats(0.), phase(4.), tempo(120.)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void update(State& state)
|
||||||
|
{
|
||||||
|
state.link.enable(true);
|
||||||
|
|
||||||
|
while (state.running)
|
||||||
|
{
|
||||||
|
const auto time = state.link.clock().micros();
|
||||||
|
auto sessionState = state.link.captureAppSessionState();
|
||||||
|
|
||||||
|
state.beats = sessionState.beatAtTime(time, state.engine.quantum());
|
||||||
|
state.phase = sessionState.phaseAtTime(time, state.engine.quantum());
|
||||||
|
state.tempo = sessionState.tempo();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
state.link.enable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ableton
|
||||||
|
|
||||||
|
|
||||||
|
ableton::State link_state_;
|
||||||
|
|
||||||
|
Metronome::Metronome()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Metronome::init()
|
||||||
|
{
|
||||||
|
std::thread(ableton::update, std::ref(link_state_)).detach();
|
||||||
|
|
||||||
|
return link_state_.running;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Metronome::terminate()
|
||||||
|
{
|
||||||
|
link_state_.running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double Metronome::beats() const
|
||||||
|
{
|
||||||
|
return link_state_.beats;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Metronome::phase() const
|
||||||
|
{
|
||||||
|
return link_state_.phase;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Metronome::tempo() const
|
||||||
|
{
|
||||||
|
return link_state_.tempo;
|
||||||
|
}
|
||||||
27
Metronome.h
Normal file
27
Metronome.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef METRONOME_H
|
||||||
|
#define METRONOME_H
|
||||||
|
|
||||||
|
|
||||||
|
class Metronome
|
||||||
|
{
|
||||||
|
// Private Constructor
|
||||||
|
Metronome();
|
||||||
|
Metronome(Metronome const& copy) = delete;
|
||||||
|
Metronome& operator=(Metronome const& copy) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static Metronome& manager ()
|
||||||
|
{
|
||||||
|
// The only instance
|
||||||
|
static Metronome _instance;
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool init ();
|
||||||
|
void terminate();
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // METRONOME_H
|
||||||
1
ext/link
Submodule
1
ext/link
Submodule
Submodule ext/link added at 14f6cc99ac
13
main.cpp
13
main.cpp
@@ -28,7 +28,7 @@
|
|||||||
#include "RenderingManager.h"
|
#include "RenderingManager.h"
|
||||||
#include "UserInterfaceManager.h"
|
#include "UserInterfaceManager.h"
|
||||||
#include "Connection.h"
|
#include "Connection.h"
|
||||||
|
#include "Metronome.h"
|
||||||
|
|
||||||
#if defined(APPLE)
|
#if defined(APPLE)
|
||||||
extern "C"{
|
extern "C"{
|
||||||
@@ -85,12 +85,18 @@ int main(int argc, char *argv[])
|
|||||||
/// lock to inform an instance is running
|
/// lock to inform an instance is running
|
||||||
Settings::Lock();
|
Settings::Lock();
|
||||||
|
|
||||||
|
///
|
||||||
///
|
///
|
||||||
/// CONNECTION INIT
|
/// CONNECTION INIT
|
||||||
///
|
///
|
||||||
if ( !Connection::manager().init() )
|
if ( !Connection::manager().init() )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/// METRONOME INIT
|
||||||
|
///
|
||||||
|
if ( !Metronome::manager().init() )
|
||||||
|
return 1;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// RENDERING INIT
|
/// RENDERING INIT
|
||||||
///
|
///
|
||||||
@@ -140,6 +146,11 @@ int main(int argc, char *argv[])
|
|||||||
///
|
///
|
||||||
Rendering::manager().terminate();
|
Rendering::manager().terminate();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// METRONOME TERMINATE
|
||||||
|
///
|
||||||
|
Metronome::manager().terminate();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// CONNECTION TERMINATE
|
/// CONNECTION TERMINATE
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user