From 16dfc785d334bdc16da91b6b36d405ba979b9c65 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 5 Mar 2022 00:36:50 -0500 Subject: [PATCH] PC speaker: improvements --- src/engine/platform/pcspkr.cpp | 75 ++++++++++++++++++++++++++++++++-- src/engine/platform/pcspkr.h | 9 +++- src/engine/song.h | 6 +++ src/gui/gui.cpp | 22 ++++++++++ 4 files changed, 107 insertions(+), 5 deletions(-) diff --git a/src/engine/platform/pcspkr.cpp b/src/engine/platform/pcspkr.cpp index 76d6612ab..51353fedf 100644 --- a/src/engine/platform/pcspkr.cpp +++ b/src/engine/platform/pcspkr.cpp @@ -37,7 +37,10 @@ const char* DivPlatformPCSpeaker::getEffectName(unsigned char effect) { return NULL; } -void DivPlatformPCSpeaker::acquire(short* bufL, short* bufR, size_t start, size_t len) { +const float cut=0.05; +const float reso=0.06; + +void DivPlatformPCSpeaker::acquire_unfilt(short* bufL, short* bufR, size_t start, size_t len) { for (size_t i=start; i>1):((freq+1)>>1); + pos+=freq; } - flip=!flip; } - bufL[i]=(flip && !isMuted[0])?32767:0; + bufL[i]=(pos>(freq>>1) && !isMuted[0])?32767:0; } else { bufL[i]=0; } } } +void DivPlatformPCSpeaker::acquire_cone(short* bufL, short* bufR, size_t start, size_t len) { + for (size_t i=start; i((freq+16)>>1) && !isMuted[0])?1:0; + low+=0.04*band; + band+=0.04*(next-low-band); + float out=(low+band)*0.75; + if (out>1.0) out=1.0; + if (out<-1.0) out=-1.0; + bufL[i]=out*32767; + } else { + bufL[i]=0; + } + } +} + +void DivPlatformPCSpeaker::acquire_piezo(short* bufL, short* bufR, size_t start, size_t len) { + for (size_t i=start; i((freq+64)>>1) && !isMuted[0])?1:0; + low+=cut*band; + band+=cut*(next-low-(reso*band)); + float out=band*0.15-(next-low)*0.06; + if (out>1.0) out=1.0; + if (out<-1.0) out=-1.0; + bufL[i]=out*32767; + } else { + bufL[i]=0; + } + } +} + +void DivPlatformPCSpeaker::acquire(short* bufL, short* bufR, size_t start, size_t len) { + switch (speakerType) { + case 0: + acquire_unfilt(bufL,bufR,start,len); + break; + case 1: + acquire_cone(bufL,bufR,start,len); + break; + case 2: + acquire_piezo(bufL,bufR,start,len); + break; + } +} + void DivPlatformPCSpeaker::tick() { for (int i=0; i<1; i++) { chan[i].std.next(); @@ -221,6 +285,8 @@ void DivPlatformPCSpeaker::reset() { freq=0; pos=0; flip=false; + low=0; + band=0; memset(regPool,0,2); } @@ -232,6 +298,7 @@ bool DivPlatformPCSpeaker::keyOffAffectsArp(int ch) { void DivPlatformPCSpeaker::setFlags(unsigned int flags) { chipClock=COLOR_NTSC/3.0; rate=chipClock/PCSPKR_DIVIDER; + speakerType=flags&3; } void DivPlatformPCSpeaker::notifyInsDeletion(void* ins) { diff --git a/src/engine/platform/pcspkr.h b/src/engine/platform/pcspkr.h index 90e19b8ca..caf6b7f3a 100644 --- a/src/engine/platform/pcspkr.h +++ b/src/engine/platform/pcspkr.h @@ -53,12 +53,19 @@ class DivPlatformPCSpeaker: public DivDispatch { Channel chan[1]; bool isMuted[1]; bool on, flip; - int pos; + int pos, speakerType; + float low, band; + float low2, high2, band2; + float low3, band3; unsigned short freq; unsigned char regPool[2]; friend void putDispatchChan(void*,int,int); + void acquire_unfilt(short* bufL, short* bufR, size_t start, size_t len); + void acquire_cone(short* bufL, short* bufR, size_t start, size_t len); + void acquire_piezo(short* bufL, short* bufR, size_t start, size_t len); + public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); diff --git a/src/engine/song.h b/src/engine/song.h index fff1065fe..d1e255d95 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -215,6 +215,12 @@ struct DivSong { // - 1: Amiga 1200 // - bit 8-14: stereo separation // - 0 is 0% while 127 is 100% + // - PC Speaker: + // - bit 0-1: speaker type + // - 0: unfiltered + // - 1: cone + // - 2: piezo + // - 3: real (TODO) // - QSound: // - bit 12-20: echo feedback // - Valid values are 0-255 diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 7ee75fc4d..191f0c21f 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4843,6 +4843,28 @@ bool FurnaceGUI::loop() { } break; } + case DIV_SYSTEM_PCSPKR: { + ImGui::Text("Speaker type:"); + if (ImGui::RadioButton("Unfiltered",(flags&3)==0)) { + e->setSysFlags(i,(flags&(~3))|0,restart); + updateWindowTitle(); + } + if (ImGui::RadioButton("Cone",(flags&3)==1)) { + e->setSysFlags(i,(flags&(~3))|1,restart); + updateWindowTitle(); + } + if (ImGui::RadioButton("Piezo",(flags&3)==2)) { + e->setSysFlags(i,(flags&(~3))|2,restart); + updateWindowTitle(); + } + /* + if (ImGui::RadioButton("Use system beeper",(flags&3)==3)) { + e->setSysFlags(i,(flags&(~3))|3,restart); + updateWindowTitle(); + } + */ + break; + } case DIV_SYSTEM_QSOUND: { ImGui::Text("Echo delay:"); int echoBufSize=2725 - (flags & 4095);