Permalink
Browse files

cv2midiclock

  • Loading branch information...
mlang committed Jul 27, 2017
1 parent 28ecae0 commit ab0fccd4db0675847f3191578383df90effe0cdd
Showing with 117 additions and 64 deletions.
  1. +2 −2 CMakeLists.txt
  2. +75 −0 cv2midiclock.cpp
  3. +0 −55 edge.cpp
  4. +33 −0 lib/dsp.hpp
  5. +1 −1 lib/jack.hpp
  6. +6 −6 lib/midi.hpp
View
@@ -12,6 +12,6 @@ add_executable(stats stats.cpp)
target_link_libraries(stats IO Boost::boost)
add_executable(brltest brltest.cpp)
target_link_libraries(brltest IO)
add_executable(edge edge.cpp)
target_link_libraries(edge IO)
add_executable(cv2midiclock cv2midiclock.cpp)
target_link_libraries(cv2midiclock IO)
View
@@ -0,0 +1,75 @@
#include <chrono>
#include <thread>
#include <jack.hpp>
#include <dsp.hpp>
class EdgeDetect : public JACK::Client {
JACK::AudioIn CVIn;
JACK::MIDIOut MIDIOut;
BrlCV::EWMA<decltype(CVIn)::value_type> FastAverage, SlowAverage;
decltype(CVIn)::value_type PreviousDifference = 0;
std::size_t FramesSinceLastPulse = 0, FramesPerPulse = 0, FramesUntilNextMIDIClock = 0, MIDIClockPulse = 0;
float const Threshold;
BrlCV::FairSegmentation<24> MIDIClockFrameCount;
public:
EdgeDetect(float Threshold = 0.2) : JACK::Client("EdgeDetect")
, CVIn(createAudioIn("In"))
, MIDIOut(createMIDIOut("Out"))
, FastAverage(0.25), SlowAverage(0.0625)
, FramesUntilNextMIDIClock(0)
, Threshold(Threshold)
{ Expects(Threshold > 0); }
int process(std::uint32_t FrameCount) override {
auto MIDIBuffer = MIDIOut.buffer(FrameCount);
int PulseOffset = -1;
std::size_t Frame = 0;
MIDIBuffer.clear();
for (auto Sample : CVIn.buffer(FrameCount)) {
auto Difference = FastAverage(Sample) - SlowAverage(Sample);
if (PreviousDifference < Threshold && Difference > Threshold) {
PulseOffset = Frame;
FramesPerPulse = FramesSinceLastPulse;
FramesSinceLastPulse = 0;
}
PreviousDifference = Difference;
Frame += 1; FramesSinceLastPulse += 1;
}
if (FramesPerPulse) {
if (PulseOffset != -1) {
MIDIClockPulse = 0;
MIDIClockFrameCount = FramesPerPulse;
MIDIBuffer[PulseOffset] = MIDI::SystemRealTimeMessage::Clock;
FramesUntilNextMIDIClock = MIDIClockFrameCount[MIDIClockPulse++];
FramesUntilNextMIDIClock -= FrameCount - PulseOffset;
} else if (MIDIClockPulse < 24) {
if (FramesUntilNextMIDIClock < FrameCount) {
MIDIBuffer[FramesUntilNextMIDIClock] = MIDI::SystemRealTimeMessage::Clock;
FramesUntilNextMIDIClock = MIDIClockFrameCount[MIDIClockPulse++] - (FrameCount - FramesUntilNextMIDIClock);
} else {
FramesUntilNextMIDIClock -= FrameCount;
}
}
}
return 0;
}
};
using namespace std::literals::chrono_literals;
int main() {
EdgeDetect App;
App.activate();
while (true) {
std::this_thread::sleep_for(10ms);
}
return EXIT_SUCCESS;
}
View

This file was deleted.

Oops, something went wrong.
View
@@ -1,6 +1,9 @@
#if !defined(BrlCV_DSP_HPP)
#define BrlCV_DSP_HPP
#include <bitset>
#include <gsl/gsl>
namespace BrlCV {
// https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
@@ -24,6 +27,36 @@ class ExponentiallyWeightedMovingAverage {
template<typename T> using EWMA = ExponentiallyWeightedMovingAverage<T>;
template<std::size_t N>
class FairSegmentation {
std::size_t SegmentSize;
std::bitset<N> Set;
public:
FairSegmentation() : SegmentSize(0), Set(0) {}
FairSegmentation(std::size_t Size) : SegmentSize(Size / N), Set(0) {
auto const R = Size % N;
for (auto I = 0; I < R; ++I) Set.set(N*I/R);
Ensures(Set.count() == R);
}
FairSegmentation &operator=(std::size_t Size) {
SegmentSize = Size / N;
Set.reset();
auto const R = Size % N;
for (auto I = 0; I < R; ++I) Set.set(N*I/R);
Ensures(Set.count() == R);
}
constexpr bool empty() const { return N == 0; }
constexpr std::size_t size() const { return N; }
std::size_t operator[](std::size_t Position) const {
Expects(Position < N);
return SegmentSize + Set.test(Position);
}
};
} // namespace BrlCV
#endif // BrlCV_DSP_HPP
View
@@ -77,7 +77,7 @@ class MIDIBuffer {
return reserve(FrameOffset, Size);
}
Index operator[](std::uint32_t FrameOffset) {
Ensures(FrameOffset < Frames);
Expects(FrameOffset < Frames);
return { *this, FrameOffset };
}
};
View
@@ -4,12 +4,12 @@
namespace MIDI {
enum class SystemRealTimeMessage {
Clock = 0b11111000,
Start = 0b11111010,
Continue = 0b11111011,
Stop = 0b11111100,
ActiveSensing = 0b11111110,
Reset = 0b11111111
Clock = 0b11111'000,
Start = 0b11111'010,
Continue = 0b11111'011,
Stop = 0b11111'100,
ActiveSensing = 0b11111'110,
Reset = 0b11111'111
};
}

0 comments on commit ab0fccd

Please sign in to comment.