Skip to content

Commit ad78052

Browse files
Remove latency detector for audio system
Because it's flawed like rappergf said. I wouldn't rely on it anyway. I'd have a very professional way of getting user latency from you just hitting the keys on beat with the song's beat upon the start, like how you'd do it with the options menu but more flexible with the upcoming chart editor. But, that's for future me when I'm actually prepared, because right now I'm not into it.
1 parent 746723c commit ad78052

File tree

4 files changed

+3
-179
lines changed

4 files changed

+3
-179
lines changed

hdlls/windows/ma_thing.hdll

-512 Bytes
Binary file not shown.

src/miniaudio/ma_thing.cpp

Lines changed: 1 addition & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,6 @@ struct DecoderStream {
238238
bool active = false;
239239
ma_decoder decoder;
240240
ma_uint64 decoderLength = 0;
241-
ma_uint64 detectedLatency = 0;
242241

243242
DecoderStream() {
244243
memset(&decoder, 0, sizeof(ma_decoder));
@@ -468,7 +467,6 @@ struct DecoderStream {
468467
validFrames = other.validFrames;
469468
active = other.active;
470469
decoderLength = other.decoderLength;
471-
detectedLatency = other.detectedLatency;
472470

473471
// Move async state (non-atomic members)
474472
asyncState.nextBufferStartPos = other.asyncState.nextBufferStartPos;
@@ -693,10 +691,6 @@ class AudioSystem {
693691
bool exists = false;
694692
double masterVolume = 1.0;
695693

696-
ma_uint64 detectedLatency = 0; // Max latency across all decoders
697-
bool latenciesDetected = false;
698-
static constexpr float SILENCE_THRESHOLD = 0.1f;
699-
700694
ma_uint32 callbackCounter = 0;
701695

702696
AudioSystem() {
@@ -778,15 +772,6 @@ class AudioSystem {
778772
s.asyncState.asyncNextBuffer = s.pcmBufferB;
779773
s.asyncState.asyncLoadingBuffer = s.pcmBufferC;
780774

781-
// Store per-decoder latency
782-
// the inst starts first so yeah
783-
if (i == 0) {
784-
s.detectedLatency = detectLatency(i);
785-
if (s.detectedLatency > detectedLatency) {
786-
detectedLatency = s.detectedLatency;
787-
}
788-
}
789-
790775
// Fill initial buffer (starts at 0)
791776
fillInitialBuffer(i, 0);
792777

@@ -804,8 +789,6 @@ class AudioSystem {
804789
}
805790
}
806791

807-
latenciesDetected = true;
808-
809792
// Initialize async loader
810793
streamPtrs.clear();
811794
for (auto& stream : streams) {
@@ -836,73 +819,6 @@ class AudioSystem {
836819
mixerState = 3;
837820
}
838821

839-
// actually check for both channels because if certain instruments like ample metal hellrazer are played at the beginning, each of the channels can be offsetted.
840-
ma_uint64 detectLatency(size_t index) {
841-
DecoderStream& s = streams[index];
842-
843-
const ma_uint64 SCAN_CHUNK_SIZE = 4096;
844-
float* scanBuffer = (float*)malloc(sizeof(float) * SCAN_CHUNK_SIZE * CHANNEL_COUNT);
845-
846-
if (!scanBuffer) return 0;
847-
848-
ma_decoder_seek_to_pcm_frame(&s.decoder, 0);
849-
850-
ma_uint64 totalFramesScanned = 0;
851-
ma_uint64 latencyFrames = 0;
852-
bool foundSignal = false;
853-
854-
ma_uint64 maxFramesToScan = SAMPLE_RATE * 0.1;
855-
if (maxFramesToScan > s.decoderLength) {
856-
maxFramesToScan = s.decoderLength;
857-
}
858-
859-
const float VOLUME_THRESHOLD = 0.2f; // 20% volume
860-
861-
while (totalFramesScanned < maxFramesToScan && !foundSignal) {
862-
ma_uint64 framesToRead = SCAN_CHUNK_SIZE;
863-
if (totalFramesScanned + framesToRead > maxFramesToScan) {
864-
framesToRead = maxFramesToScan - totalFramesScanned;
865-
}
866-
867-
ma_uint64 framesRead = 0;
868-
ma_decoder_read_pcm_frames(&s.decoder, scanBuffer, framesToRead, &framesRead);
869-
870-
if (framesRead == 0) break;
871-
872-
for (ma_uint64 frame = 0; frame < framesRead && !foundSignal; frame++) {
873-
bool bothChannelsAboveThreshold = true;
874-
875-
for (int ch = 0; ch < CHANNEL_COUNT; ch++) {
876-
float sample = scanBuffer[frame * CHANNEL_COUNT + ch];
877-
if (fabs(sample) <= VOLUME_THRESHOLD) {
878-
bothChannelsAboveThreshold = false;
879-
break;
880-
}
881-
}
882-
883-
if (bothChannelsAboveThreshold) {
884-
latencyFrames = totalFramesScanned + frame;
885-
foundSignal = true;
886-
}
887-
}
888-
889-
totalFramesScanned += framesRead;
890-
}
891-
892-
free(scanBuffer);
893-
ma_decoder_seek_to_pcm_frame(&s.decoder, 0);
894-
895-
return latencyFrames;
896-
}
897-
898-
double getLatencyMs() const {
899-
return (double)detectedLatency / (SAMPLE_RATE * 0.001);
900-
}
901-
902-
ma_uint64 getLatencyFrames() const {
903-
return detectedLatency;
904-
}
905-
906822
void destroy() {
907823
if(!exists) return;
908824
exists = false;
@@ -930,8 +846,6 @@ class AudioSystem {
930846
playbackRate = 1.0f;
931847
masterVolume = 1.0;
932848
mixerState = 3;
933-
latenciesDetected = false;
934-
detectedLatency = 0;
935849
callbackCounter = 0;
936850
}
937851

@@ -1307,8 +1221,6 @@ class AudioSystem {
13071221
masterVolume = other.masterVolume;
13081222
mixerState = other.mixerState;
13091223
exists = other.exists;
1310-
latenciesDetected = other.latenciesDetected;
1311-
detectedLatency = other.detectedLatency;
13121224
callbackCounter = other.callbackCounter;
13131225

13141226
other.stretch = nullptr;
@@ -1318,8 +1230,6 @@ class AudioSystem {
13181230
other.masterVolume = 1.0;
13191231
other.mixerState = 3;
13201232
other.exists = false;
1321-
other.latenciesDetected = false;
1322-
other.detectedLatency = 0;
13231233
other.callbackCounter = 0;
13241234
}
13251235
};
@@ -2133,7 +2043,7 @@ int detectLatency() {
21332043
if (g_audioSystem.exists) {
21342044
if(!wearingPlugNPlay()) osMs += 50;
21352045
if(wearingHeadphones()) osMs += 50;
2136-
osMs -= g_audioSystem.getLatencyMs();
2046+
ma_device device = g_audioSystem.device;
21372047
}
21382048
return osMs;
21392049
}

src/miniaudio/ma_thing_hl.cpp

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@ struct DecoderStream {
245245
bool active = false;
246246
ma_decoder decoder;
247247
ma_uint64 decoderLength = 0;
248-
ma_uint64 detectedLatency = 0;
249248

250249
DecoderStream() {
251250
memset(&decoder, 0, sizeof(ma_decoder));
@@ -475,7 +474,6 @@ struct DecoderStream {
475474
validFrames = other.validFrames;
476475
active = other.active;
477476
decoderLength = other.decoderLength;
478-
detectedLatency = other.detectedLatency;
479477

480478
// Move async state (non-atomic members)
481479
asyncState.nextBufferStartPos = other.asyncState.nextBufferStartPos;
@@ -700,10 +698,6 @@ class AudioSystem {
700698
bool exists = false;
701699
double masterVolume = 1.0;
702700

703-
ma_uint64 detectedLatency = 0; // Max latency across all decoders
704-
bool latenciesDetected = false;
705-
static constexpr float SILENCE_THRESHOLD = 0.1f;
706-
707701
ma_uint32 callbackCounter = 0;
708702

709703
AudioSystem() {
@@ -785,12 +779,6 @@ class AudioSystem {
785779
s.asyncState.asyncNextBuffer = s.pcmBufferB;
786780
s.asyncState.asyncLoadingBuffer = s.pcmBufferC;
787781

788-
// Store per-decoder latency
789-
s.detectedLatency = detectLatency(i);
790-
if (s.detectedLatency > detectedLatency) {
791-
detectedLatency = s.detectedLatency;
792-
}
793-
794782
// Fill initial buffer (starts at 0)
795783
fillInitialBuffer(i, 0);
796784

@@ -808,8 +796,6 @@ class AudioSystem {
808796
}
809797
}
810798

811-
latenciesDetected = true;
812-
813799
// Initialize async loader
814800
streamPtrs.clear();
815801
for (auto& stream : streams) {
@@ -840,72 +826,6 @@ class AudioSystem {
840826
mixerState = 3;
841827
}
842828

843-
ma_uint64 detectLatency(size_t index) {
844-
DecoderStream& s = streams[index];
845-
846-
const ma_uint64 SCAN_CHUNK_SIZE = 4096;
847-
float* scanBuffer = (float*)malloc(sizeof(float) * SCAN_CHUNK_SIZE * CHANNEL_COUNT);
848-
849-
if (!scanBuffer) return 0;
850-
851-
ma_decoder_seek_to_pcm_frame(&s.decoder, 0);
852-
853-
ma_uint64 totalFramesScanned = 0;
854-
ma_uint64 latencyFrames = 0;
855-
bool foundSignal = false;
856-
857-
ma_uint64 maxFramesToScan = SAMPLE_RATE * 0.1;
858-
if (maxFramesToScan > s.decoderLength) {
859-
maxFramesToScan = s.decoderLength;
860-
}
861-
862-
const float VOLUME_THRESHOLD = 0.2f; // 20% volume
863-
864-
while (totalFramesScanned < maxFramesToScan && !foundSignal) {
865-
ma_uint64 framesToRead = SCAN_CHUNK_SIZE;
866-
if (totalFramesScanned + framesToRead > maxFramesToScan) {
867-
framesToRead = maxFramesToScan - totalFramesScanned;
868-
}
869-
870-
ma_uint64 framesRead = 0;
871-
ma_decoder_read_pcm_frames(&s.decoder, scanBuffer, framesToRead, &framesRead);
872-
873-
if (framesRead == 0) break;
874-
875-
for (ma_uint64 frame = 0; frame < framesRead && !foundSignal; frame++) {
876-
bool bothChannelsAboveThreshold = true;
877-
878-
for (int ch = 0; ch < CHANNEL_COUNT; ch++) {
879-
float sample = scanBuffer[frame * CHANNEL_COUNT + ch];
880-
if (fabs(sample) <= VOLUME_THRESHOLD) {
881-
bothChannelsAboveThreshold = false;
882-
break;
883-
}
884-
}
885-
886-
if (bothChannelsAboveThreshold) {
887-
latencyFrames = totalFramesScanned + frame;
888-
foundSignal = true;
889-
}
890-
}
891-
892-
totalFramesScanned += framesRead;
893-
}
894-
895-
free(scanBuffer);
896-
ma_decoder_seek_to_pcm_frame(&s.decoder, 0);
897-
898-
return latencyFrames;
899-
}
900-
901-
double getLatencyMs() const {
902-
return (double)detectedLatency / (SAMPLE_RATE * 0.001);
903-
}
904-
905-
ma_uint64 getLatencyFrames() const {
906-
return detectedLatency;
907-
}
908-
909829
void destroy() {
910830
if(!exists) return;
911831
exists = false;
@@ -933,8 +853,6 @@ class AudioSystem {
933853
playbackRate = 1.0f;
934854
masterVolume = 1.0;
935855
mixerState = 3;
936-
latenciesDetected = false;
937-
detectedLatency = 0;
938856
callbackCounter = 0;
939857
}
940858

@@ -1310,8 +1228,6 @@ class AudioSystem {
13101228
masterVolume = other.masterVolume;
13111229
mixerState = other.mixerState;
13121230
exists = other.exists;
1313-
latenciesDetected = other.latenciesDetected;
1314-
detectedLatency = other.detectedLatency;
13151231
callbackCounter = other.callbackCounter;
13161232

13171233
other.stretch = nullptr;
@@ -1321,8 +1237,6 @@ class AudioSystem {
13211237
other.masterVolume = 1.0;
13221238
other.mixerState = 3;
13231239
other.exists = false;
1324-
other.latenciesDetected = false;
1325-
other.detectedLatency = 0;
13261240
other.callbackCounter = 0;
13271241
}
13281242
};
@@ -2142,7 +2056,6 @@ HL_PRIM int HL_NAME(detectLatency)(_NO_ARG) {
21422056
if (g_audioSystem.exists) {
21432057
if(!HL_NAME(wearingPlugNPlay)()) osMs += 50;
21442058
if(HL_NAME(wearingHeadphones)()) osMs += 50;
2145-
osMs -= g_audioSystem.getLatencyMs();
21462059
}
21472060
return osMs;
21482061
}

src/structures/gameplay/Strumline.hx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,9 @@ class Strumline {
162162
var posWithLatency = MetaNote.floatToMetaNotePosition(pf.songPosition + (Main.conductor.offset * 2.0));
163163
// Now 0..1 instead of -250..250 just in case people don't know what the hitbox actually is
164164
// and it's flexible too considering you want different offsets for certain things yk?
165+
// also adjust for scroll speed like psych does
165166
var _timing = MetaNote.metaNotePositionToSongTime(noteToHit.position - posWithLatency);
166-
var timing = (_timing / parent._cachedHitbox) * 0.8;
167+
var timing = (_timing / parent._cachedHitbox) * 0.8 / ((pf.scrollSpeed * 0.5) + 0.5);
167168
// this trace was there because I was constantly testing the new latency compensation system
168169
// specifically implemented inside the note system as I've had to even make an `onBeatHitUnoffsetted` event
169170
// just to make it so that countdown doesn't get affected by the conductor offset in the first place

0 commit comments

Comments
 (0)