aboutsummaryrefslogtreecommitdiffstats
path: root/source/device.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/device.cpp')
-rw-r--r--source/device.cpp151
1 files changed, 74 insertions, 77 deletions
diff --git a/source/device.cpp b/source/device.cpp
index df3f361..abcc88a 100644
--- a/source/device.cpp
+++ b/source/device.cpp
@@ -11,10 +11,12 @@
#include "stmdsp.hpp"
+#include "circular.hpp"
#include "imgui.h"
#include "wav.hpp"
#include <array>
+#include <cctype>
#include <charconv>
#include <cmath>
#include <deque>
@@ -30,7 +32,7 @@
extern std::string tempFileName;
extern void log(const std::string& str);
-extern std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string_view);
+extern std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string&);
std::shared_ptr<stmdsp::device> m_device;
@@ -62,14 +64,16 @@ static std::vector<stmdsp::dacsample_t> tryReceiveChunk(
std::shared_ptr<stmdsp::device> device,
auto readFunc)
{
- int tries = -1;
- do {
+ for (int tries = 0; tries < 100; ++tries) {
+ if (!device->is_running())
+ break;
+
const auto chunk = readFunc(device.get());
if (!chunk.empty())
return chunk;
else
std::this_thread::sleep_for(std::chrono::microseconds(20));
- } while (++tries < 100 && device->is_running());
+ }
return {};
}
@@ -94,15 +98,13 @@ static void drawSamplesTask(std::shared_ptr<stmdsp::device> device)
const auto bufferTime = getBufferPeriod(device);
- std::unique_lock<std::timed_mutex> lockDraw (mutexDrawSamples, std::defer_lock);
- std::unique_lock<std::timed_mutex> lockDevice (mutexDeviceLoad, std::defer_lock);
-
- auto addToQueue = [&lockDraw](auto& queue, const auto& chunk) {
- lockDraw.lock();
+ const auto addToQueue = [](auto& queue, const auto& chunk) {
+ std::scoped_lock lock (mutexDrawSamples);
std::copy(chunk.cbegin(), chunk.cend(), std::back_inserter(queue));
- lockDraw.unlock();
};
+ std::unique_lock<std::timed_mutex> lockDevice (mutexDeviceLoad, std::defer_lock);
+
while (device && device->is_running()) {
const auto next = std::chrono::high_resolution_clock::now() + bufferTime;
@@ -112,7 +114,7 @@ static void drawSamplesTask(std::shared_ptr<stmdsp::device> device)
lockDevice.unlock();
addToQueue(drawSamplesQueue, chunk);
- if (logSamplesFile.good()) {
+ if (logSamplesFile.is_open()) {
for (const auto& s : chunk)
logSamplesFile << s << '\n';
}
@@ -145,29 +147,29 @@ static void feedSigGenTask(std::shared_ptr<stmdsp::device> device)
std::vector<stmdsp::dacsample_t> wavBuf (device->get_buffer_size() * 2, 2048);
- std::unique_lock<std::timed_mutex> lockDevice (mutexDeviceLoad, std::defer_lock);
+ {
+ std::scoped_lock lock (mutexDeviceLoad);
+ device->siggen_upload(wavBuf.data(), wavBuf.size());
+ device->siggen_start();
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
- lockDevice.lock();
- device->siggen_upload(wavBuf.data(), wavBuf.size());
wavBuf.resize(wavBuf.size() / 2);
- device->siggen_start();
- std::this_thread::sleep_for(std::chrono::milliseconds(1));
- lockDevice.unlock();
-
std::vector<int16_t> wavIntBuf (wavBuf.size());
while (device->is_siggening()) {
const auto next = std::chrono::high_resolution_clock::now() + delay;
wavOutput.next(wavIntBuf.data(), wavIntBuf.size());
- auto src = wavIntBuf.cbegin();
- std::generate(wavBuf.begin(), wavBuf.end(),
- [&src] { return static_cast<stmdsp::dacsample_t>(*src++ / 16 + 2048); });
+ std::transform(wavIntBuf.cbegin(), wavIntBuf.cend(),
+ wavBuf.begin(),
+ [](auto i) { return static_cast<stmdsp::dacsample_t>(i / 16 + 2048); });
- lockDevice.lock();
- while (!device->siggen_upload(wavBuf.data(), wavBuf.size()))
- std::this_thread::sleep_for(uploadDelay);
- lockDevice.unlock();
+ {
+ std::scoped_lock lock (mutexDeviceLoad);
+ while (!device->siggen_upload(wavBuf.data(), wavBuf.size()))
+ std::this_thread::sleep_for(uploadDelay);
+ }
std::this_thread::sleep_until(next);
}
@@ -179,10 +181,9 @@ static void statusTask(std::shared_ptr<stmdsp::device> device)
return;
while (device->connected()) {
- std::unique_lock<std::timed_mutex> lockDevice (mutexDeviceLoad, std::defer_lock);
- lockDevice.lock();
+ mutexDeviceLoad.lock();
const auto [status, error] = device->get_status();
- lockDevice.unlock();
+ mutexDeviceLoad.unlock();
if (error != stmdsp::Error::None) {
switch (error) {
@@ -214,7 +215,7 @@ void deviceLoadAudioFile(const std::string& file)
void deviceLoadLogFile(const std::string& file)
{
logSamplesFile = std::ofstream(file);
- if (logSamplesFile.good())
+ if (logSamplesFile.is_open())
log("Log file ready.");
else
log("Error: Could not open log file.");
@@ -261,7 +262,7 @@ bool deviceConnect()
if (!m_device) {
stmdsp::scanner scanner;
- if (auto devices = scanner.scan(); !devices.empty()) {
+ if (const auto devices = scanner.scan(); !devices.empty()) {
try {
m_device.reset(new stmdsp::device(devices.front()));
} catch (...) {
@@ -307,7 +308,7 @@ void deviceStart(bool measureCodeTime, bool logResults, bool drawSamples)
std::this_thread::sleep_for(std::chrono::microseconds(150));
m_device->continuous_stop();
}
- if (logSamplesFile.good()) {
+ if (logSamplesFile.is_open()) {
logSamplesFile.close();
log("Log file saved and closed.");
}
@@ -329,12 +330,9 @@ void deviceAlgorithmUpload()
{
if (!m_device) {
log("No device connected.");
- return;
} else if (m_device->is_running()) {
- return;
- }
-
- if (std::ifstream algo (tempFileName + ".o"); algo.good()) {
+ log("Cannot upload algorithm while running.");
+ } else if (std::ifstream algo (tempFileName + ".o"); algo.is_open()) {
std::ostringstream sstr;
sstr << algo.rdbuf();
auto str = sstr.str();
@@ -350,7 +348,9 @@ void deviceAlgorithmUnload()
{
if (!m_device) {
log("No device connected.");
- } else if (!m_device->is_running()) {
+ } else if (m_device->is_running()) {
+ log("Cannot unload algorithm while running.");
+ } else {
m_device->unload_filter();
log("Algorithm unloaded.");
}
@@ -361,85 +361,82 @@ void deviceGenLoadList(const std::string_view list)
std::vector<stmdsp::dacsample_t> samples;
auto it = list.cbegin();
- while (it != list.cend() && samples.size() < stmdsp::SAMPLES_MAX * 2) {
- const auto end = list.find_first_not_of("0123456789",
- std::distance(list.cbegin(), it));
- const auto itend = end != std::string_view::npos ? list.cbegin() + end
- : list.cend();
+ while (it != list.cend()) {
+ const auto itend = std::find_if(it, list.cend(),
+ [](char c) { return !isdigit(c); });
+
unsigned long n;
- const auto [ptr, ec] = std::from_chars(it, itend, n);
- if (ec != std::errc())
+ const auto ec = std::from_chars(it, itend, n).ec;
+ if (ec != std::errc()) {
+ log("Error: Bad data in sample list.");
+ break;
+ } else if (n > 4095) {
+ log("Error: Sample data value larger than max of 4095.");
break;
+ } else {
+ samples.push_back(n & 4095);
+ if (samples.size() >= stmdsp::SAMPLES_MAX * 2) {
+ log("Error: Too many samples for signal generator.");
+ break;
+ }
+ }
- samples.push_back(n & 4095);
it = itend;
}
- if (samples.size() <= stmdsp::SAMPLES_MAX * 2) {
+ if (it == list.cend()) {
// DAC buffer must be of even size
if (samples.size() % 2 != 0)
samples.push_back(samples.back());
- if (m_device)
- m_device->siggen_upload(samples.data(), samples.size());
+ m_device->siggen_upload(samples.data(), samples.size());
log("Generator ready.");
- } else {
- log("Error: Too many samples for signal generator.");
}
}
-void deviceGenLoadFormula(std::string_view formula)
+void deviceGenLoadFormula(const std::string& formula)
{
auto samples = deviceGenLoadFormulaEval(formula);
if (!samples.empty()) {
- if (m_device)
- m_device->siggen_upload(samples.data(), samples.size());
-
+ m_device->siggen_upload(samples.data(), samples.size());
log("Generator ready.");
} else {
log("Error: Bad formula.");
}
}
-void pullFromQueue(
+std::size_t pullFromQueue(
std::deque<stmdsp::dacsample_t>& queue,
- std::vector<stmdsp::dacsample_t>& buffer,
- decltype(buffer.begin())& bufferCursor,
+ CircularBuffer<std::vector, stmdsp::dacsample_t>& circ,
double timeframe)
{
- if (buffer.size() != drawSamplesBufferSize) {
- buffer.resize(drawSamplesBufferSize);
- bufferCursor = buffer.begin();
- }
+ if (circ.size() != drawSamplesBufferSize)
+ return drawSamplesBufferSize;
std::scoped_lock lock (mutexDrawSamples);
- auto count = drawSamplesBufferSize / (60. * timeframe) * 1.025;
- count = std::min(drawSamplesInputQueue.size(),
- static_cast<std::size_t>(count));
- for (auto i = count; i; --i) {
- *bufferCursor = queue.front();
+ const auto desiredCount = drawSamplesBufferSize / (60. * timeframe) * 1.025;
+ auto count = std::min(queue.size(), static_cast<std::size_t>(desiredCount));
+ while (count--) {
+ circ.put(queue.front());
queue.pop_front();
-
- if (++bufferCursor == buffer.end())
- bufferCursor = buffer.begin();
}
+
+ return 0;
}
-void pullFromDrawQueue(
- std::vector<stmdsp::dacsample_t>& buffer,
- decltype(buffer.begin())& bufferCursor,
+std::size_t pullFromDrawQueue(
+ CircularBuffer<std::vector, stmdsp::dacsample_t>& circ,
double timeframe)
{
- pullFromQueue(drawSamplesQueue, buffer, bufferCursor, timeframe);
+ return pullFromQueue(drawSamplesQueue, circ, timeframe);
}
-void pullFromInputDrawQueue(
- std::vector<stmdsp::dacsample_t>& buffer,
- decltype(buffer.begin())& bufferCursor,
+std::size_t pullFromInputDrawQueue(
+ CircularBuffer<std::vector, stmdsp::dacsample_t>& circ,
double timeframe)
{
- pullFromQueue(drawSamplesInputQueue, buffer, bufferCursor, timeframe);
+ return pullFromQueue(drawSamplesInputQueue, circ, timeframe);
}