make more generic, independent modulation channels

This commit is contained in:
Sébastien Bourdeauducq 2024-12-27 16:31:44 +08:00
parent ced16e1338
commit 297616c4ff

View File

@ -11,16 +11,14 @@
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h" #include "imgui_impl_opengl3.h"
static std::atomic<bool> shutdown_threads;
static std::atomic<float> frequency = 440.0f;
#define SND_SIG 1
#define SND_BITS 16 #define SND_BITS 16
#define SND_PCHAN 2 #define SND_PCHAN 2
#define SND_RCHAN 1
#define SND_RATE 44100 #define SND_RATE 44100
#define SND_BUFLEN 4096 #define SND_BUFLEN 4096
static std::atomic<bool> shutdown_threads;
static std::atomic<float> frequency[SND_PCHAN];
static void dsp_thread() static void dsp_thread()
{ {
struct sio_hdl *hdl; struct sio_hdl *hdl;
@ -32,10 +30,10 @@ static void dsp_thread()
return; return;
} }
sio_initpar(&par); sio_initpar(&par);
par.sig = SND_SIG; par.sig = 1;
par.bits = SND_BITS; par.bits = SND_BITS;
par.pchan = SND_PCHAN; par.pchan = SND_PCHAN;
par.pchan = SND_RCHAN; par.rchan = 1;
par.rate = SND_RATE; par.rate = SND_RATE;
par.le = SIO_LE_NATIVE; par.le = SIO_LE_NATIVE;
par.xrun = SIO_ERROR; par.xrun = SIO_ERROR;
@ -56,7 +54,7 @@ static void dsp_thread()
return; return;
} }
uint32_t phase = 0; uint32_t phase_out[SND_PCHAN] = { 0 };
int16_t buf_out[SND_BUFLEN*SND_PCHAN]; int16_t buf_out[SND_BUFLEN*SND_PCHAN];
size_t buf_out_idx = SND_BUFLEN*SND_PCHAN; size_t buf_out_idx = SND_BUFLEN*SND_PCHAN;
@ -68,13 +66,18 @@ static void dsp_thread()
poll(pfd, nfds, INFTIM); poll(pfd, nfds, INFTIM);
int revents = sio_revents(hdl, pfd); int revents = sio_revents(hdl, pfd);
uint32_t ftw[SND_PCHAN];
for(int i=0;i<SND_PCHAN;i++)
ftw[i] = frequency[i]*(float)UINT32_MAX/SND_RATE;
if(revents & POLLOUT) { if(revents & POLLOUT) {
float scale = powf(2.0f, SND_BITS-1) - 1.0f;
if(buf_out_idx == SND_BUFLEN*SND_PCHAN) { if(buf_out_idx == SND_BUFLEN*SND_PCHAN) {
uint32_t ftw = frequency*(float)UINT32_MAX/SND_RATE; for(int i=0;i<SND_PCHAN;i++)
for(int i=0;i<SND_BUFLEN;i++) { for(int j=0;j<SND_BUFLEN;j++) {
buf_out[2*i] = buf_out[2*i+1] = (INT16_MAX-1)*sinf(phase*2.0f*(float)M_PI/(float)UINT32_MAX); buf_out[2*j+i] = scale*sinf(phase_out[i]*2.0f*(float)M_PI/(float)UINT32_MAX);
phase += ftw; phase_out[i] += ftw[i]; // wraps on overflow
} }
buf_out_idx = 0; buf_out_idx = 0;
} }
size_t written = sio_write(hdl, &buf_out[buf_out_idx], sizeof(buf_out) - buf_out_idx*sizeof(buf_out[0])); size_t written = sio_write(hdl, &buf_out[buf_out_idx], sizeof(buf_out) - buf_out_idx*sizeof(buf_out[0]));
@ -82,7 +85,7 @@ static void dsp_thread()
} }
if(revents & POLLIN) { if(revents & POLLIN) {
int16_t buf_in[SND_BUFLEN*SND_RCHAN]; int16_t buf_in[SND_BUFLEN];
sio_read(hdl, buf_in, sizeof(buf_in)); sio_read(hdl, buf_in, sizeof(buf_in));
for(int i=0;i<10;i++) for(int i=0;i<10;i++)
std::cout << buf_in[i] << " "; std::cout << buf_in[i] << " ";
@ -135,6 +138,9 @@ int main(int argc, char* argv[])
ImGui_ImplOpenGL3_Init("#version 130"); ImGui_ImplOpenGL3_Init("#version 130");
std::atexit(ImGui_ImplOpenGL3_Shutdown); std::atexit(ImGui_ImplOpenGL3_Shutdown);
for(int i=0;i<SND_PCHAN;i++)
frequency[i] = 441.0 + 202.0*i;
static std::thread dsp_thread_h = std::thread(dsp_thread); static std::thread dsp_thread_h = std::thread(dsp_thread);
static auto JoinDSP = []() { static auto JoinDSP = []() {
dsp_thread_h.join(); dsp_thread_h.join();
@ -162,9 +168,15 @@ int main(int argc, char* argv[])
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::Begin("sndlock", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize); ImGui::Begin("sndlock", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize);
float frequency_l = frequency; if(ImGui::CollapsingHeader("Modulation", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::SliderFloat("Frequency", &frequency_l, 50.0f, 8000.0f); for(int i=0;i<SND_PCHAN;i++) {
frequency = frequency_l; char str[64];
sprintf(str, "Frequency ch%d", i);
float frequency_l = frequency[i];
ImGui::SliderFloat(str, &frequency_l, 50.0f, 8000.0f);
frequency[i] = frequency_l;
}
}
if(ImGui::Button("Exit")) if(ImGui::Button("Exit"))
exit = true; exit = true;