sndlock/sndlock.cpp

151 lines
4.1 KiB
C++
Raw Normal View History

2024-12-26 11:48:03 +08:00
#include <iostream>
2024-12-26 16:18:43 +08:00
#include <thread>
#include <cstdint>
2024-12-26 11:48:03 +08:00
2024-12-26 12:33:11 +08:00
#include <GLFW/glfw3.h>
2024-12-26 16:18:43 +08:00
#include <sndio.h>
#include <math.h>
2024-12-26 12:33:11 +08:00
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
2024-12-26 16:18:43 +08:00
static std::atomic<bool> shutdown_threads;
static std::atomic<float> frequency = 440.0f;
#define SND_SIG 1
#define SND_BITS 16
#define SND_PCHAN 2
#define SND_RATE 44100
#define SND_BUFLEN 4096
static void dsp_thread()
{
struct sio_hdl *hdl;
struct sio_par par;
hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
if(hdl == nullptr) {
std::cerr << "failed to open sound device" << std::endl;
return;
}
sio_initpar(&par);
par.sig = SND_SIG;
par.bits = SND_BITS;
par.pchan = SND_PCHAN;
par.rate = SND_RATE;
par.le = SIO_LE_NATIVE;
if(!sio_setpar(hdl, &par)) {
std::cerr << "failed to set 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;
}
uint32_t phase = 0;
int16_t buf[SND_BUFLEN*SND_PCHAN];
while(!shutdown_threads) {
uint32_t ftw = frequency*(float)UINT32_MAX/SND_RATE;
for(int i=0;i<SND_BUFLEN;i++) {
buf[2*i] = buf[2*i+1] = (INT16_MAX-1)*sin(phase*2.0f*(float)M_PI/(float)UINT32_MAX);
phase += ftw;
}
if(!sio_write(hdl, buf, SND_BUFLEN*(SND_BITS/8)*SND_PCHAN)) {
std::cerr << "failed to write to sound device" << std::endl;
sio_stop(hdl);
sio_close(hdl);
return;
}
}
sio_stop(hdl);
sio_close(hdl);
}
2024-12-26 12:33:11 +08:00
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, 768, "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);
2024-12-26 16:18:43 +08:00
static std::thread dsp_thread_h = std::thread(dsp_thread);
static auto JoinDSP = []() {
dsp_thread_h.join();
};
std::atexit(JoinDSP);
shutdown_threads = false;
static auto SetShutdown = []() {
shutdown_threads = true;
};
std::atexit(SetShutdown);
2024-12-26 12:33:11 +08:00
bool exit = false;
while(!exit && !glfwWindowShouldClose(window)) {
glfwPollEvents();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f));
ImGui::SetNextWindowSize(io.DisplaySize);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::Begin("sndlock", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize);
2024-12-26 16:18:43 +08:00
float frequency_l = frequency;
ImGui::SliderFloat("Frequency", &frequency_l, 50.0f, 8000.0f);
frequency = frequency_l;
2024-12-26 12:33:11 +08:00
if(ImGui::Button("Exit"))
exit = true;
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);
}
2024-12-26 11:48:03 +08:00
return 0;
}