remove signal generator
This commit is contained in:
@@ -3,14 +3,13 @@
|
||||
#include <sndfile.h>
|
||||
#include <hack/logger/logger.hpp>
|
||||
|
||||
#include "utils/var.hpp" // IWYU pragma: keep
|
||||
#include "utils/signal_generator/signal_generator.hpp" // IWYU pragma: keep
|
||||
#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/magnitude/magnitude.hpp" // IWYU pragma: keep
|
||||
|
||||
namespace hr
|
||||
{
|
||||
@@ -88,9 +87,10 @@ namespace hr
|
||||
}
|
||||
while (read == setup.m_step_size); // Продолжать пока читаются полные блоки
|
||||
|
||||
hack::log()("adf");
|
||||
|
||||
// Закрытие файла и возврат результата
|
||||
sf_close(file);
|
||||
|
||||
return ad.get_result();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ headers = [
|
||||
'utils/workers/result.hpp',
|
||||
'utils/workers/setup.hpp',
|
||||
'utils/windows/hann/hann.hpp',
|
||||
'utils/signal_generator/signal_generator.hpp',
|
||||
|
||||
# plugins
|
||||
'plugins/magnitude/magnitude.hpp',
|
||||
@@ -26,7 +25,6 @@ sources = [
|
||||
'utils/fvec/fvec.cpp',
|
||||
|
||||
'utils/windows/hann/hann.cpp',
|
||||
'utils/signal_generator/signal_generator.cpp',
|
||||
|
||||
# plugins
|
||||
'plugins/magnitude/magnitude.cpp',
|
||||
|
||||
@@ -6,10 +6,13 @@ namespace hr::plugins
|
||||
{
|
||||
}
|
||||
|
||||
void magnitude::process(fvec_t& base, real_time timestamp)
|
||||
{
|
||||
}
|
||||
|
||||
void magnitude::process(cvec_t& fft, fvec_t& base, real_time timestamp)
|
||||
{
|
||||
std::size_t frames = fft.size();
|
||||
|
||||
base_t m = 0.f;
|
||||
for (std::size_t i = 0; i < frames; ++i) m += fft.m_norm[i];
|
||||
m /= frames;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace hr::plugins
|
||||
result m_result;
|
||||
|
||||
public:
|
||||
void process(fvec_t& base, real_time timestamp) override {};
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
#include "signal_generator.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace hr
|
||||
{
|
||||
result signal_generator::generate(signal_type st, NOISE noise)
|
||||
{
|
||||
std::vector<float> tmp;
|
||||
switch (st.m_type)
|
||||
{
|
||||
case signal_type::type::SIN:
|
||||
tmp = sin(noise);
|
||||
break;
|
||||
case signal_type::type::SQUARE:
|
||||
tmp = square(noise);
|
||||
break;
|
||||
case signal_type::type::TRIANGLE:
|
||||
tmp = triangle(noise);
|
||||
break;
|
||||
case signal_type::type::SAW:
|
||||
tmp = saw(noise);
|
||||
break;
|
||||
case signal_type::type::SPEECH_LIKE:
|
||||
tmp = speech_like(noise);
|
||||
break;
|
||||
case signal_type::type::NOISE_ONLY:
|
||||
tmp = noise_only();
|
||||
break;
|
||||
case signal_type::type::THREE_SINES:
|
||||
tmp = three_sines(noise);
|
||||
break;
|
||||
}
|
||||
|
||||
result res;
|
||||
for (auto t : tmp)
|
||||
{
|
||||
result::bit b;
|
||||
b.m_value.push_back(t);
|
||||
res.set_bit(b);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<float> signal_generator::sin(NOISE noise)
|
||||
{
|
||||
std::vector<float> signal(m_params.m_samples);
|
||||
for (std::size_t i = 0; i < m_params.m_samples; ++i)
|
||||
{
|
||||
float t = i * 0.02f;
|
||||
signal[i] = m_params.m_amplitude * std::sin(m_params.m_frequency * t * 2 * M_PI);
|
||||
}
|
||||
|
||||
if (noise == NOISE::YES)
|
||||
{
|
||||
// создаем распределение случайных величин
|
||||
std::uniform_real_distribution<> dist(-m_params.m_noise_level, m_params.m_noise_level);
|
||||
for (auto& s : signal) s += dist(m_gen);
|
||||
}
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
std::vector<float> signal_generator::square(NOISE noise)
|
||||
{
|
||||
std::vector<float> signal(m_params.m_samples);
|
||||
for (std::size_t i = 0; i < m_params.m_samples; ++i)
|
||||
{
|
||||
float t = i * 0.02f;
|
||||
float phase = m_params.m_frequency * t * 2 * M_PI;
|
||||
// Прямоугольный сигнал: +1 когда sin > 0, -1 когда sin < 0
|
||||
signal[i] = m_params.m_amplitude * (std::sin(phase) > 0 ? 1.0f : -1.0f);
|
||||
}
|
||||
|
||||
if (noise == NOISE::YES)
|
||||
{
|
||||
std::uniform_real_distribution<> dist(-m_params.m_noise_level, m_params.m_noise_level);
|
||||
for (auto& s : signal) s += dist(m_gen);
|
||||
}
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
std::vector<float> signal_generator::triangle(NOISE noise)
|
||||
{
|
||||
std::vector<float> signal(m_params.m_samples);
|
||||
for (std::size_t i = 0; i < m_params.m_samples; ++i)
|
||||
{
|
||||
float t = i * 0.02f;
|
||||
float phase = fmod(m_params.m_frequency * t, 1.0f); // 0..1
|
||||
|
||||
// Треугольный сигнал: линейный рост от -1 до 1, потом падение
|
||||
if (phase < 0.25f) signal[i] = m_params.m_amplitude * (4.0f * phase); // 0..1
|
||||
else if (phase < 0.75f) signal[i] = m_params.m_amplitude * (2.0f - 4.0f * phase); // 1..-1
|
||||
else signal[i] = m_params.m_amplitude * (4.0f * phase - 4.0f); // -1..0
|
||||
}
|
||||
|
||||
if (noise == NOISE::YES)
|
||||
{
|
||||
std::uniform_real_distribution<> dist(-m_params.m_noise_level, m_params.m_noise_level);
|
||||
for (auto& s : signal) s += dist(m_gen);
|
||||
}
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
std::vector<float> signal_generator::saw(NOISE noise)
|
||||
{
|
||||
std::vector<float> signal(m_params.m_samples);
|
||||
for (std::size_t i = 0; i < m_params.m_samples; ++i)
|
||||
{
|
||||
float t = i * 0.02f;
|
||||
float phase = fmod(m_params.m_frequency * t, 1.0f); // 0..1
|
||||
|
||||
// Пилообразный сигнал: линейный рост от -1 до 1, потом резкий сброс
|
||||
signal[i] = m_params.m_amplitude * (2.0f * phase - 1.0f); // -1..1
|
||||
}
|
||||
|
||||
if (noise == NOISE::YES)
|
||||
{
|
||||
std::uniform_real_distribution<> dist(-m_params.m_noise_level, m_params.m_noise_level);
|
||||
for (auto& s : signal) s += dist(m_gen);
|
||||
}
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
std::vector<float> signal_generator::noise_only()
|
||||
{
|
||||
std::vector<float> signal(m_params.m_samples);
|
||||
std::uniform_real_distribution<> dist(-m_params.m_amplitude, m_params.m_amplitude);
|
||||
|
||||
for (std::size_t i = 0; i < m_params.m_samples; ++i)
|
||||
signal[i] = dist(m_gen);
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
std::vector<float> signal_generator::speech_like(NOISE noise)
|
||||
{
|
||||
std::vector<float> signal(m_params.m_samples);
|
||||
|
||||
// Базовая частота (основной тон речи)
|
||||
float base_freq = m_params.m_frequency;
|
||||
|
||||
// Добавляем гармоники, как в реальной речи
|
||||
float harmonics[] = { 2.0f, 3.0f, 4.0f, 5.0f }; // гармоники
|
||||
float harmonics_amp[] = { 0.7f, 0.5f, 0.3f, 0.2f }; // их амплитуды
|
||||
|
||||
// Форманты (резонансные частоты речи)
|
||||
float formants[] = {500.0f, 1500.0f, 2500.0f, 3500.0f};
|
||||
float formants_amp[] = {0.4f, 0.6f, 0.3f, 0.2f};
|
||||
|
||||
// Модуляция амплитуды (как при произношении слогов)
|
||||
float envelope_freq = 2.0f; // частота слогов
|
||||
|
||||
for (std::size_t i = 0; i < m_params.m_samples; ++i)
|
||||
{
|
||||
float t = i * 0.02f;
|
||||
float value = 0.0f;
|
||||
|
||||
// Основной тон + гармоники
|
||||
for (int h = 0; h < 4; h++)
|
||||
value += harmonics_amp[h] * std::sin(2 * M_PI * base_freq * harmonics[h] * t);
|
||||
|
||||
// Форманты (резонансы)
|
||||
for (int f = 0; f < 4; f++)
|
||||
value += formants_amp[f] * std::sin(2 * M_PI * formants[f] * t * 0.001f); // kHz to Hz
|
||||
|
||||
// Огибающая (модуляция амплитуды)
|
||||
float envelope = 0.5f + 0.5f * std::sin(2 * M_PI * envelope_freq * t);
|
||||
|
||||
// Добавляем немного шума (дыхание)
|
||||
std::uniform_real_distribution<> breath_noise(-0.1f, 0.1f);
|
||||
float breath = breath_noise(m_gen);
|
||||
|
||||
// И немного низкочастотной модуляции (вибрато)
|
||||
float vibrato = 0.1f * std::sin(2 * M_PI * 5.0f * t); // 5 Hz vibrato
|
||||
|
||||
signal[i] = m_params.m_amplitude * envelope * (value + breath + vibrato);
|
||||
}
|
||||
|
||||
// Нормализуем
|
||||
float max_val = *std::max_element(signal.begin(), signal.end(),
|
||||
[](float a, float b) { return std::abs(a) < std::abs(b); });
|
||||
if (max_val > 0)
|
||||
for (auto& s : signal) s /= max_val;
|
||||
|
||||
// Добавляем дополнительный шум если нужно
|
||||
if (noise == NOISE::YES)
|
||||
{
|
||||
std::uniform_real_distribution<> dist(-m_params.m_noise_level, m_params.m_noise_level);
|
||||
for (auto& s : signal) s += dist(m_gen);
|
||||
}
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
std::vector<float> signal_generator::three_sines(NOISE noise)
|
||||
{
|
||||
std::vector<float> signal(m_params.m_samples);
|
||||
|
||||
// три разные частоты
|
||||
float f1 = m_params.m_frequency;
|
||||
float f2 = m_params.m_frequency * 2.f;
|
||||
|
||||
// амплитуды
|
||||
float a1 = m_params.m_amplitude;
|
||||
float a2 = m_params.m_amplitude * 0.5f;
|
||||
|
||||
for (std::size_t i = 0; i < m_params.m_samples; ++i)
|
||||
{
|
||||
float t = i * 0.02f;
|
||||
signal[i] = a1 * std::sin(2 * M_PI * f1 * t) +
|
||||
a2 * std::sin(2 * M_PI * f2 * t + 3.f/4.f* M_PI);
|
||||
}
|
||||
|
||||
if (noise == NOISE::YES)
|
||||
{
|
||||
std::uniform_real_distribution<> dist(-m_params.m_noise_level, m_params.m_noise_level);
|
||||
for (auto& s : signal) s += dist(m_gen);
|
||||
}
|
||||
|
||||
return signal;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <random>
|
||||
#include "utils/workers/signal_type.hpp"
|
||||
#include "utils/workers/result.hpp"
|
||||
|
||||
// Генерирует простую синусоиду и др. полезности см. workers/signal_type.hpp
|
||||
namespace hr
|
||||
{
|
||||
enum class NOISE
|
||||
{
|
||||
NO,
|
||||
YES
|
||||
};
|
||||
|
||||
// Формула синусоиды
|
||||
// f(t) = A_m sin(2 PI t 1/T + a)
|
||||
// где
|
||||
// a - начальная фаза
|
||||
// t - время замера
|
||||
// 1/T - частота
|
||||
// T - время полного цикла одного периуда колебаний
|
||||
class signal_generator
|
||||
{
|
||||
public:
|
||||
signal_generator() : m_gen(12345) {}
|
||||
|
||||
public:
|
||||
result generate(signal_type st, NOISE noise = NOISE::NO);
|
||||
|
||||
public:
|
||||
struct signal_params
|
||||
{
|
||||
float m_amplitude = 1.0f; // A
|
||||
float m_frequency = 1.0f; // 1/T
|
||||
float m_noise_level = 0.7f;
|
||||
std::size_t m_samples = 1200;
|
||||
} m_params;
|
||||
|
||||
private:
|
||||
std::vector<float> sin(NOISE noise);
|
||||
std::vector<float> square(NOISE noise);
|
||||
std::vector<float> triangle(NOISE noise);
|
||||
std::vector<float> saw(NOISE noise);
|
||||
std::vector<float> noise_only();
|
||||
std::vector<float> speech_like(NOISE noise);
|
||||
std::vector<float> three_sines(NOISE noise);
|
||||
|
||||
private:
|
||||
std::mt19937 m_gen;
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/workers/signal_type.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
namespace hr
|
||||
@@ -22,7 +21,6 @@ namespace hr
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace hr
|
||||
{
|
||||
// Некая структура описывающая базоввые типы сигналов
|
||||
struct signal_type
|
||||
{
|
||||
enum class type
|
||||
{
|
||||
FILE, // Из файла
|
||||
SIN, // Синусоида
|
||||
SQUARE, // Прямоугольный
|
||||
TRIANGLE, // Треугольный
|
||||
SAW, // Пилообразный
|
||||
NOISE_ONLY, // Только шум
|
||||
SPEECH_LIKE, // Типа речь
|
||||
THREE_SINES // Три частоты
|
||||
} m_type = type::FILE;
|
||||
|
||||
signal_type() = default;
|
||||
explicit signal_type(type t) : m_type(t) {}
|
||||
|
||||
// Получить имя типа
|
||||
std::string get_name() const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case type::FILE: return "FILE";
|
||||
case type::SIN: return "SIN";
|
||||
case type::SQUARE: return "SQUARE";
|
||||
case type::TRIANGLE: return "TRIANGLE";
|
||||
case type::SAW: return "SAW";
|
||||
case type::NOISE_ONLY: return "NOISE_ONLY";
|
||||
case type::SPEECH_LIKE: return "SPEECH_LIKE";
|
||||
case type::THREE_SINES: return "THREE_SINES";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(const signal_type& other) const
|
||||
{
|
||||
return m_type < other.m_type;
|
||||
}
|
||||
|
||||
bool operator==(const signal_type& other) const
|
||||
{
|
||||
return m_type == other.m_type;
|
||||
}
|
||||
};
|
||||
|
||||
// просто для итерации в графическом интерфейсе
|
||||
inline const std::vector<signal_type>& all_types()
|
||||
{
|
||||
static const std::vector<signal_type> signals = {
|
||||
signal_type(signal_type::type::FILE),
|
||||
signal_type(signal_type::type::SIN),
|
||||
signal_type(signal_type::type::SQUARE),
|
||||
signal_type(signal_type::type::TRIANGLE),
|
||||
signal_type(signal_type::type::SAW),
|
||||
signal_type(signal_type::type::NOISE_ONLY),
|
||||
signal_type(signal_type::type::SPEECH_LIKE),
|
||||
signal_type(signal_type::type::THREE_SINES)
|
||||
};
|
||||
return signals;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user