Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update link sources, bump version to 1.0.1
  • Loading branch information
falkTX committed Oct 21, 2019
1 parent 4457966 commit 0e55d7f
Show file tree
Hide file tree
Showing 548 changed files with 27,717 additions and 15,103 deletions.
26 changes: 20 additions & 6 deletions Makefile
Expand Up @@ -8,13 +8,26 @@ AR ?= ar
CC ?= gcc
CXX ?= g++

# ----------------------------------------------------------------------------------------------------------------------------
# Fallback to Linux if no other OS defined
# ---------------------------------------------------------------------------------------------------------------------
# Auto-detect OS if not defined

ifneq ($(LINUX),true)
ifneq ($(MACOS),true)
ifneq ($(WIN32),true)

TARGET_MACHINE := $(shell $(CC) -dumpmachine)
ifneq (,$(findstring linux,$(TARGET_MACHINE)))
LINUX=true
endif
ifneq (,$(findstring apple,$(TARGET_MACHINE)))
MACOS=true
endif
ifneq (,$(findstring mingw,$(TARGET_MACHINE)))
WIN32=true
endif

endif
endif
endif

# ----------------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -44,12 +57,13 @@ CXXFLAGS += -fvisibility-inlines-hidden
endif

BUILD_C_FLAGS = $(BASE_FLAGS) -std=gnu99 $(CFLAGS)
BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=gnu++0x $(CXXFLAGS) $(CPPFLAGS)
BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=gnu++11 $(CXXFLAGS) $(CPPFLAGS)

# ----------------------------------------------------------------------------------------------------------------------------

BUILD_CXX_FLAGS += -Wno-multichar -Wno-unused-variable -Wno-uninitialized -Wno-missing-field-initializers
BUILD_CXX_FLAGS += -Ilink
BUILD_CXX_FLAGS += -Wno-missing-field-initializers -Wno-multichar -Wno-uninitialized -Wno-unknown-pragmas
BUILD_CXX_FLAGS += -I. -Ilink
# -Wno-unused-variable -Wno-uninitialized

ifeq ($(LINUX),true)
BUILD_CXX_FLAGS += -DLINK_PLATFORM_LINUX=1
Expand All @@ -66,7 +80,7 @@ endif
# ----------------------------------------------------------------------------------------------------------------------------

OBJS = build/hylia.cpp.o
VERSION = 0.0.1
VERSION = 1.0.1

PREFIX = /usr/local
INCDIR = $(PREFIX)/include
Expand Down
40 changes: 40 additions & 0 deletions hylia.cpp
Expand Up @@ -17,7 +17,17 @@

#include "hylia.h"

#if defined(__clang_major__) && __clang_major__ >= 4
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunused-local-typedef"
#endif

#include "AudioEngine.hpp"

#if defined(__clang_major__) && __clang_major__ >= 4
# pragma clang diagnostic pop
#endif

#include "ableton/link/HostTimeFilter.hpp"
#include <chrono>

Expand Down Expand Up @@ -54,6 +64,21 @@ class HyliaTransport {
outputLatency = latency;
}

void setStartStopSyncEnabled(const bool enabled)
{
engine.setStartStopSyncEnabled(enabled);
}

void startPlaying()
{
engine.startPlaying();
}

void stopPlaying()
{
engine.stopPlaying();
}

void process(const uint32_t frames, LinkTimeInfo* const info)
{
const std::chrono::microseconds hostTime = hostTimeFilter.sampleTimeToHostTime(sampleTime)
Expand Down Expand Up @@ -104,6 +129,21 @@ void hylia_set_output_latency(hylia_t* link, uint32_t latency)
((HyliaTransport*)link)->setOutputLatency(latency);
}

void hylia_set_start_stop_sync_enabled(hylia_t* link, bool enabled)
{
((HyliaTransport*)link)->setStartStopSyncEnabled(enabled);
}

void hylia_start_playing(hylia_t* link)
{
((HyliaTransport*)link)->startPlaying();
}

void hylia_stop_playing(hylia_t* link)
{
((HyliaTransport*)link)->stopPlaying();
}

