1
0
mirror of https://github.com/wine-mirror/wine synced 2024-06-26 13:02:25 +00:00

faudio: Import upstream release 24.06.

This commit is contained in:
Alexandre Julliard 2024-06-02 22:03:55 +02:00
parent 951e0e27a7
commit 41c65022c1
7 changed files with 266 additions and 44 deletions

View File

@ -494,7 +494,7 @@ extern FAudioGUID DATAFORMAT_SUBTYPE_IEEE_FLOAT;
#define FAUDIO_ABI_VERSION 0
#define FAUDIO_MAJOR_VERSION 24
#define FAUDIO_MINOR_VERSION 5
#define FAUDIO_MINOR_VERSION 6
#define FAUDIO_PATCH_VERSION 0
#define FAUDIO_COMPILED_VERSION ( \

View File

@ -85,7 +85,7 @@ static inline float FACT_INTERNAL_CalculateFilterFrequency(
*
* -@Woflox
*/
float freq = 2 * FAudio_sin(
float freq = 2.0f * FAudio_sinf(
F3DAUDIO_PI *
FAudio_min(desiredFrequency / sampleRate, 0.5f)
);
@ -1027,21 +1027,21 @@ float FACT_INTERNAL_CalculateRPC(
}
else if (rpc->points[i].type == 1) /* Fast */
{
result += maxY * (1.0f - FAudio_pow(1.0f - FAudio_pow(deltaXNormalized, 1.0f / 1.5f), 1.5f));
result += maxY * (1.0f - FAudio_powf(1.0f - FAudio_powf(deltaXNormalized, 1.0f / 1.5f), 1.5f));
}
else if (rpc->points[i].type == 2) /* Slow */
{
result += maxY * (1.0f - FAudio_pow(1.0f - FAudio_pow(deltaXNormalized, 1.5f), 1.0f / 1.5f));
result += maxY * (1.0f - FAudio_powf(1.0f - FAudio_powf(deltaXNormalized, 1.5f), 1.0f / 1.5f));
}
else if (rpc->points[i].type == 3) /* SinCos */
{
if (maxY > 0.0f)
{
result += maxY * (1.0f - FAudio_pow(1.0f - FAudio_sqrtf(deltaXNormalized), 2.0f));
result += maxY * (1.0f - FAudio_powf(1.0f - FAudio_sqrtf(deltaXNormalized), 2.0f));
}
else
{
result += maxY * (1.0f - FAudio_sqrtf(1.0f - FAudio_pow(deltaXNormalized, 2.0f)));
result += maxY * (1.0f - FAudio_sqrtf(1.0f - FAudio_powf(deltaXNormalized, 2.0f)));
}
}
else
@ -2066,8 +2066,8 @@ uint32_t FACT_INTERNAL_ParseAudioEngine(
rpcOffset,
dspPresetOffset,
dspParameterOffset;
uint16_t blob1Count, blob2Count;
uint8_t version, tool;
uint16_t blob1Count, blob2Count, tool;
uint8_t version;
uint8_t se;
uint32_t magic;
size_t memsize;

View File

@ -183,7 +183,7 @@ static inline void DspBiQuad_Change(
float q,
float gain
) {
const float TWOPI = 6.283185307179586476925286766559005;
const float TWOPI = (float)6.283185307179586476925286766559005;
float theta_c = (TWOPI * frequency) / (float) filter->sampleRate;
float mu = DbGainToFactor(gain);
float beta = (type == DSP_BIQUAD_LOWSHELVING) ?

View File

@ -383,6 +383,12 @@ static void FAudio_INTERNAL_DecodeBuffers(
if ( voice->src.callback != NULL &&
voice->src.callback->OnBufferStart != NULL )
{
FAudio_PlatformUnlockMutex(voice->src.bufferLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
FAudio_PlatformUnlockMutex(voice->sendLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
FAudio_PlatformUnlockMutex(voice->audio->sourceLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock)
@ -393,6 +399,12 @@ static void FAudio_INTERNAL_DecodeBuffers(
FAudio_PlatformLockMutex(voice->audio->sourceLock);
LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock)
FAudio_PlatformLockMutex(voice->sendLock);
LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
FAudio_PlatformLockMutex(voice->src.bufferLock);
LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
}
}
@ -442,6 +454,12 @@ static void FAudio_INTERNAL_DecodeBuffers(
if ( voice->src.callback != NULL &&
voice->src.callback->OnLoopEnd != NULL )
{
FAudio_PlatformUnlockMutex(voice->src.bufferLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
FAudio_PlatformUnlockMutex(voice->sendLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
FAudio_PlatformUnlockMutex(voice->audio->sourceLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock)
@ -452,6 +470,12 @@ static void FAudio_INTERNAL_DecodeBuffers(
FAudio_PlatformLockMutex(voice->audio->sourceLock);
LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock)
FAudio_PlatformLockMutex(voice->sendLock);
LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
FAudio_PlatformLockMutex(voice->src.bufferLock);
LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
}
}
else
@ -504,6 +528,12 @@ static void FAudio_INTERNAL_DecodeBuffers(
/* Callbacks */
if (voice->src.callback != NULL)
{
FAudio_PlatformUnlockMutex(voice->src.bufferLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
FAudio_PlatformUnlockMutex(voice->sendLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
FAudio_PlatformUnlockMutex(voice->audio->sourceLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock)
@ -522,6 +552,15 @@ static void FAudio_INTERNAL_DecodeBuffers(
);
}
FAudio_PlatformLockMutex(voice->audio->sourceLock);
LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock)
FAudio_PlatformLockMutex(voice->sendLock);
LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
FAudio_PlatformLockMutex(voice->src.bufferLock);
LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
/* One last chance at redemption */
if (buffer == NULL && voice->src.bufferList != NULL)
{
@ -531,14 +570,29 @@ static void FAudio_INTERNAL_DecodeBuffers(
if (buffer != NULL && voice->src.callback->OnBufferStart != NULL)
{
FAudio_PlatformUnlockMutex(voice->src.bufferLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
FAudio_PlatformUnlockMutex(voice->sendLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
FAudio_PlatformUnlockMutex(voice->audio->sourceLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock)
voice->src.callback->OnBufferStart(
voice->src.callback,
buffer->pContext
);
}
FAudio_PlatformLockMutex(voice->audio->sourceLock);
LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock)
FAudio_PlatformLockMutex(voice->audio->sourceLock);
LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock)
FAudio_PlatformLockMutex(voice->sendLock);
LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
FAudio_PlatformLockMutex(voice->src.bufferLock);
LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
}
}
voice->audio->pFree(toDelete);
@ -631,7 +685,7 @@ static inline void FAudio_INTERNAL_FilterVoice(
filterState[ci][FAudioHighPassFilter] = samples[j * numChannels + ci] - filterState[ci][FAudioLowPassFilter] - (filter->OneOverQ * filterState[ci][FAudioBandPassFilter]);
filterState[ci][FAudioBandPassFilter] = (filter->Frequency * filterState[ci][FAudioHighPassFilter]) + filterState[ci][FAudioBandPassFilter];
filterState[ci][FAudioNotchFilter] = filterState[ci][FAudioHighPassFilter] + filterState[ci][FAudioLowPassFilter];
samples[j * numChannels + ci] = filterState[ci][filter->Type] * filter->WetDryMix + samples[j * numChannels + ci] * (1.0 - filter->WetDryMix);
samples[j * numChannels + ci] = filterState[ci][filter->Type] * filter->WetDryMix + samples[j * numChannels + ci] * (1.0f - filter->WetDryMix);
}
LOG_FUNC_EXIT(audio)
@ -1250,6 +1304,9 @@ static void FAudio_INTERNAL_FlushPendingBuffers(FAudioSourceVoice *voice)
if (voice->src.callback != NULL && voice->src.callback->OnBufferEnd != NULL)
{
FAudio_PlatformUnlockMutex(voice->src.bufferLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
FAudio_PlatformUnlockMutex(voice->audio->sourceLock);
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock)
@ -1260,6 +1317,9 @@ static void FAudio_INTERNAL_FlushPendingBuffers(FAudioSourceVoice *voice)
FAudio_PlatformLockMutex(voice->audio->sourceLock);
LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock)
FAudio_PlatformLockMutex(voice->src.bufferLock);
LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
}
voice->audio->pFree(entry);
}

View File

@ -57,6 +57,7 @@
#define FAudio_strlcpy(ptr1, ptr2, size) lstrcpynA(ptr1, ptr2, size)
#define FAudio_pow(x, y) pow(x, y)
#define FAudio_powf(x, y) powf(x, y)
#define FAudio_log(x) log(x)
#define FAudio_log10(x) log10(x)
#define FAudio_sin(x) sin(x)
@ -138,6 +139,7 @@ extern void FAudio_Log(char const *msg);
#define FAudio_strlcpy(ptr1, ptr2, size) SDL_strlcpy(ptr1, ptr2, size)
#define FAudio_pow(x, y) SDL_pow(x, y)
#define FAudio_powf(x, y) SDL_powf(x, y)
#define FAudio_log(x) SDL_log(x)
#define FAudio_log10(x) SDL_log10(x)
#define FAudio_sin(x) SDL_sin(x)

View File

@ -41,6 +41,7 @@
#include <initguid.h>
#include <audioclient.h>
#include <mmdeviceapi.h>
#include <devpkey.h>
DEFINE_GUID(CLSID_CWMADecMediaObject, 0x2eeb4adf, 0x4578, 0x4d10, 0xbc, 0xa7, 0xbb, 0x95, 0x5f, 0x56, 0x32, 0x0a);
DEFINE_MEDIATYPE_GUID(MFAudioFormat_XMAudio2, FAUDIO_FORMAT_XMAUDIO2);
@ -180,6 +181,11 @@ static DWORD WINAPI FAudio_AudioClientThread(void *user)
while (WaitForMultipleObjects(2, args->events, FALSE, INFINITE) == WAIT_OBJECT_0)
{
hr = IAudioClient_GetCurrentPadding(args->client, &padding);
if (hr == AUDCLNT_E_DEVICE_INVALIDATED)
{
/* Device was removed, just exit */
break;
}
FAudio_assert(!FAILED(hr) && "Failed to get IAudioClient current padding!");
hr = FAudio_FillAudioClientBuffer(args, render_client, frames, padding);
@ -194,6 +200,141 @@ static DWORD WINAPI FAudio_AudioClientThread(void *user)
return 0;
}
/* Sets `defaultDeviceIndex` to the default audio device index in
* `deviceCollection`.
* On failure, `defaultDeviceIndex` is not modified and the latest error is
* returned. */
static HRESULT FAudio_DefaultDeviceIndex(
IMMDeviceCollection *deviceCollection,
uint32_t* defaultDeviceIndex
) {
IMMDevice *device;
HRESULT hr;
uint32_t i, count;
WCHAR *default_guid;
WCHAR *device_guid;
/* Open the default device and get its GUID. */
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(
device_enumerator,
eRender,
eConsole,
&device
);
if (FAILED(hr))
{
return hr;
}
hr = IMMDevice_GetId(device, &default_guid);
if (FAILED(hr))
{
IMMDevice_Release(device);
return hr;
}
/* Free the default device. */
IMMDevice_Release(device);
hr = IMMDeviceCollection_GetCount(deviceCollection, &count);
if (FAILED(hr))
{
CoTaskMemFree(default_guid);
return hr;
}
for (i = 0; i < count; i += 1)
{
/* Open the device and get its GUID. */
hr = IMMDeviceCollection_Item(deviceCollection, i, &device);
if (FAILED(hr)) {
CoTaskMemFree(default_guid);
return hr;
}
hr = IMMDevice_GetId(device, &device_guid);
if (FAILED(hr))
{
CoTaskMemFree(default_guid);
IMMDevice_Release(device);
return hr;
}
if (lstrcmpW(default_guid, device_guid) == 0)
{
/* Device found. */
CoTaskMemFree(default_guid);
CoTaskMemFree(device_guid);
IMMDevice_Release(device);
*defaultDeviceIndex = i;
return S_OK;
}
CoTaskMemFree(device_guid);
IMMDevice_Release(device);
}
/* This should probably never happen. Just in case, set
* `defaultDeviceIndex` to 0 and return S_OK. */
CoTaskMemFree(default_guid);
*defaultDeviceIndex = 0;
return S_OK;
}
/* Open `device`, corresponding to `deviceIndex`. `deviceIndex` 0 always
* corresponds to the default device. XAudio reorders the devices so that the
* default device is always at index 0, so we mimick this behavior here by
* swapping the devices at indexes 0 and `defaultDeviceIndex`.
*/
static HRESULT FAudio_OpenDevice(uint32_t deviceIndex, IMMDevice **device)
{
IMMDeviceCollection *deviceCollection;
HRESULT hr;
uint32_t defaultDeviceIndex;
uint32_t actualIndex;
*device = NULL;
hr = IMMDeviceEnumerator_EnumAudioEndpoints(
device_enumerator,
eRender,
DEVICE_STATE_ACTIVE,
&deviceCollection
);
if (FAILED(hr))
{
return hr;
}
/* Get the default device index. */
hr = FAudio_DefaultDeviceIndex(deviceCollection, &defaultDeviceIndex);
if (FAILED(hr))
{
IMMDeviceCollection_Release(deviceCollection);
return hr;
}
if (deviceIndex == 0) {
/* Default device. */
actualIndex = defaultDeviceIndex;
} else if (deviceIndex == defaultDeviceIndex) {
/* Open the device at index 0 instead of the "correct" one. */
actualIndex = 0;
} else {
/* Otherwise, just open the device. */
actualIndex = deviceIndex;
}
hr = IMMDeviceCollection_Item(deviceCollection, actualIndex, device);
if (FAILED(hr))
{
IMMDeviceCollection_Release(deviceCollection);
return hr;
}
IMMDeviceCollection_Release(deviceCollection);
return hr;
}
void FAudio_PlatformInit(
FAudio *audio,
uint32_t flags,
@ -223,7 +364,6 @@ void FAudio_PlatformInit(
FAudio_PlatformAddRef();
*platformDevice = NULL;
if (deviceIndex > 0) return;
args = FAudio_malloc(sizeof(*args));
FAudio_assert(!!args && "Failed to allocate FAudio thread args!");
@ -257,13 +397,8 @@ void FAudio_PlatformInit(
data->stopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
FAudio_assert(!!data->stopEvent && "Failed to create FAudio thread stop event!");
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(
device_enumerator,
eRender,
eConsole,
&device
);
FAudio_assert(!FAILED(hr) && "Failed to get default audio endpoint!");
hr = FAudio_OpenDevice(deviceIndex, &device);
FAudio_assert(!FAILED(hr) && "Failed to get audio device!");
hr = IMMDevice_Activate(
device,
@ -394,29 +529,35 @@ void FAudio_PlatformRelease()
uint32_t FAudio_PlatformGetDeviceCount(void)
{
IMMDevice *device;
IMMDeviceCollection *device_collection;
uint32_t count;
HRESULT hr;
FAudio_PlatformAddRef();
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(
hr = IMMDeviceEnumerator_EnumAudioEndpoints(
device_enumerator,
eRender,
eConsole,
&device
DEVICE_STATE_ACTIVE,
&device_collection
);
if (hr == E_NOTFOUND) {
if (FAILED(hr)) {
FAudio_PlatformRelease();
return 0;
}
FAudio_assert(!FAILED(hr) && "Failed to get default audio endpoint!");
hr = IMMDeviceCollection_GetCount(device_collection, &count);
if (FAILED(hr)) {
IMMDeviceCollection_Release(device_collection);
FAudio_PlatformRelease();
return 0;
}
IMMDeviceCollection_Release(device_collection);
IMMDevice_Release(device);
FAudio_PlatformRelease();
return 1;
return count;
}
uint32_t FAudio_PlatformGetDeviceDetails(
@ -427,31 +568,50 @@ uint32_t FAudio_PlatformGetDeviceDetails(
WAVEFORMATEXTENSIBLE *ext;
IAudioClient *client;
IMMDevice *device;
IPropertyStore* properties;
PROPVARIANT deviceName;
uint32_t count = 0;
uint32_t ret = 0;
HRESULT hr;
WCHAR *str;
GUID sub;
FAudio_memset(details, 0, sizeof(FAudioDeviceDetails));
if (index > 0) return FAUDIO_E_INVALID_CALL;
FAudio_PlatformAddRef();
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(
device_enumerator,
eRender,
eConsole,
&device
);
FAudio_assert(!FAILED(hr) && "Failed to get default audio endpoint!");
count = FAudio_PlatformGetDeviceCount();
if (index >= count)
{
FAudio_PlatformRelease();
return FAUDIO_E_INVALID_CALL;
}
details->Role = FAudioGlobalDefaultDevice;
hr = FAudio_OpenDevice(index, &device);
FAudio_assert(!FAILED(hr) && "Failed to get audio endpoint!");
if (index == 0)
{
details->Role = FAudioGlobalDefaultDevice;
}
else
{
details->Role = FAudioNotDefaultDevice;
}
/* Set the Device Display Name */
hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &properties);
FAudio_assert(!FAILED(hr) && "Failed to open device property store!");
hr = IPropertyStore_GetValue(properties, (PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &deviceName);
FAudio_assert(!FAILED(hr) && "Failed to get audio device friendly name!");
lstrcpynW((LPWSTR)details->DisplayName, deviceName.pwszVal, ARRAYSIZE(details->DisplayName) - 1);
PropVariantClear(&deviceName);
IPropertyStore_Release(properties);
/* Set the Device ID */
hr = IMMDevice_GetId(device, &str);
FAudio_assert(!FAILED(hr) && "Failed to get audio endpoint id!");
lstrcpynW((WCHAR *)details->DeviceID, str, ARRAYSIZE(details->DeviceID) - 1);
lstrcpynW((WCHAR *)details->DisplayName, str, ARRAYSIZE(details->DisplayName) - 1);
lstrcpynW((LPWSTR)details->DeviceID, str, ARRAYSIZE(details->DeviceID) - 1);
CoTaskMemFree(str);
hr = IMMDevice_Activate(
@ -1053,7 +1213,7 @@ FAUDIOAPI uint32_t XNA_GetSongEnded()
return 1;
}
FAudioSourceVoice_GetState(songVoice, &state, 0);
return state.BuffersQueued == 0;
return state.BuffersQueued == 0 && state.SamplesPlayed == 0;
}
FAUDIOAPI void XNA_EnableVisualization(uint32_t enable)

View File

@ -1382,7 +1382,7 @@ static void skip(vorb *z, int n)
}
#ifndef STB_VORBIS_NO_STDIO
{
long x = ftell(z->f);
int64_t x = ftell(z->f);
fseek(z->f, x+n, SEEK_SET);
}
#endif