Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update base link code; Rework hylia code
  • Loading branch information
falkTX committed Apr 11, 2017
1 parent a543449 commit 20bc92f
Show file tree
Hide file tree
Showing 15 changed files with 490 additions and 255 deletions.
64 changes: 39 additions & 25 deletions hylia.cpp
Expand Up @@ -15,79 +15,93 @@
* along with Hylia. If not, see <http://www.gnu.org/licenses/>.
*/

#include "mod-link.h"
#include "hylia.h"

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

class HyliaTransport {
public:
HyliaTransport(double bpm, double bufferSize, double sampleRate)
: link(bpm),
HyliaTransport()
: link(120.0),
engine(link),
outputLatency(0),
sampleTime(0)
{
outputLatency = std::chrono::microseconds(llround(1.0e6 * bufferSize / sampleRate));
}

void setEnabled(bool enabled, double bpm)
void setEnabled(const bool enabled)
{
link.enable(enabled);

if (enabled)
{
sampleTime = 0;
engine.setTempo(bpm);
}

link.enable(enabled);
}

void setTempo(double tempo)
void setQuantum(const double quantum)
{
engine.setQuantum(quantum);
}

void setTempo(const double tempo)
{
engine.setTempo(tempo);
}

void process(uint32_t frames, LinkTimeInfo* info)
void setOutputLatency(const uint32_t latency) noexcept
{
const auto hostTime = hostTimeFilter.sampleTimeToHostTime(sampleTime);
const auto bufferBeginAtOutput = hostTime + outputLatency;
outputLatency = latency;
}

engine.timelineCallback(bufferBeginAtOutput, info);
void process(const uint32_t frames, LinkTimeInfo* const info)
{
const std::chrono::microseconds hostTime = hostTimeFilter.sampleTimeToHostTime(sampleTime)
+ std::chrono::microseconds(outputLatency);
engine.timelineCallback(hostTime, info);

sampleTime += frames;
}

private:
ableton::Link link;
ableton::linkaudio::AudioEngine engine;
ableton::link::AudioEngine engine;
ableton::link::HostTimeFilter<ableton::link::platform::Clock> hostTimeFilter;

ableton::link::HostTimeFilter<ableton::platforms::stl::Clock> hostTimeFilter;
std::chrono::microseconds outputLatency;
uint32_t sampleTime;
uint32_t outputLatency, sampleTime;
};

hylia_t* hylia_create(double bpm, uint32_t buffer_size, uint32_t sample_rate)
hylia_t* hylia_create(void)
{
HyliaTransport* t;

try {
t = new HyliaTransport(bpm, buffer_size, sample_rate);
t = new HyliaTransport();
} catch (...) {
return nullptr;
}

return (hylia_t*)t;
}

void hylia_enable(hylia_t* link, bool on, double bpm)
void hylia_enable(hylia_t* link, bool on)
{
((HyliaTransport*)link)->setEnabled(on);
}

void hylia_set_beats_per_bar(hylia_t* link, double beatsPerBar)
{
((HyliaTransport*)link)->setQuantum(beatsPerBar);
}

void hylia_set_beats_per_minute(hylia_t* link, double beatsPerMinute)
{
((HyliaTransport*)link)->setEnabled(on, bpm);
((HyliaTransport*)link)->setTempo(beatsPerMinute);
}

void hylia_set_tempo(hylia_t* link, double bpm)
void hylia_set_output_latency(hylia_t* link, uint32_t latency)
{
((HyliaTransport*)link)->setTempo(bpm);
((HyliaTransport*)link)->setOutputLatency(latency);
}