void hylia_process(hylia_t* link, uint32_t frames, hylia_time_info_t* info)
{
((HyliaTransport*)link)->process(frames, (LinkTimeInfo*)info);
Expand Down
4 changes: 4 additions & 0 deletions hylia.h
Expand Up @@ -30,6 +30,7 @@ typedef struct _hylia_t hylia_t;

typedef struct _hylia_time_info_t {
double beatsPerBar, beatsPerMinute, beat, phase;
bool playing;
} hylia_time_info_t;

hylia_t* hylia_create(void);
Expand All @@ -38,6 +39,9 @@ void hylia_process(hylia_t* link, uint32_t frames, hylia_time_info_t* info);
void hylia_set_beats_per_bar(hylia_t* link, double beatsPerBar);
void hylia_set_beats_per_minute(hylia_t* link, double beatsPerMinute);
void hylia_set_output_latency(hylia_t* link, uint32_t latency);
void hylia_set_start_stop_sync_enabled(hylia_t* link, bool enabled);
void hylia_start_playing(hylia_t* link);
void hylia_stop_playing(hylia_t* link);
void hylia_cleanup(hylia_t* link);

#ifdef __cplusplus
Expand Down
92 changes: 67 additions & 25 deletions link/AudioEngine.cpp
Expand Up @@ -19,30 +19,45 @@

#include "AudioEngine.hpp"

// Make sure to define this before <cmath> is included for Windows
#define _USE_MATH_DEFINES
#include <cmath>

namespace ableton
{
namespace link
{

AudioEngine::AudioEngine(Link& link)
: mLink(link)
, mSharedEngineData({0., false, 4.})
, mSharedEngineData({0., false, false, 4., false})
, mLockfreeEngineData(mSharedEngineData)
, mIsPlaying(false)
{
}

void AudioEngine::startPlaying()
{
std::lock_guard<std::mutex> lock(mEngineDataGuard);
mSharedEngineData.requestStart = true;
}

void AudioEngine::stopPlaying()
{
std::lock_guard<std::mutex> lock(mEngineDataGuard);
mSharedEngineData.requestStop = true;
}

bool AudioEngine::isPlaying() const
{
return mLink.captureAppSessionState().isPlaying();
}

double AudioEngine::beatTime() const
{
const auto timeline = mLink.captureAppTimeline();
return timeline.beatAtTime(mLink.clock().micros(), mSharedEngineData.quantum);
const auto sessionState = mLink.captureAppSessionState();
return sessionState.beatAtTime(mLink.clock().micros(), mSharedEngineData.quantum);
}

void AudioEngine::setTempo(double tempo)
{
const std::lock_guard<std::mutex> lock(mEngineDataGuard);
std::lock_guard<std::mutex> lock(mEngineDataGuard);
mSharedEngineData.requestedTempo = tempo;
}

Expand All @@ -53,26 +68,38 @@ double AudioEngine::quantum() const

void AudioEngine::setQuantum(double quantum)
{
const std::lock_guard<std::mutex> lock(mEngineDataGuard);
std::lock_guard<std::mutex> lock(mEngineDataGuard);
mSharedEngineData.quantum = quantum;
mSharedEngineData.resetBeatTime = true;
}

bool AudioEngine::isStartStopSyncEnabled() const
{
return mLink.isStartStopSyncEnabled();
}

void AudioEngine::setStartStopSyncEnabled(const bool enabled)
{
mLink.enableStartStopSync(enabled);
}

AudioEngine::EngineData AudioEngine::pullEngineData()
{
auto engineData = EngineData{};

if (mEngineDataGuard.try_lock())
{
engineData.requestedTempo = mSharedEngineData.requestedTempo;
mSharedEngineData.requestedTempo = 0;
engineData.requestStart = mSharedEngineData.requestStart;
mSharedEngineData.requestStart = false;
engineData.requestStop = mSharedEngineData.requestStop;
mSharedEngineData.requestStop = false;

engineData.resetBeatTime = mSharedEngineData.resetBeatTime;
engineData.quantum = mSharedEngineData.quantum;
mSharedEngineData.resetBeatTime = false;
mLockfreeEngineData.quantum = mSharedEngineData.quantum;
mLockfreeEngineData.startStopSyncOn = mSharedEngineData.startStopSyncOn;

mEngineDataGuard.unlock();
}
engineData.quantum = mLockfreeEngineData.quantum;

return engineData;
}
Expand All @@ -81,29 +108,44 @@ void AudioEngine::timelineCallback(const std::chrono::microseconds hostTime, Lin
{
const auto engineData = pullEngineData();

auto timeline = mLink.captureAudioTimeline();
auto sessionState = mLink.captureAudioSessionState();

if (engineData.requestStart)
{
sessionState.setIsPlaying(true, hostTime);
}

if (engineData.requestStop)
{
sessionState.setIsPlaying(false, hostTime);
}

if (engineData.resetBeatTime)
if (!mIsPlaying && sessionState.isPlaying())
{
// Reset the timeline so that beat 0 corresponds to the time when transport starts
sessionState.requestBeatAtStartPlayingTime(0, engineData.quantum);
mIsPlaying = true;
}
else if (mIsPlaying && !sessionState.isPlaying())
{
// Reset the timeline so that beat 0 lands at the beginning of
// this buffer and clear the flag.
timeline.requestBeatAtTime(0, hostTime, engineData.quantum);
mIsPlaying = false;
}

if (engineData.requestedTempo > 0)
{
// Set the newly requested tempo from the beginning of this buffer
timeline.setTempo(engineData.requestedTempo, hostTime);
sessionState.setTempo(engineData.requestedTempo, hostTime);
}

// Timeline modifications are complete, commit the results
mLink.commitAudioTimeline(timeline);
mLink.commitAudioSessionState(sessionState);

// Save timeline info
// Save session state
info->beatsPerBar = engineData.quantum;
info->beatsPerMinute = timeline.tempo();
info->beat = timeline.beatAtTime(hostTime, engineData.quantum);
info->phase = timeline.phaseAtTime(hostTime, engineData.quantum);
info->beatsPerMinute = sessionState.tempo();
info->beat = sessionState.beatAtTime(hostTime, engineData.quantum);
info->phase = sessionState.phaseAtTime(hostTime, engineData.quantum);
info->playing = mIsPlaying;
}

} // namespace link
Expand Down
29 changes: 26 additions & 3 deletions link/AudioEngine.hpp
Expand Up @@ -19,13 +19,27 @@

#pragma once

// Make sure to define this before <cmath> is included for Windows
#ifdef LINK_PLATFORM_WINDOWS
#define _USE_MATH_DEFINES
#include "mingw-std-threads/mingw.condition_variable.h"
#include "mingw-std-threads/mingw.mutex.h"
#include "mingw-std-threads/mingw.thread.h"
#if __BIG_ENDIAN__
# define htonll(x) (x)
# define ntohll(x) (x)
#else
# define htonll(x) ((uint64_t)htonl(((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
# define ntohll(x) ((uint64_t)ntohl(((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
#endif
#endif

#include <cmath>

#include "ableton/Link.hpp"
#include <mutex>

struct LinkTimeInfo {
double beatsPerBar, beatsPerMinute, beat, phase;
bool playing;
};

namespace ableton
Expand All @@ -37,25 +51,34 @@ class AudioEngine
{
public:
AudioEngine(Link& link);
void startPlaying();
void stopPlaying();
bool isPlaying() const;
double beatTime() const;
void setTempo(double tempo);
double quantum() const;
void setQuantum(double quantum);
bool isStartStopSyncEnabled() const;
void setStartStopSyncEnabled(bool enabled);

void timelineCallback(const std::chrono::microseconds hostTime, LinkTimeInfo* const info);

private:
struct EngineData
{
double requestedTempo;
bool resetBeatTime;
bool requestStart;
bool requestStop;
double quantum;
bool startStopSyncOn;
};

EngineData pullEngineData();

Link& mLink;
EngineData mSharedEngineData;
EngineData mLockfreeEngineData;
bool mIsPlaying;
std::mutex mEngineDataGuard;
};

Expand Down

0 comments on commit 0e55d7f

Please sign in to comment.