diff --git a/.gitignore b/.gitignore index aa7dccb..85151b9 100755 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ build .cache subprojects/* !subprojects/catch2.wrap +bin/test diff --git a/bin/main.cpp b/bin/main.cpp index a82cef6..ac50ea6 100644 --- a/bin/main.cpp +++ b/bin/main.cpp @@ -1,6 +1,10 @@ #include #include +#include "hack/audio/generate.hpp" +#include "hack/audio/play.hpp" +#include "hack/audio/save.hpp" + #include "hack/logger/logger.hpp" #include "hack/range/sort.hpp" @@ -14,6 +18,28 @@ auto main(int argc, char *argv[]) -> int { + { + int sample_rate = 44100; + // Воспроизведение последовательности нот + hack::warn()("Пример использования: audio"); + + std::vector frequencies = { 130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 233.08, 246.94 }; + std::vector melody; + for (double freq : frequencies) + { + auto note = hack::audio::generate::sine(freq, 0.3, sample_rate); + melody.insert(melody.end(), note.begin(), note.end()); + // Добавляем небольшую паузу между нотами. Т.е. вставляем кол-во с нулевым значением. + melody.insert(melody.end(), sample_rate * 0.05, 0.0); + } + + hack::log()("Воспроизведение последовательности нот..."); + hack::audio::play(melody, sample_rate); + + hack::log()("Запись последовательности нот в файл"); + hack::audio::save("/mnt/raid/projects/hack/hack/bin/test/note.wav", melody, sample_rate); + } + // patterns::ring_buffer { hack::patterns::ring_buffer rb; @@ -55,8 +81,8 @@ auto main(int argc, char *argv[]) -> int hack::log()(v); hack::log()(l); - // hack::range::save_to_file("/mnt/raid/projects/hack/hack/test.txt", v); - // hack::range::save_to_file("/mnt/raid/projects/hack/hack/test.txt", v, ":"); + hack::range::save_to_file("/mnt/raid/projects/hack/hack/bin/test/range.txt", v); + hack::range::save_to_file("/mnt/raid/projects/hack/hack/bin/test/range.delemiter.txt", v, ":"); } // math::max diff --git a/meson.build b/meson.build index 99a70d0..38d3c5f 100755 --- a/meson.build +++ b/meson.build @@ -31,6 +31,7 @@ args = [] inc = [] deps = [ dependency('uuid'), + dependency('sndfile'), dependency('portaudio-2.0', required: true) ] diff --git a/src/hack/audio/generate.hpp b/src/hack/audio/generate.hpp new file mode 100644 index 0000000..6a65f84 --- /dev/null +++ b/src/hack/audio/generate.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include +#include + +// Генерация разнообразных звуковых волн +namespace hack::audio::generate +{ + // Генерация синусоидального сигнала + inline std::vector sine(double frequency, double duration, int sample_rate) + { + std::vector samples; + int total_samples = static_cast(duration * sample_rate); + + for (int i = 0; i < total_samples; ++i) + { + double time = static_cast(i) / sample_rate; + double sample = 0.5 * std::sin(2.0 * M_PI * frequency * time); + samples.push_back(sample); + } + + return samples; + } + + // Генерация прямоугольного сигнала + inline std::vector square_wave(double frequency, double duration, int sample_rate) + { + std::vector samples; + int total_samples = static_cast(duration * sample_rate); + int samples_per_period = sample_rate / frequency; + + for (int i = 0; i < total_samples; ++i) + { + double sample = ((i / samples_per_period) % 2 == 0) ? 0.5 : -0.5; + samples.push_back(sample); + } + + return samples; + } + + // Генерация белого шума + inline std::vector white_noise(double duration, int sample_rate) + { + std::vector samples; + int total_samples = static_cast(duration * sample_rate); + + for (int i = 0; i < total_samples; ++i) + { + double sample = (static_cast(rand()) / RAND_MAX) * 2.0 - 1.0; + samples.push_back(sample * 0.3); // Уменьшаем громкость + } + + return samples; + } +} + diff --git a/src/hack/audio/play.hpp b/src/hack/audio/play.hpp index 201e43c..fe9a59b 100644 --- a/src/hack/audio/play.hpp +++ b/src/hack/audio/play.hpp @@ -1,13 +1,13 @@ #pragma once #include -#include "hack/logger/logger.hpp" #include +#include "hack/logger/logger.hpp" namespace hack::audio { - // namespace - // { + namespace + { const int FRAMES_PER_BUFFER = 256; // callback - вызывается, когда нужны новые аудио-данные @@ -26,7 +26,7 @@ namespace hack::audio return (pos >= samples.size()) ? paComplete : paContinue; } - // } + } // пока только wav inline void play(std::vector& samples, int sample_rate) diff --git a/src/hack/audio/save.hpp b/src/hack/audio/save.hpp index c64cc13..a79bac1 100644 --- a/src/hack/audio/save.hpp +++ b/src/hack/audio/save.hpp @@ -34,5 +34,3 @@ namespace hack::audio sf_close(outfile); } } - - diff --git a/src/hack/range/save_to_file.hpp b/src/hack/range/save_to_file.hpp index 85c9ac1..bc4c882 100644 --- a/src/hack/range/save_to_file.hpp +++ b/src/hack/range/save_to_file.hpp @@ -5,12 +5,15 @@ #include #include "hack/logger/logger.hpp" +// Записывает массив в файл с указанным разделителем namespace hack::range { namespace { template void save_to_file_impl(const std::filesystem::path& p, T& v, std::string delemiter = ", ") { + // Создаем директорию, если ее нет. + std::filesystem::create_directories(p.parent_path()); std::ofstream file(p); if (!file) { diff --git a/src/meson.build b/src/meson.build index 18165fa..be61d77 100755 --- a/src/meson.build +++ b/src/meson.build @@ -1,6 +1,11 @@ inc += include_directories('.') headers = [ + 'hack/audio/generate.hpp', + 'hack/audio/play.hpp', + 'hack/audio/save.hpp', + + 'hack/concepts/concepts.hpp', 'hack/iterators/associative_ostream_iterator.hpp', @@ -18,12 +23,10 @@ headers = [ 'hack/utils/color.hpp' ] -sources = [] - lib = library( meson.project_name(), include_directories : inc, - sources: [headers, sources], + sources: [headers], dependencies : deps, cpp_args: args ) diff --git a/test.txt b/test.txt deleted file mode 100644 index f7fa9aa..0000000 --- a/test.txt +++ /dev/null @@ -1 +0,0 @@ -1, 2, 3, 4, 4, 4, 6 \ No newline at end of file