We are getting somewhere with aubio

This commit is contained in:
Stepland 2023-05-10 02:00:20 +02:00
parent 69a6f5437c
commit 56d1afb46f
4 changed files with 100 additions and 0 deletions

27
src/aubio_cpp.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "aubio_cpp.hpp"
#include <algorithm>
#include <iterator>
#include <limits>
#include <aubio/fvec.h>
namespace aubio {
std::optional<std::size_t> onset_detector::detect(const std::vector<sf::Int16>& samples) {
std::unique_ptr<fvec_t, decltype(&del_fvec)> out{new_fvec(2), del_fvec};
std::vector<float> input;
std::ranges::transform(samples, std::back_inserter(input), [](const sf::Int16 i) -> float {
return static_cast<float>(i) / std::numeric_limits<sf::Int16>::max();
});
fvec_t _input = {
.length=static_cast<uint_t>(input.size()),
.data=input.data(),
};
aubio_onset_do(this->get(), &_input, out.get());
if (out->data[0] != 0) {
return aubio_onset_get_last(this->get());
} else {
return {};
}
}
}

25
src/aubio_cpp.hpp Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include <functional>
#include <memory>
#include <aubio/aubio.h>
#include <aubio/onset/onset.h>
#include <SFML/Config.hpp>
// Thanks stack overflow !
// https://stackoverflow.com/a/54121092/10768117
template <auto F>
struct Functor {
template <typename... Args>
auto operator()(Args&&... args) const { return std::invoke(F, std::forward<Args>(args)...); }
};
namespace aubio {
using _aubio_onset_t_unique_ptr = std::unique_ptr<aubio_onset_t, Functor<del_aubio_onset>>;
struct onset_detector : _aubio_onset_t_unique_ptr {
template <typename... Args>
onset_detector(Args&&... args) : _aubio_onset_t_unique_ptr(new_aubio_onset(std::forward<Args>(args)...)) {}
std::optional<std::size_t> detect(const std::vector<sf::Int16>& samples);
};
}

31
src/guess_tempo.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "guess_tempo.hpp"
#include <SFML/Config.hpp>
#include <SFML/System/Utf.hpp>
#include <deque>
#include "aubio_cpp.hpp"
#include "custom_sfml_audio/precise_sound_stream.hpp"
std::vector<TempoEstimate> guess_tempo(feis::InputSoundFile& music) {
const auto onsets = detect_onsets(music);
}
std::vector<sf::Time> detect_onsets(feis::InputSoundFile& music) {
auto samplerate = music.getSampleRate();
std::size_t win_s = 1024; // window size
std::size_t hop_size = win_s / 4;
std::size_t read = 0;
std::vector<sf::Int16> samples(hop_size); // input audio buffer
std::vector<sf::Time> onsets;
auto detector = aubio::onset_detector("default", win_s, hop_size, samplerate);
do {
read = music.read(samples.data(), hop_size);
auto onset = detector.detect(samples);
// do something with the onsets
if (onset) {
onsets.push_back(samples_to_time(*onset, music.getSampleRate(), music.getChannelCount()));
}
} while ( read == hop_size );
aubio_cleanup();
return onsets;
}

17
src/guess_tempo.hpp Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include <SFML/System/Time.hpp>
#include <filesystem>
#include <vector>
#include "special_numeric_types.hpp"
#include "utf8_sfml_redefinitions.hpp"
struct TempoEstimate {
Decimal bpm;
sf::Time offset;
float fitness;
};
std::vector<TempoEstimate> guess_tempo(feis::InputSoundFile& music);
std::vector<sf::Time> detect_onsets(feis::InputSoundFile& music);