diff options
author | Roland Reichwein <mail@reichwein.it> | 2025-01-03 21:02:11 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2025-01-03 21:02:11 +0100 |
commit | 22cdfccb11679d6ae241653c9cb92c32f4fc1fde (patch) | |
tree | 16b0f8401e22c99e8d953eea14ac57a2fe50c67a | |
parent | 6bf4770e950299da92952f2965cccf86a903fc9f (diff) |
Integrate ClickStream into PCM
-rw-r--r-- | ClickStream.cpp | 3 | ||||
-rw-r--r-- | ClickStream.h | 57 | ||||
-rw-r--r-- | MIDI.h | 7 | ||||
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | PCM.h | 60 | ||||
-rw-r--r-- | config.h | 2 | ||||
-rw-r--r-- | main.cpp | 8 |
7 files changed, 65 insertions, 73 deletions
diff --git a/ClickStream.cpp b/ClickStream.cpp deleted file mode 100644 index 0448af1..0000000 --- a/ClickStream.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "ClickStream.h" - - diff --git a/ClickStream.h b/ClickStream.h deleted file mode 100644 index c94f8de..0000000 --- a/ClickStream.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "config.h" - -#include <libreichwein/file.h> - -#include <cstring> -#include <string> -#include <vector> - -class ClickStream -{ -public: - ClickStream(): m_phase(1000000) - { - std::string data_s = Reichwein::File::getFile("media/click.s16le"); - m_data.resize(data_s.size() / 2); // src is in bytes - memcpy(m_data.data(), data_s.data(), data_s.size()); - } - - // generate 1 buffer size - void generate() - { - int i; - size_t j = m_phase; - - for (i = 0; i < nframes; i++) { - if (j >= m_data.size()) - { - buffer[i] = 0; - } - else - { - buffer[i] = m_data[j]; - } - j++; - } - - m_phase = j; - } - - void click() - { - m_phase = 0; - } - - int16_t* get_buffer() - { - return buffer; - } - -private: - std::vector<uint16_t> m_data; - size_t m_phase; - int16_t buffer[nframes]; -}; - @@ -158,6 +158,13 @@ public: } } + void flush() + { + while (event_ready()) { + (void) read(); + } + } + void wait_for_event() { int result = poll(pfd, npfd, 10000); @@ -6,7 +6,6 @@ SRCS= \ main.cpp \ MIDI.cpp \ PCM.cpp \ - ClickStream.cpp \ config.cpp \ UI.cpp \ Timer.cpp \ @@ -1,22 +1,29 @@ #pragma once -#include "ClickStream.h" - #include "config.h" +#include "log.h" + +#include <libreichwein/file.h> #include <alsa/asoundlib.h> #include <fmt/format.h> #include <iostream> #include <string> +#include <vector> using namespace std::string_literals; class PCM { public: - PCM(ClickStream& stream): m_stream(stream) + PCM(): m_phase(1000000) { + // prepare the sample + std::string data_s = Reichwein::File::getFile("media/click.s16le"); + m_data.resize(data_s.size() / 2); // src is in bytes + memcpy(m_data.data(), data_s.data(), data_s.size()); + // non-blocking if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { throw std::runtime_error(fmt::format("Playback open error: {}", snd_strerror(err))); @@ -27,11 +34,11 @@ public: 1, f_sample, 1, - 100000)) < 0) { // latency in us + pcm_latency_us)) < 0) { // latency in us throw std::runtime_error(fmt::format("Playback open error: {}", snd_strerror(err))); } - m_stream.generate(); + generate(); npfd = snd_pcm_poll_descriptors_count(handle); if (npfd < 0) { @@ -69,6 +76,33 @@ public: free(pfd); } + void click() + { + snd_pcm_sframes_t delay; + if (0 > snd_pcm_delay(handle, &delay)) { + } + + m_phase = 0; // - click_latency_frames + delay + } + + // generate 1 buffer size + void generate() + { + int i; + + for (i = 0; i < nframes; i++) { + if (m_phase < 0 || m_phase >= m_data.size()) + { + buffer[i] = 0; + } + else + { + buffer[i] = m_data[m_phase]; + } + m_phase++; + } + } + int fd() { return pfd->fd; @@ -77,7 +111,7 @@ public: // write from buffer to ALSA PCM void write() { - snd_pcm_sframes_t written = snd_pcm_writei(handle, m_stream.get_buffer(), nframes); + snd_pcm_sframes_t written = snd_pcm_writei(handle, buffer, nframes); if (written < 0) { if (written == -EPIPE) { std::cout << "Warning: PCM underrun" << std::endl; @@ -93,7 +127,15 @@ public: std::cout << "Warning: written " << std::to_string(written) << " frames instead of "<< std::to_string(nframes) << std::endl; } - m_stream.generate(); + snd_pcm_sframes_t avail; + snd_pcm_sframes_t delay; + if (0 > snd_pcm_avail_delay(handle, &avail, &delay)) { + log_cout << "Error detecting avail and delay" << std::endl; + } else { + log_cout << fmt::format("Delay: {}, avail. buffer; {} frames", delay, avail) << std::endl; + } + + generate(); } bool wait_for_event() @@ -130,6 +172,8 @@ private: int npfd; struct pollfd* pfd; - ClickStream& m_stream; + std::vector<uint16_t> m_data; + int32_t m_phase; + int16_t buffer[nframes]; }; @@ -10,6 +10,8 @@ const snd_pcm_sframes_t nframes = 1024; // ~1/44th sec buffer size const unsigned int f_sample = 44100; const int log_lines = 10; const int default_bpm = 120; +const int pcm_latency_us = 100000; +const int click_latency_frames = 10000; class Config { @@ -1,5 +1,4 @@ #include "Click.h" -#include "ClickStream.h" #include "MIDI.h" #include "PCM.h" #include "Timer.h" @@ -48,8 +47,7 @@ int main(void) std::shared_ptr<Click> click = note_click; MIDI midi; - ClickStream stream; - PCM pcm{stream}; + PCM pcm; UI ui; pcm.write(); @@ -62,10 +60,12 @@ int main(void) // Signal-Slot Connections: midi.signal_note.connect([&](int channel, int note){note_click->receive_note(channel, note);}); - note_click->signal_click.connect([&](){stream.click();}); + note_click->signal_click.connect([&](){pcm.click();}); timer_500ms.elapsed.connect([&](){ui.draw();}); signal_count_loops.connect([&](){ui.count_main_loops();}); + midi.flush(); + while (true) { debug_cout << "Main loop entered." << std::endl; signal_count_loops(); |