add more verbose ASIO debugging

This commit is contained in:
Anthony Samms
2025-10-20 15:29:32 -04:00
parent e104e14513
commit 64174a53b3
4 changed files with 72 additions and 16 deletions

View File

@@ -44,7 +44,6 @@ jobs:
mingw-w64-x86_64-speex
mingw-w64-x86_64-cmake
mingw-w64-x86_64-pkg-config
# Note: Removed mingw-w64-x86_64-portaudio since we're using our own
- name: Verify local PortAudio library (Windows)
if: runner.os == 'Windows'
@@ -199,6 +198,12 @@ jobs:
sudo make install
shell: bash
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: PyTaiko-${{ runner.os }}-${{ runner.arch }}
path: release/
- name: Install uv
uses: astral-sh/setup-uv@v4
@@ -264,12 +269,6 @@ jobs:
fi
shell: bash
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: PyTaiko-${{ runner.os }}-${{ runner.arch }}
path: release/
- name: Upload Release
uses: softprops/action-gh-release@v2
if: github.ref == 'refs/heads/main' && github.event_name == 'push'

View File

@@ -32,9 +32,18 @@ right_don = [17]
right_kat = [12]
[audio]
# device_type: 0 = default, check console output from list_host_apis() for other options
device_type = 0
# sample_rate: -1 = use device default (usually 44100 or 48000)
sample_rate = -1
buffer_size = 0
# buffer_size: Size in samples per audio buffer
# - 0 = let driver choose (may result in very small buffers with ASIO, typically 64)
# - ASIO users: Use 128, 256, 512, 1024, or 2048 (must be power of 2)
# - ASIO drivers have strict minimum buffer sizes (often 64-256 samples)
# - If you request a buffer size below the driver's minimum, it will use the minimum instead
# - Lower = less latency but higher CPU usage; Higher = more latency but more stable
# - Recommended: 512 for most users, 256 for low latency, 1024+ for stability
buffer_size = 512
exclusive = false
[volume]

View File

@@ -6,6 +6,9 @@
// stream to portaudio
#include "portaudio.h"
#ifdef _WIN32
#include "pa_asio.h"
#endif
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
@@ -324,6 +327,44 @@ void init_audio_device(PaHostApiIndex host_api, double sample_rate, unsigned lon
AUDIO.System.outputParameters.hostApiSpecificStreamInfo = NULL;
AUDIO.System.sampleRate = sample_rate;
const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(AUDIO.System.outputParameters.device);
const PaHostApiInfo *hostApiInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
#ifdef _WIN32
if (hostApiInfo->type == paASIO) {
long minSize, maxSize, preferredSize, granularity;
PaError asioErr = PaAsio_GetAvailableBufferSizes(AUDIO.System.outputParameters.device,
&minSize, &maxSize, &preferredSize, &granularity);
if (asioErr == paNoError) {
TRACELOG(LOG_INFO, "AUDIO: ASIO buffer size constraints:");
TRACELOG(LOG_INFO, " > Minimum: %ld samples", minSize);
TRACELOG(LOG_INFO, " > Maximum: %ld samples", maxSize);
TRACELOG(LOG_INFO, " > Preferred: %ld samples", preferredSize);
if (granularity == -1) {
TRACELOG(LOG_INFO, " > Granularity: Powers of 2 only");
} else if (granularity == 0) {
TRACELOG(LOG_INFO, " > Granularity: Fixed size (min=max=preferred)");
} else {
TRACELOG(LOG_INFO, " > Granularity: %ld samples", granularity);
}
// Warn if requested buffer size is out of range
if (buffer_size > 0 && buffer_size < minSize) {
TRACELOG(LOG_WARNING, "AUDIO: Requested buffer size (%lu) is below ASIO minimum (%ld)", buffer_size, minSize);
TRACELOG(LOG_WARNING, "AUDIO: Driver will use %ld samples instead", minSize);
} else if (buffer_size > maxSize) {
TRACELOG(LOG_WARNING, "AUDIO: Requested buffer size (%lu) exceeds ASIO maximum (%ld)", buffer_size, maxSize);
TRACELOG(LOG_WARNING, "AUDIO: Driver will use %ld samples instead", maxSize);
} else if (buffer_size == 0) {
TRACELOG(LOG_INFO, "AUDIO: Buffer size not specified, driver will choose (likely %ld samples)", preferredSize);
}
} else {
TRACELOG(LOG_WARNING, "AUDIO: Failed to query ASIO buffer sizes: %s", Pa_GetErrorText(asioErr));
}
}
#endif
err = Pa_OpenStream(&AUDIO.System.stream,
NULL, // No input
&AUDIO.System.outputParameters, // Output parameters
@@ -351,17 +392,24 @@ void init_audio_device(PaHostApiIndex host_api, double sample_rate, unsigned lon
AUDIO.System.isReady = true;
const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(AUDIO.System.outputParameters.device);
const PaHostApiInfo *hostApiInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
TRACELOG(LOG_INFO, "AUDIO: Device initialized successfully");
TRACELOG(LOG_INFO, " > Backend: PortAudio | %s", hostApiInfo->name);
TRACELOG(LOG_INFO, " > Device: %s", deviceInfo->name);
TRACELOG(LOG_INFO, " > Format: %s", "Float32");
const PaStreamInfo *streamInfo = Pa_GetStreamInfo(AUDIO.System.stream);
TRACELOG(LOG_INFO, " > Channels: %d", AUDIO_DEVICE_CHANNELS);
TRACELOG(LOG_INFO, " > Sample rate: %f", AUDIO.System.sampleRate);
TRACELOG(LOG_INFO, " > Buffer size: %lu", buffer_size);
TRACELOG(LOG_INFO, " > Latency: %f ms", Pa_GetStreamInfo(AUDIO.System.stream)->outputLatency * 1000.0);
TRACELOG(LOG_INFO, " > Buffer size: %lu (requested)", buffer_size);
TRACELOG(LOG_INFO, " > Latency: %f ms", streamInfo->outputLatency * 1000.0);
#ifdef _WIN32
if (hostApiInfo->type == paASIO) {
unsigned long estimatedBufferSize = (unsigned long)(streamInfo->outputLatency * AUDIO.System.sampleRate);
TRACELOG(LOG_INFO, " > Estimated actual buffer: ~%lu samples (based on latency)", estimatedBufferSize);
if (buffer_size > 0 && estimatedBufferSize != buffer_size) {
TRACELOG(LOG_INFO, " > Note: ASIO driver adjusted buffer size to meet its constraints");
}
}
#endif
}
void close_audio_device(void)

View File

@@ -16,7 +16,7 @@ class DevScreen:
if not self.screen_init:
self.screen_init = True
tex.load_screen_textures('game')
self.obj = JudgeCounter(10)
self.obj = JudgeCounter()
def on_screen_end(self, next_screen: str):
self.screen_init = False
@@ -24,11 +24,11 @@ class DevScreen:
def update(self):
self.on_screen_start()
self.obj.update()
self.obj.update(0, 0, 0, 0)
if ray.is_key_pressed(ray.KeyboardKey.KEY_ENTER):
return self.on_screen_end('GAME')
if ray.is_key_pressed(ray.KeyboardKey.KEY_SPACE):
self.obj = JudgeCounter(500)
self.obj = JudgeCounter()
def draw(self):
ray.draw_rectangle(0, 0, 1280, 720, ray.GREEN)