Commit Description:
Add timers for Simulation and various engines...
Commit Description:
Add timers for Simulation and various engines Starting to add additional timers for different stages of the process of updating in order to get more insight into what is slowing it down. The update takes 9ms, which is much longer than it used to. Engine-specific timers are coming later.
File last commit:
Show/Diff file:
Action:
FNA/lib/FAudio/utils/testreverb/audio_xaudio.cpp
291 lines | 7.9 KiB | text/x-c | CppLexer
#include "audio.h"
#ifdef HAVE_XAUDIO2
#include <xaudio2.h>
#include <xaudio2fx.h>
#include <SDL.h>
struct AudioContext
{
IXAudio2 *xaudio2;
uint32_t output_5p1;
AudioVoiceType effect_on_voice;
IXAudio2MasteringVoice *mastering_voice;
IXAudio2SubmixVoice *submix_voice;
IXAudio2SourceVoice *source_voice;
IXAudio2Voice *voices[3];
unsigned int wav_channels;
unsigned int wav_samplerate;
drwav_uint64 wav_sample_count;
float * wav_samples;
XAUDIO2_BUFFER buffer;
XAUDIO2_EFFECT_DESCRIPTOR reverb_effect;
XAUDIO2_EFFECT_CHAIN effect_chain;
ReverbParameters reverb_params;
bool reverb_enabled;
};
void xaudio_destroy_context(AudioContext *context)
{
if (context != NULL)
{
context->source_voice->DestroyVoice();
context->submix_voice->DestroyVoice();
context->mastering_voice->DestroyVoice();
context->xaudio2->Release();
delete context;
}
}
void xaudio_create_voice(AudioContext *context, float *buffer, size_t buffer_size, int sample_rate, int num_channels)
{
// create reverb effect
IUnknown *xapo = NULL;
HRESULT hr = XAudio2CreateReverb(&xapo);
if (FAILED(hr))
{
return;
}
// create effect chain
context->reverb_effect.InitialState = context->reverb_enabled;
context->reverb_effect.OutputChannels = (context->output_5p1) ? 6 : context->wav_channels;
context->reverb_effect.pEffect = xapo;
context->effect_chain.EffectCount = 1;
context->effect_chain.pEffectDescriptors = &context->reverb_effect;
XAUDIO2_EFFECT_CHAIN *voice_effect[3] = {NULL, NULL, NULL};
voice_effect[context->effect_on_voice] = &context->effect_chain;
// create a mastering voice
uint32_t inChannels = context->wav_channels;
if (context->output_5p1 && context->effect_on_voice != AudioVoiceType_Master)
{
inChannels = 6;
}
hr = context->xaudio2->CreateMasteringVoice(
&context->mastering_voice,
inChannels,
XAUDIO2_DEFAULT_SAMPLERATE,
0,
0,
voice_effect[AudioVoiceType_Master]
);
if (FAILED(hr))
{
return;
}
context->voices[AudioVoiceType_Master] = context->mastering_voice;
// create a submix voice
inChannels = context->wav_channels;
if (context->output_5p1 && context->effect_on_voice == AudioVoiceType_Source)
{
inChannels = 6;
}
hr = context->xaudio2->CreateSubmixVoice(
&context->submix_voice,
inChannels,
SAMPLERATE,
0,
0,
NULL,
voice_effect[AudioVoiceType_Submix]
);
if (FAILED(hr))
{
return;
}
context->voices[AudioVoiceType_Submix] = context->submix_voice;
context->submix_voice->SetVolume(1.0f);
// create a source voice
XAUDIO2_SEND_DESCRIPTOR desc = {0, context->submix_voice};
XAUDIO2_VOICE_SENDS sends = {1, &desc};
WAVEFORMATEX waveFormat;
waveFormat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
waveFormat.nChannels = num_channels;
waveFormat.nSamplesPerSec = sample_rate;
waveFormat.nBlockAlign = num_channels * 4;
waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
waveFormat.wBitsPerSample = 32;
waveFormat.cbSize = 0;
hr = context->xaudio2->CreateSourceVoice(
&context->source_voice,
&waveFormat,
0,
XAUDIO2_DEFAULT_FREQ_RATIO,
NULL,
&sends,
voice_effect[AudioVoiceType_Source]
);
if (FAILED(hr))
{
return;
}
context->voices[AudioVoiceType_Source] = context->source_voice;
context->source_voice->SetVolume(1.0f);
xapo->Release();
// submit the array
SDL_zero(context->buffer);
context->buffer.AudioBytes = 4 * buffer_size * num_channels;
context->buffer.pAudioData = (byte *)buffer;
context->buffer.Flags = XAUDIO2_END_OF_STREAM;
context->buffer.PlayBegin = 0;
context->buffer.PlayLength = buffer_size;
context->buffer.LoopBegin = 0;
context->buffer.LoopLength = 0;
context->buffer.LoopCount = 0;
}
void xaudio_reverb_set_params(AudioContext *context)
{
XAUDIO2FX_REVERB_PARAMETERS native_params = { 0 };
native_params.WetDryMix = context->reverb_params.WetDryMix;
native_params.ReflectionsDelay = context->reverb_params.ReflectionsDelay;
native_params.ReverbDelay = context->reverb_params.ReverbDelay;
native_params.RearDelay = context->reverb_params.RearDelay;
native_params.PositionLeft = context->reverb_params.PositionLeft;
native_params.PositionRight = context->reverb_params.PositionRight;
native_params.PositionMatrixLeft = context->reverb_params.PositionMatrixLeft;
native_params.PositionMatrixRight = context->reverb_params.PositionMatrixRight;
native_params.EarlyDiffusion = context->reverb_params.EarlyDiffusion;
native_params.LateDiffusion = context->reverb_params.LateDiffusion;
native_params.LowEQGain = context->reverb_params.LowEQGain;
native_params.LowEQCutoff = context->reverb_params.LowEQCutoff;
native_params.HighEQGain = context->reverb_params.HighEQGain;
native_params.HighEQCutoff = context->reverb_params.HighEQCutoff;
native_params.RoomFilterFreq = context->reverb_params.RoomFilterFreq;
native_params.RoomFilterMain = context->reverb_params.RoomFilterMain;
native_params.RoomFilterHF = context->reverb_params.RoomFilterHF;
native_params.ReflectionsGain = context->reverb_params.ReflectionsGain;
native_params.ReverbGain = context->reverb_params.ReverbGain;
native_params.DecayTime = context->reverb_params.DecayTime;
native_params.Density = context->reverb_params.Density;
native_params.RoomSize = context->reverb_params.RoomSize;
/* 2.8+ only but zero-initialization catches this
native_params.DisableLateField = 0; */
HRESULT hr = context->voices[context->effect_on_voice]->SetEffectParameters(
0,
&native_params,
sizeof(XAUDIO2FX_REVERB_PARAMETERS)
);
}
void xaudio_wave_load(AudioContext *context, AudioSampleWave sample, bool stereo)
{
if (context->source_voice)
{
context->source_voice->DestroyVoice();
context->submix_voice->DestroyVoice();
context->mastering_voice->DestroyVoice();
}
context->wav_samples = WAVS_Open(
sample,
stereo,
&context->wav_channels,
&context->wav_samplerate,
&context->wav_sample_count);
context->wav_sample_count /= context->wav_channels;
audio_create_voice(context, context->wav_samples, context->wav_sample_count, context->wav_samplerate, context->wav_channels);
xaudio_reverb_set_params(context);
}
void xaudio_wave_play(AudioContext *context)
{
context->source_voice->Stop();
context->source_voice->FlushSourceBuffers();
HRESULT hr = context->source_voice->SubmitSourceBuffer(&context->buffer);
if (FAILED(hr))
{
return;
}
context->source_voice->Start();
}
void xaudio_wave_stop(AudioContext *context)
{
context->source_voice->Stop(XAUDIO2_PLAY_TAILS);
}
void xaudio_effect_change(AudioContext *context, bool enabled, ReverbParameters *params)
{
HRESULT hr;
if (context->reverb_enabled && !enabled)
{
hr = context->voices[context->effect_on_voice]->DisableEffect(0);
context->reverb_enabled = enabled;
}
else if (!context->reverb_enabled && enabled)
{
hr = context->voices[context->effect_on_voice]->EnableEffect(0);
context->reverb_enabled = enabled;
}
memcpy(&context->reverb_params, params, sizeof(ReverbParameters));
xaudio_reverb_set_params(context);
}
AudioContext *xaudio_create_context(bool output_5p1, AudioVoiceType effect_on_voice)
{
// setup function pointers
audio_destroy_context = xaudio_destroy_context;
audio_create_voice = xaudio_create_voice;
audio_wave_load = xaudio_wave_load;
audio_wave_play = xaudio_wave_play;
audio_wave_stop = xaudio_wave_stop;
audio_effect_change = xaudio_effect_change;
// create XAudio object
IXAudio2 *xaudio2;
HRESULT hr = XAudio2Create(&xaudio2);
if (FAILED(hr))
{
return NULL;
}
// return a context object
AudioContext *context = new AudioContext();
context->xaudio2 = xaudio2;
context->output_5p1 = output_5p1;
context->effect_on_voice = effect_on_voice;
context->mastering_voice = NULL;
context->submix_voice = NULL;
context->source_voice = NULL;
context->wav_samples = NULL;
context->reverb_params = audio_reverb_presets[0];
context->reverb_enabled = false;
// load the first wave
audio_wave_load(context, (AudioSampleWave) 0, false);
return context;
}
#endif // HAVE_XAUDIO2