finished draw samples, can draw input too

pull/1/head
Clyne 3 years ago
parent e976308b6f
commit a1700f3ca6

1
.gitignore vendored

@ -1,5 +1,6 @@
imgui.ini imgui.ini
stmdspgui stmdspgui
stmdspgui.exe stmdspgui.exe
perf.data*
*.o *.o
.* .*

@ -13,10 +13,7 @@
* TODO list: * TODO list:
* - Test loading the signal generator with a formula. * - Test loading the signal generator with a formula.
* - Improve signal generator audio streaming. * - Improve signal generator audio streaming.
* - Decide how to handle drawing samples at 96kS/s. * - Log samples (should be good..?)
* - May not be possible: USB streaming maxing out at ~80kS/s (1.25MB/s)
* - Draw input samples
* - Log samples
*/ */
#include "stmdsp.hpp" #include "stmdsp.hpp"
@ -76,6 +73,7 @@ static std::ofstream logSamplesFile;
static wav::clip wavOutput; static wav::clip wavOutput;
static std::deque<stmdsp::dacsample_t> drawSamplesQueue; static std::deque<stmdsp::dacsample_t> drawSamplesQueue;
static std::deque<stmdsp::dacsample_t> drawSamplesInputQueue;
static double drawSamplesTimeframe = 1.0; // seconds static double drawSamplesTimeframe = 1.0; // seconds
static unsigned int drawSamplesBufferSize = 1; static unsigned int drawSamplesBufferSize = 1;
@ -97,100 +95,46 @@ static void drawSamplesTask(stmdsp::device *device)
const double bufferSize = m_device->get_buffer_size(); const double bufferSize = m_device->get_buffer_size();
const double sampleRate = sampleRateInts[m_device->get_sample_rate()]; const double sampleRate = sampleRateInts[m_device->get_sample_rate()];
double samplesToPush = sampleRate * 0.0007 * 2; unsigned long bufferTime = bufferSize / sampleRate * 0.975 * 1e6;
std::vector<stmdsp::dacsample_t> lastReadBuffer (bufferSize, 2048);
double lastReadIndexD = 0;
double desiredTime = bufferSize / sampleRate * 1.01;
auto bufferTime = std::chrono::high_resolution_clock::now();
while (m_device && m_device->is_running()) { while (m_device && m_device->is_running()) {
if (samplesToPush < bufferSize || drawSamplesTimeframe < 0.25) { auto next = std::chrono::high_resolution_clock::now() +
if (lastReadIndexD >= bufferSize - 1) std::chrono::microseconds(bufferTime);
lastReadIndexD -= bufferSize - 1;
unsigned int lastReadIndex = std::floor(lastReadIndexD);
unsigned int end = lastReadIndexD + samplesToPush;
{ auto chunk = m_device->continuous_read();
std::scoped_lock lock (mutexDrawSamples); while (chunk.empty() && m_device->is_running()) {
for (; lastReadIndexD < end; lastReadIndexD += 1) { std::this_thread::sleep_for(std::chrono::microseconds(20));
if (lastReadIndex >= lastReadBuffer.size()) { chunk = m_device->continuous_read();
//auto old = samplesToPush;
auto now = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = now - bufferTime;
lastReadBuffer = m_device->continuous_read();
if (drawSamplesInput && popupRequestDraw)
drawSamplesBuf2 = m_device->continuous_read_input();
if (lastReadBuffer.empty()) {
do {
std::this_thread::sleep_for(std::chrono::microseconds(20));
lastReadBuffer = m_device->continuous_read();
} while (lastReadBuffer.empty() && m_device->is_running());
}
bufferTime = now;
if (double c = diff.count(); c > desiredTime + 0.001) {
// Too slow
samplesToPush = (samplesToPush * c / desiredTime) * 0.98;
if (samplesToPush > bufferSize)
samplesToPush = bufferSize;
} else if (c < desiredTime - 0.001) {
// Too fast
samplesToPush = (samplesToPush * c / desiredTime) * 0.98;
}
//if (std::abs(old - samplesToPush) > 4) {
// printf("\r%0.2lf", samplesToPush);
// fflush(stdout);
//}
lastReadIndex = 0;
}
drawSamplesQueue.push_back(lastReadBuffer[lastReadIndex++]);
}
}
std::this_thread::sleep_for(std::chrono::microseconds(700));
} }
// Full blast
else { if (drawSamplesInput && popupRequestDraw) {
lastReadBuffer = m_device->continuous_read(); auto chunk2 = m_device->continuous_read_input();
while (lastReadBuffer.empty() && m_device->is_running()) { while (chunk2.empty() && m_device->is_running()) {
std::this_thread::sleep_for(std::chrono::microseconds(1)); std::this_thread::sleep_for(std::chrono::microseconds(20));
lastReadBuffer = m_device->continuous_read(); chunk2 = m_device->continuous_read_input();
} }
{ {
std::scoped_lock lock (mutexDrawSamples); std::scoped_lock lock (mutexDrawSamples);
for (const auto& s : lastReadBuffer) auto i = chunk2.cbegin();
for (const auto& s : chunk) {
drawSamplesQueue.push_back(s); drawSamplesQueue.push_back(s);
} drawSamplesInputQueue.push_back(*i++);
auto now = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = now - bufferTime;
bufferTime = now;
if (drawSamplesTimeframe >= 0.25) {
double c = diff.count();
if (c < desiredTime) {
samplesToPush = (samplesToPush * c / desiredTime) * 0.98;
} }
}
std::this_thread::sleep_for(std::chrono::microseconds(10)); } else if (!doLogger) {
} else { std::scoped_lock lock (mutexDrawSamples);
std::this_thread::sleep_for(std::chrono::milliseconds(300)); for (const auto& s : chunk)
drawSamplesQueue.push_back(s);
} else {
std::scoped_lock lock (mutexDrawSamples);
for (const auto& s : chunk) {
drawSamplesQueue.push_back(s);
logSamplesFile << s << '\n';
} }
} }
//if (doLogger) { std::this_thread::sleep_until(next);
// for (const auto& s : drawSamplesBuf)
// logSamplesFile << s << '\n';
//}
} }
} }
@ -358,9 +302,9 @@ void deviceRenderDraw()
if (popupRequestDraw) { if (popupRequestDraw) {
static std::vector<stmdsp::dacsample_t> buffer; static std::vector<stmdsp::dacsample_t> buffer;
static decltype(buffer.begin()) bufferCursor; static decltype(buffer.begin()) bufferCursor;
static std::vector<stmdsp::dacsample_t> bufferInput;
static decltype(bufferInput.begin()) bufferInputCursor;
static unsigned int yMinMax = 4095; static unsigned int yMinMax = 4095;
//static long unsigned int drawChunkSize = 0;
//static std::chrono::time_point<std::chrono::high_resolution_clock> timee;
ImGui::Begin("draw", &popupRequestDraw); ImGui::Begin("draw", &popupRequestDraw);
ImGui::Text("Draw input "); ImGui::Text("Draw input ");
@ -393,28 +337,32 @@ void deviceRenderDraw()
yMinMax = std::min(4095u, (yMinMax << 1) | 1); yMinMax = std::min(4095u, (yMinMax << 1) | 1);
} }
static unsigned long csize = 0;
if (buffer.size() != drawSamplesBufferSize) { if (buffer.size() != drawSamplesBufferSize) {
buffer.resize(drawSamplesBufferSize); buffer.resize(drawSamplesBufferSize);
bufferInput.resize(drawSamplesBufferSize);
bufferCursor = buffer.begin(); bufferCursor = buffer.begin();
bufferInputCursor = bufferInput.begin();
csize = drawSamplesBufferSize / (60. * drawSamplesTimeframe) * 1.025;
} }
{ {
std::scoped_lock lock (mutexDrawSamples); std::scoped_lock lock (mutexDrawSamples);
auto qsize = drawSamplesQueue.size(); auto count = std::min(drawSamplesQueue.size(), csize);
auto count = qsize;//std::min(qsize, drawChunkSize);
//if (count > 0)
// printf("draw: %9llu/%9lu\n", qsize, count);
for (auto i = count; i; --i) { for (auto i = count; i; --i) {
*bufferCursor = drawSamplesQueue.front(); *bufferCursor = drawSamplesQueue.front();
drawSamplesQueue.pop_front(); drawSamplesQueue.pop_front();
if (++bufferCursor == buffer.end()) { if (++bufferCursor == buffer.end())
bufferCursor = buffer.begin(); bufferCursor = buffer.begin();
}
//auto now = std::chrono::high_resolution_clock::now(); if (drawSamplesInput) {
//std::chrono::duration<double> diff = now - timee; auto count = std::min(drawSamplesInputQueue.size(), csize);
//timee = now; for (auto i = count; i; --i) {
//printf("\rtime: %.9lf", diff); *bufferInputCursor = drawSamplesInputQueue.front();
//fflush(stdout); drawSamplesInputQueue.pop_front();
if (++bufferInputCursor == bufferInput.end())
bufferInputCursor = bufferInput.begin();
} }
} }
} }
@ -428,7 +376,7 @@ void deviceRenderDraw()
const float di = static_cast<float>(buffer.size()) / size.x; const float di = static_cast<float>(buffer.size()) / size.x;
const float dx = std::ceil(size.x / static_cast<float>(buffer.size())); const float dx = std::ceil(size.x / static_cast<float>(buffer.size()));
ImVec2 pp = p0; ImVec2 pp = p0;
float i = 0; float i = 0;
while (pp.x < p0.x + size.x) { while (pp.x < p0.x + size.x) {
unsigned int idx = i; unsigned int idx = i;
@ -440,27 +388,20 @@ void deviceRenderDraw()
pp = next; pp = next;
} }
//const unsigned int didx = std::ceil(1.f / (size.x / static_cast<float>(buffer.size()))); if (drawSamplesInput) {
//const auto dx = size.x / buffer.size(); ImVec2 pp = p0;
//ImVec2 pp = p0; float i = 0;
//for (auto i = 0u; i < buffer.size(); i += didx) { while (pp.x < p0.x + size.x) {
// float n = std::clamp((buffer[i] - 2048.) / yMinMax, -0.5, 0.5); unsigned int idx = i;
float n = std::clamp((bufferInput[idx] - 2048.) / yMinMax, -0.5, 0.5);
// ImVec2 next (pp.x + 1, p0.y + size.y * (0.5 - n)); i += di;
// drawList->AddLine(pp, next, ImGui::GetColorU32(IM_COL32(255, 0, 0, 255)));
// pp = next; ImVec2 next (pp.x + dx, p0.y + size.y * (0.5 - n));
//} drawList->AddLine(pp, next, ImGui::GetColorU32(IM_COL32(0, 0, 255, 255)));
pp = next;
//if (drawSamplesInput) { }
// pp = p0; }
// for (auto i = 0u; i < drawSamplesBuf2.size(); i += didx) {
// ImVec2 next (pp.x + 1,
// p0.y + size.y -
// (static_cast<float>(buffer[i]) / yMinMax) * size.y);
// drawList->AddLine(pp, next, ImGui::GetColorU32(IM_COL32(0, 0, 255, 255)));
// pp = next;
// }
//}
ImGui::End(); ImGui::End();
} }
} }
@ -550,7 +491,7 @@ void deviceRenderToolbar()
ImGui::SameLine(); ImGui::SameLine();
ImGui::SetNextItemWidth(100); ImGui::SetNextItemWidth(100);
if (ImGui::BeginCombo("", sampleRatePreview)) { if (ImGui::BeginCombo("", sampleRatePreview)) {
for (int i = 0; i < sampleRateList.size() - 1; ++i) { for (int i = 0; i < sampleRateList.size(); ++i) {
if (ImGui::Selectable(sampleRateList[i])) { if (ImGui::Selectable(sampleRateList[i])) {
sampleRatePreview = sampleRateList[i]; sampleRatePreview = sampleRateList[i];
if (m_device != nullptr && !m_device->is_running()) { if (m_device != nullptr && !m_device->is_running()) {

@ -26,7 +26,7 @@ static decltype(SDL_GL_CreateContext(nullptr)) gl_context;
bool guiInitialize() bool guiInitialize()
{ {
if (SDL_Init(SDL_INIT_VIDEO) != 0) { if (SDL_Init(/*SDL_INIT_VIDEO*/0) != 0) {
printf("Error: %s\n", SDL_GetError()); printf("Error: %s\n", SDL_GetError());
return false; return false;
} }

@ -17,7 +17,10 @@
#include "logview.h" #include "logview.h"
#include "stmdsp.hpp" #include "stmdsp.hpp"
#include <chrono>
#include <cmath>
#include <string> #include <string>
#include <thread>
extern ImFont *fontSans; extern ImFont *fontSans;
extern ImFont *fontMono; extern ImFont *fontMono;
@ -61,6 +64,9 @@ int main(int, char **)
codeEditorInit(); codeEditorInit();
while (!done) { while (!done) {
auto endTime = std::chrono::steady_clock::now() +
std::chrono::milliseconds(static_cast<unsigned int>(std::floor(1000. / 60.)));
guiHandleEvents(done); guiHandleEvents(done);
// Start the new window frame and render the menu bar. // Start the new window frame and render the menu bar.
@ -107,6 +113,8 @@ int main(int, char **)
guiRender([] { guiRender([] {
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
}); });
std::this_thread::sleep_until(endTime);
} }
guiShutdown(); guiShutdown();

Loading…
Cancel
Save