From 22cdfccb11679d6ae241653c9cb92c32f4fc1fde Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Fri, 3 Jan 2025 21:02:11 +0100 Subject: Integrate ClickStream into PCM --- PCM.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 8 deletions(-) (limited to 'PCM.h') diff --git a/PCM.h b/PCM.h index bfa1e24..3e9b41d 100644 --- a/PCM.h +++ b/PCM.h @@ -1,22 +1,29 @@ #pragma once -#include "ClickStream.h" - #include "config.h" +#include "log.h" + +#include #include #include #include #include +#include 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 m_data; + int32_t m_phase; + int16_t buffer[nframes]; }; -- cgit v1.2.3