#include #include #include #include #include #include #include #include #include #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include "dsp_lib.h" #include "fifo.h" #define SND_BITS 24 #define SND_PCHAN 2 #define SND_RCHAN 2 #define SND_RATE 44100 #define SND_BUFLEN 4096 static std::atomic shutdown_threads; static std::atomic frequency[SND_PCHAN]; static std::atomic amplitude[SND_PCHAN]; static std::atomic lpf_bandwidth[SND_PCHAN]; static std::mutex li_hist_mutex; static std::atomic li_hist_pause[SND_PCHAN]; static float li_hist_mag[SND_PCHAN][512]; static float li_hist_phase[SND_PCHAN][512]; static void dsp_thread() { struct sio_hdl *hdl; struct sio_par par; hdl = sio_open(SIO_DEVANY, SIO_PLAY|SIO_REC, 1); if(hdl == nullptr) { std::cerr << "failed to open sound device" << std::endl; return; } sio_initpar(&par); par.sig = 1; par.bits = SND_BITS; par.pchan = SND_PCHAN; par.rchan = SND_RCHAN; par.rate = SND_RATE; par.le = SIO_LE_NATIVE; par.xrun = SIO_ERROR; if(!sio_setpar(hdl, &par)) { std::cerr << "failed to set sound device parameters" << std::endl; sio_close(hdl); return; } if(!sio_getpar(hdl, &par)) { std::cerr << "failed to get back sound device parameters" << std::endl; sio_close(hdl); return; } if(!sio_start(hdl)) { std::cerr << "failed to start sound device" << std::endl; sio_close(hdl); return; } DDS dds[SND_PCHAN]; int32_t buf_out[SND_BUFLEN*SND_PCHAN]; size_t buf_out_offset = sizeof(buf_out); int32_t buf_in[SND_BUFLEN*SND_RCHAN]; size_t buf_in_offset = sizeof(buf_in); FIFO ftw_fifo[SND_PCHAN]; Lockin<4> lockin[SND_PCHAN]; for(int i=0;i= sizeof(buf_in)) { for(int i=0;i ftw = ftw_fifo[i].pull(); if(ftw.has_value()) lockin[i].ftw = ftw.value(); else std::cerr << "FTW FIFO underflow" << std::endl; } buf_in_offset -= sizeof(buf_in); } for(int i=0;i lockin_out = lockin[i].update(sample); if(!li_hist_pause[i]) { li_count[i]++; if(li_count[i] == 200) { li_count[i] = 0; std::lock_guard guard(li_hist_mutex); std::memmove(&li_hist_mag[i][0], &li_hist_mag[i][1], 511*sizeof(float)); li_hist_mag[i][511] = std::abs(lockin_out); std::memmove(&li_hist_phase[i][0], &li_hist_phase[i][1], 511*sizeof(float)); li_hist_phase[i][511] = std::arg(lockin_out); } } } } if(sio_eof(hdl)) { std::cerr << "sound I/O error" << std::endl; sio_close(hdl); return; } } sio_stop(hdl); sio_close(hdl); } int main(int argc, char* argv[]) { if(!glfwInit()) { std::cerr << "failed to initialize GLFW" << std::endl; return 1; } std::atexit(glfwTerminate); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); static GLFWwindow* window = glfwCreateWindow(1024, 1200, "sndlock", nullptr, nullptr); if(window == nullptr) { std::cerr << "failed to create GLFW window" << std::endl; return 1; } static auto DestroyWindow = []() { glfwDestroyWindow(window); }; std::atexit(DestroyWindow); glfwMakeContextCurrent(window); glfwSwapInterval(1); IMGUI_CHECKVERSION(); ImGui::CreateContext(); static auto ImGuiDestroyContext = []() { ImGui::DestroyContext(); }; std::atexit(ImGuiDestroyContext); ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; ImGui::StyleColorsDark(); ImGui_ImplGlfw_InitForOpenGL(window, true); std::atexit(ImGui_ImplGlfw_Shutdown); ImGui_ImplOpenGL3_Init("#version 130"); std::atexit(ImGui_ImplOpenGL3_Shutdown); for(int i=0;i guard(li_hist_mutex); sprintf(str, "magnitude##%d", i); ImGui::PlotLines(str, li_hist_mag[i], 512, 0, 0, -0.0f, 0.1f*plot_scale[i], ImVec2(0.0f, 200.0f)); sprintf(str, "phase##%d", i); ImGui::PlotLines(str, li_hist_phase[i], 512, 0, 0, -M_PI, M_PI, ImVec2(0.0f, 200.0f)); } bool pause_l = li_hist_pause[i]; sprintf(str, "pause##%d", i); ImGui::Checkbox(str, &pause_l); li_hist_pause[i] = pause_l; ImGui::SameLine(); { std::lock_guard guard(li_hist_mutex); ImGui::Text("values: %8.5f %8.5f rad", li_hist_mag[i][511], li_hist_phase[i][511]); } } } ImGui::End(); ImGui::PopStyleVar(1); ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glfwSwapBuffers(window); } return 0; }