remove signal generator
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
#include <hack/logger/logger.hpp>
|
||||
#include "harmonica.hpp"
|
||||
|
||||
auto main() -> int
|
||||
{
|
||||
// setup создается для каждого файла свой
|
||||
// т.к. при чтении данных из файла уже должен быть определен размер блока
|
||||
// данных для чтения m_block_size; см. установки по умолчанию.
|
||||
// Передается по ссылке и заполняется необходимыми данными
|
||||
hr::setup setup;
|
||||
setup.m_domain = hr::DOMAIN_PLUGIN::FREQUENSY;
|
||||
setup.m_file = hr::TEST_SOUND;
|
||||
|
||||
auto r = hr::run<hr::plugins::magnitude>(setup);
|
||||
hack::log()("size:", r.m_data.size());
|
||||
|
||||
if (!r.empty())
|
||||
{
|
||||
std::vector<float> s;
|
||||
for (auto p : r.m_data) s.push_back(p.m_value[0]);
|
||||
hack::log()(s);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/workers/result.hpp"
|
||||
#include "utils/workers/setup.hpp"
|
||||
#include "utils/fft/fft.hpp"
|
||||
#include "utils/fvec/fvec.hpp"
|
||||
#include "utils/windows/hann/hann.hpp"
|
||||
|
||||
namespace hr
|
||||
{
|
||||
template<typename Plugin>
|
||||
class adapter
|
||||
{
|
||||
public:
|
||||
adapter(Plugin& p) : m_plugin { p }
|
||||
{
|
||||
m_end = m_plugin.m_setup.m_block_size - m_plugin.m_setup.m_step_size;
|
||||
m_data.resize(m_plugin.m_setup.m_block_size, 0.0);
|
||||
m_data_old.resize(m_end, 0.0);
|
||||
m_fft.init(m_plugin.m_setup.m_block_size);
|
||||
m_hann.creaate(m_plugin.m_setup.m_block_size);
|
||||
}
|
||||
|
||||
virtual ~adapter() { }
|
||||
|
||||
protected:
|
||||
Plugin& m_plugin;
|
||||
real_time m_timestamp;
|
||||
fft m_fft;
|
||||
math::hann m_hann;
|
||||
fvec_t m_data;
|
||||
fvec_t m_data_old;
|
||||
size_t m_end;
|
||||
|
||||
public:
|
||||
void process(fvec_t& in, real_time timestamp)
|
||||
{
|
||||
m_timestamp = timestamp;
|
||||
|
||||
switch(m_plugin.m_setup.m_domain)
|
||||
{
|
||||
case DOMAIN_PLUGIN::TIME:
|
||||
{
|
||||
m_plugin.process(in, m_timestamp);
|
||||
break;
|
||||
}
|
||||
case DOMAIN_PLUGIN::FREQUENSY:
|
||||
{
|
||||
frequensy(in);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result get_result() { return m_plugin.get_result(); }
|
||||
|
||||
private:
|
||||
void swap_buffer(fvec_t& in)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (i = 0; i < m_end; ++i) m_data[i] = m_data_old[i];
|
||||
for (i = 0; i < m_plugin.m_setup.m_step_size; ++i) m_data[m_end + i] = in[i];
|
||||
for (i = 0; i < m_end; ++i) m_data_old[i] = m_data[i + m_plugin.m_setup.m_step_size];
|
||||
}
|
||||
|
||||
void frequensy(fvec_t& in)
|
||||
{
|
||||
swap_buffer(in);
|
||||
m_hann.apply(m_data);
|
||||
m_data.shift();
|
||||
auto r = m_fft.process(m_data);
|
||||
m_plugin.process(r, in, m_timestamp);
|
||||
}
|
||||
};
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include <sndfile.h>
|
||||
#include <hack/logger/logger.hpp>
|
||||
|
||||
#include "utils/var.hpp" // IWYU pragma: keep
|
||||
#include "utils/using.hpp"
|
||||
#include "utils/workers/setup.hpp"
|
||||
#include "utils/workers/result.hpp"
|
||||
#include "adapter/adapter.hpp"
|
||||
|
||||
#include "plugins/magnitude/magnitude.hpp" // IWYU pragma: keep
|
||||
#include "plugins/signal_generator/signal_generator.hpp" // IWYU pragma: keep
|
||||
|
||||
namespace hr
|
||||
{
|
||||
/**
|
||||
* @brief Запуск на чтение аудиофайла и обработка его через плагин
|
||||
* @tparam Plugin Тип плагина для обработки аудиоданных
|
||||
* @param setup Настройки обработки (путь к файлу, параметры и т.д.)
|
||||
* @return Результат обработки аудио
|
||||
*/
|
||||
template<typename Plugin>
|
||||
inline result run(setup& setup)
|
||||
{
|
||||
if (setup.m_signal_type.m_type != hr::signal_type::type::FILE)
|
||||
{
|
||||
Plugin pl { setup };
|
||||
adapter ad { pl };
|
||||
// просто заглушки для process
|
||||
fvec_t v;
|
||||
real_time t;
|
||||
ad.process(v, t);
|
||||
return ad.get_result();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Инициализация структуры для libsndfile и открытие файла
|
||||
SF_INFO sf_info;
|
||||
SNDFIoLE* file = sf_open(setup.m_file.c_str(), SFM_READ, &sf_info);
|
||||
if (!file)
|
||||
{
|
||||
// Обработка ошибки открытия файла
|
||||
hack::exception ex;
|
||||
hack::log().on_file();
|
||||
hack::log().on_func();
|
||||
hack::log().on_row();
|
||||
ex.title("Error of open file");
|
||||
ex.description(sf_strerror(file));
|
||||
ex.set("file", setup.m_file);
|
||||
hack::error()(ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// Сохранение информации о файле в настройки
|
||||
setup.m_sample_rate = sf_info.samplerate;
|
||||
setup.m_frames = sf_info.frames;
|
||||
setup.m_channels = sf_info.channels;
|
||||
|
||||
if (setup.m_channels == 0) throw std::runtime_error("Нет каналов в аудио файле");
|
||||
|
||||
// Инициализация переменных для чтения
|
||||
std::size_t read = 0; // Количество обработанных кадров
|
||||
fvec_t read_data(setup.m_channels * setup.m_step_size, .0); // Буфер для чтения (интерливированные данные)
|
||||
fvec_t in(setup.m_step_size, .0); // Буфер для моно-данных
|
||||
|
||||
// Создание плагина и адаптера для обработки
|
||||
Plugin pl { setup };
|
||||
adapter ad { pl };
|
||||
|
||||
do
|
||||
{
|
||||
// Определение длины читаемого блока (защита от выхода за границы)
|
||||
auto length = hack::math::min(setup.m_step_size, in.size());
|
||||
auto read_samples = sf_read_float(file, read_data.data(), read_data.size());
|
||||
|
||||
uint_t read_length = read_samples / setup.m_channels; // Перевод в кадры
|
||||
read_length = hack::math::min(length, read_length); // Ограничение длиной буфера
|
||||
|
||||
// Де-интерливирование и down-mixing (преобразование многоканального в моно)
|
||||
for (std::size_t i = 0; i < read_length; ++i)
|
||||
{
|
||||
in[i] = 0.0;
|
||||
// Суммирование всех каналов
|
||||
for (int c = 0; c < setup.m_channels; ++c)
|
||||
in[i] += read_data[setup.m_channels * i + c];
|
||||
// Усреднение для получения моно-сигнала
|
||||
in[i] /= static_cast<base_t>(setup.m_channels);
|
||||
}
|
||||
|
||||
// Подготовка к следующей итерации
|
||||
read = hack::math::min(length, static_cast<uint_t>(floorf(read_length + .5)));
|
||||
|
||||
// Дополнение буфера нулями если считано неполный блок (конец файла)
|
||||
if (in.size() > read) std::fill(in.begin() + read, in.end(), 0.0);
|
||||
|
||||
// Вычисление временной метки и обработка данных через адаптер
|
||||
real_time timestamp = real_time::frame2rt(read, sf_info.samplerate);
|
||||
ad.process(in, timestamp);
|
||||
}
|
||||
while (read == setup.m_step_size); // Продолжать пока читаются полные блоки
|
||||
|
||||
// Закрытие файла и возврат результата
|
||||
sf_close(file);
|
||||
return ad.get_result();
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/workers/plugin.hpp"
|
||||
|
||||
namespace hr::plugins
|
||||
{
|
||||
class magnitude : public plugin
|
||||
{
|
||||
public:
|
||||
magnitude(const setup& st);
|
||||
virtual ~magnitude() = default;
|
||||
|
||||
private:
|
||||
result m_result;
|
||||
|
||||
public:
|
||||
void process(fvec_t& base, real_time timestamp) override;
|
||||
void process(cvec_t& fft, fvec_t& base, real_time timestamp) override;
|
||||
result get_result() override;
|
||||
};
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/workers/plugin.hpp"
|
||||
#include "utils/workers/result.hpp"
|
||||
|
||||
// Генерирует простую синусоиду и др. полезности см. workers/signal_type.hpp
|
||||
namespace hr::plugins
|
||||
{
|
||||
// Формула синусоиды
|
||||
// f(t) = A_m sin(2 PI t 1/T + a)
|
||||
// где
|
||||
// a - начальная фаза
|
||||
// t - время замера
|
||||
// 1/T - частота
|
||||
// T - время полного цикла одного периуда колебаний
|
||||
class signal_generator : public plugin
|
||||
{
|
||||
public:
|
||||
signal_generator(const setup& st);
|
||||
virtual ~signal_generator() = default;
|
||||
|
||||
public:
|
||||
void process(fvec_t& base, real_time timestamp) override;
|
||||
void process(cvec_t& fft, fvec_t& base, real_time timestamp) override;
|
||||
result get_result() override;
|
||||
|
||||
private:
|
||||
result m_result;
|
||||
|
||||
private:
|
||||
std::vector<float> sin();
|
||||
std::vector<float> square();
|
||||
std::vector<float> triangle();
|
||||
std::vector<float> saw();
|
||||
std::vector<float> noise_only();
|
||||
std::vector<float> speech_like();
|
||||
std::vector<float> three_sines();
|
||||
|
||||
private:
|
||||
};
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace hr
|
||||
{
|
||||
using base_t = float;
|
||||
using uint_t = unsigned int;
|
||||
|
||||
// HERE
|
||||
// убрать это чтоб не было желяния превраить это по аналогии с fvec_t
|
||||
using ivec_t = std::vector<int>;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "noincl.hpp" // IWYU pragma: keep
|
||||
namespace hr { }
|
||||
Binary file not shown.
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "utils/real_time/real_time.hpp"
|
||||
#include "utils/fvec/fvec.hpp"
|
||||
#include <hack/logger/logger.hpp>
|
||||
|
||||
namespace hr
|
||||
{
|
||||
struct result
|
||||
{
|
||||
struct bit
|
||||
{
|
||||
real_time m_duration;
|
||||
fvec_t m_value;
|
||||
};
|
||||
|
||||
void set_bit(bit& b)
|
||||
{
|
||||
m_data.push_back(b);
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
bool res = true;
|
||||
try
|
||||
{
|
||||
if (!m_data.empty()) res = m_data.at(0).m_value.empty();
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
hack::error()(e.what());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<bit> m_data;
|
||||
};
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/workers/signals/signal_type.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
namespace hr
|
||||
{
|
||||
enum class DOMAIN_PLUGIN
|
||||
{
|
||||
TIME,
|
||||
FREQUENSY
|
||||
};
|
||||
|
||||
struct setup
|
||||
{
|
||||
// Эти данные заполняются из прочитанного файла (sndfile)
|
||||
int m_sample_rate;
|
||||
int m_frames;
|
||||
int m_channels;
|
||||
|
||||
std::filesystem::path m_file;
|
||||
std::size_t m_block_size = 1'024;
|
||||
std::size_t m_step_size = 512;
|
||||
|
||||
signal_type m_signal_type;
|
||||
DOMAIN_PLUGIN m_domain = DOMAIN_PLUGIN::FREQUENSY;
|
||||
};
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user