void hylia_process(hylia_t* link, uint32_t frames, hylia_time_info_t* info)
Expand Down
10 changes: 6 additions & 4 deletions hylia.h
Expand Up @@ -29,13 +29,15 @@ extern "C" {
typedef struct _hylia_t hylia_t;

typedef struct _hylia_time_info_t {
double bpm, beats, phase;
double beatsPerBar, beatsPerMinute, beat, phase;
} hylia_time_info_t;

hylia_t* hylia_create(double bpm, uint32_t buffer_size, uint32_t sample_rate);
void hylia_enable(hylia_t* link, bool on, double bpm);
hylia_t* hylia_create(void);
void hylia_enable(hylia_t* link, bool on);
void hylia_process(hylia_t* link, uint32_t frames, hylia_time_info_t* info);
void hylia_set_tempo(hylia_t* link, double tempo);
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_cleanup(hylia_t* link);

#ifdef __cplusplus
Expand Down
17 changes: 10 additions & 7 deletions link/AudioEngine.cpp
Expand Up @@ -25,7 +25,7 @@

namespace ableton
{
namespace linkaudio
namespace link
{

AudioEngine::AudioEngine(Link& link)
Expand All @@ -42,7 +42,7 @@ double AudioEngine::beatTime() const

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

Expand All @@ -53,18 +53,20 @@ double AudioEngine::quantum() const

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

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

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

engineData.resetBeatTime = mSharedEngineData.resetBeatTime;
engineData.quantum = mSharedEngineData.quantum;
mSharedEngineData.resetBeatTime = false;
Expand Down Expand Up @@ -98,10 +100,11 @@ void AudioEngine::timelineCallback(const std::chrono::microseconds hostTime, Lin
mLink.commitAudioTimeline(timeline);

// Save timeline info
info->bpm = timeline.tempo();
info->beats = timeline.beatAtTime(hostTime, engineData.quantum);
info->phase = timeline.phaseAtTime(hostTime, engineData.quantum);
info->beatsPerBar = engineData.quantum;
info->beatsPerMinute = timeline.tempo();
info->beat = timeline.beatAtTime(hostTime, engineData.quantum);
info->phase = timeline.phaseAtTime(hostTime, engineData.quantum);
}

} // namespace linkaudio
} // namespace link
} // namespace ableton
8 changes: 3 additions & 5 deletions link/AudioEngine.hpp
Expand Up @@ -25,12 +25,12 @@
#include <mutex>

struct LinkTimeInfo {
double bpm, beats, phase;
double beatsPerBar, beatsPerMinute, beat, phase;
};

namespace ableton
{
namespace linkaudio
namespace link
{

class AudioEngine
Expand All @@ -57,10 +57,8 @@ class AudioEngine
Link& mLink;
EngineData mSharedEngineData;
std::mutex mEngineDataGuard;

friend class AudioPlatform;
};


} // namespace linkaudio
} // namespace link
} // namespace ableton
26 changes: 17 additions & 9 deletions link/ableton/Link.hpp
Expand Up @@ -58,20 +58,20 @@ namespace ableton
* concurrently is not advised and will potentially lead to
* unexpected behavior.
*/
class Link
template <typename Clock>
class BasicLink
{
public:
using Clock = link::platform::Clock;
class Timeline;

/*! @brief Construct with an initial tempo. */
Link(double bpm);
BasicLink(double bpm);

/*! @brief Link instances cannot be copied or moved */
Link(const Link&) = delete;
Link& operator=(const Link&) = delete;
Link(Link&&) = delete;
Link& operator=(Link&&) = delete;
BasicLink(const BasicLink<Clock>&) = delete;
BasicLink& operator=(const BasicLink<Clock>&) = delete;
BasicLink(BasicLink<Clock>&&) = delete;
BasicLink& operator=(BasicLink<Clock>&&) = delete;

/*! @brief Is Link currently enabled?
* Thread-safe: yes
Expand Down Expand Up @@ -287,20 +287,28 @@ class Link
void forceBeatAtTime(double beat, std::chrono::microseconds time, double quantum);

private:
friend Link;
friend BasicLink<Clock>;

link::Timeline mOriginalTimeline;
bool mbRespectQuantum;
link::Timeline mTimeline;
};

private:
using Controller = ableton::link::Controller<link::PeerCountCallback,
link::TempoCallback,
Clock,
link::platform::IoContext>;

std::mutex mCallbackMutex;
link::PeerCountCallback mPeerCountCallback;
link::TempoCallback mTempoCallback;
Clock mClock;
link::platform::Controller mController;
Controller mController;
};

using Link = BasicLink<link::platform::Clock>;

} // ableton

#include <ableton/Link.ipp>

0 comments on commit 20bc92f

Please sign in to comment.