mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
OSS: Prime the playback buffer when starting the device.
This commit is contained in:
+48
-8
@@ -39612,17 +39612,48 @@ static void ma_device_uninit__oss(ma_device* pDevice)
|
|||||||
ma_free(pDeviceStateOSS, ma_device_get_allocation_callbacks(pDevice));
|
ma_free(pDeviceStateOSS, ma_device_get_allocation_callbacks(pDevice));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ma_device_prime_playback_buffer__oss(ma_device* pDevice)
|
||||||
|
{
|
||||||
|
ma_device_state_oss* pDeviceStateOSS = ma_device_get_backend_state__oss(pDevice);
|
||||||
|
ma_device_type deviceType = ma_device_get_type(pDevice);
|
||||||
|
ma_uint8 buffer[4096];
|
||||||
|
ma_uint32 bpf;
|
||||||
|
ma_uint32 framesToWrite;
|
||||||
|
ma_uint32 framesWritten;
|
||||||
|
|
||||||
|
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
|
||||||
|
bpf = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||||
|
framesToWrite = pDevice->playback.internalPeriodSizeInFrames * pDevice->playback.internalPeriods;
|
||||||
|
framesWritten = 0;
|
||||||
|
|
||||||
|
MA_ZERO_MEMORY(buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
while (framesWritten < framesToWrite) {
|
||||||
|
ma_uint32 framesToWriteThisIteration = sizeof(buffer) / bpf;
|
||||||
|
ma_uint32 framesRemaining = framesToWrite - framesWritten;
|
||||||
|
if (framesToWriteThisIteration > framesRemaining) {
|
||||||
|
framesToWriteThisIteration = framesRemaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just a guard to ensure we don't get stuck in a loop. Should never happen in practice (would require a massive channel count). */
|
||||||
|
if (framesToWriteThisIteration == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(pDeviceStateOSS->fdPlayback, buffer, framesToWriteThisIteration);
|
||||||
|
framesWritten += framesToWriteThisIteration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Note on Starting and Stopping
|
Note on Starting and Stopping
|
||||||
=============================
|
=============================
|
||||||
In the past I was using SNDCTL_DSP_HALT to stop the device, however this results in issues when
|
In the past I was using SNDCTL_DSP_HALT to stop the device, however this results in issues when
|
||||||
trying to resume the device again. If we use SNDCTL_DSP_HALT, the next write() or read() will
|
trying to resume the device again. If we use SNDCTL_DSP_HALT, the next write() or read() will
|
||||||
fail. Instead what we need to do is just not write or read to and from the device when the
|
fail. Instead what we need to do is just not write or read to and from the device when the
|
||||||
device is not running.
|
device is not running. As a result, the stop function for OSS is just an empty stub.
|
||||||
|
|
||||||
As a result, both the start and stop functions for OSS are just empty stubs. The starting and
|
|
||||||
stopping logic is handled by ma_device_write__oss() and ma_device_read__oss(). These will check
|
|
||||||
the device state, and if the device is stopped they will simply not do any kind of processing.
|
|
||||||
|
|
||||||
The downside to this technique is that I've noticed a fairly lengthy delay in stopping the
|
The downside to this technique is that I've noticed a fairly lengthy delay in stopping the
|
||||||
device, up to a second. This is on a virtual machine, and as such might just be due to the
|
device, up to a second. This is on a virtual machine, and as such might just be due to the
|
||||||
@@ -39630,13 +39661,22 @@ virtual drivers, but I'm not fully sure. I am not sure how to work around this p
|
|||||||
the moment that's just how it's going to have to be.
|
the moment that's just how it's going to have to be.
|
||||||
|
|
||||||
When starting the device, OSS will automatically start it when write() or read() is called.
|
When starting the device, OSS will automatically start it when write() or read() is called.
|
||||||
|
|
||||||
|
UPDATE: 2026-01-14
|
||||||
|
I'm no longer getting the stop delay when running from inside Virtual Box.
|
||||||
*/
|
*/
|
||||||
static ma_result ma_device_start__oss(ma_device* pDevice)
|
static ma_result ma_device_start__oss(ma_device* pDevice)
|
||||||
{
|
{
|
||||||
MA_ASSERT(pDevice != NULL);
|
ma_device_type deviceType = ma_device_get_type(pDevice);
|
||||||
|
|
||||||
/* The device is automatically started with reading and writing. */
|
/*
|
||||||
(void)pDevice;
|
For playback we'll start the device by priming it with silence. Otherwise we'll do nothing
|
||||||
|
and let it start in step(). We want the playback buffer to be initially filled with silence
|
||||||
|
for the benefit of duplex mode.
|
||||||
|
*/
|
||||||
|
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
|
||||||
|
ma_device_prime_playback_buffer__oss(pDevice);
|
||||||
|
}
|
||||||
|
|
||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user