Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
File last commit:
Show/Diff file:
Action:
FNA/lib/FAudio/utils/testreverb/audio_faudio.cpp
261 lines | 6.4 KiB | text/x-c | CppLexer
#include "audio.h"
#include <FAudio.h>
#include <FAudioFX.h>
#include <SDL.h>
struct AudioContext
{
FAudio *faudio;
bool output_5p1;
AudioVoiceType effect_on_voice;
FAudioMasteringVoice *mastering_voice;
FAudioSubmixVoice *submix_voice;
FAudioSourceVoice *source_voice;
FAudioVoice *voices[3];
unsigned int wav_channels;
unsigned int wav_samplerate;
drwav_uint64 wav_sample_count;
float * wav_samples;
FAudioBuffer buffer;
FAudioEffectDescriptor reverb_effect;
FAudioEffectChain effect_chain;
ReverbParameters reverb_params;
bool reverb_enabled;
};
void faudio_destroy_context(AudioContext *context)
{
if (context != NULL)
{
FAudioVoice_DestroyVoice(context->source_voice);
FAudioVoice_DestroyVoice(context->submix_voice);
FAudioVoice_DestroyVoice(context->mastering_voice);
FAudio_Release(context->faudio);
delete context;
}
}
void faudio_create_voice(AudioContext *context, float *buffer, size_t buffer_size, int sample_rate, int num_channels)
{
// create reverb effect
FAPO *fapo = NULL;
uint32_t hr = FAudioCreateReverb(&fapo, 0);
if (hr != 0)
{
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 = fapo;
context->effect_chain.EffectCount = 1;
context->effect_chain.pEffectDescriptors = &context->reverb_effect;
FAudioEffectChain *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 = FAudio_CreateMasteringVoice(
context->faudio,
&context->mastering_voice,
inChannels,
FAUDIO_DEFAULT_SAMPLERATE,
0,
0,
voice_effect[AudioVoiceType_Master]
);
if (hr != 0)
{
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 = FAudio_CreateSubmixVoice(
context->faudio,
&context->submix_voice,
inChannels,
SAMPLERATE,
0,
0,
NULL,
voice_effect[AudioVoiceType_Submix]
);
context->voices[AudioVoiceType_Submix] = context->submix_voice;
FAudioVoice_SetVolume(context->submix_voice, 1.0f, FAUDIO_COMMIT_NOW);
// create a source voice
FAudioSendDescriptor desc = {0, context->submix_voice};
FAudioVoiceSends sends = {1, &desc};
FAudioWaveFormatEx waveFormat;
waveFormat.wFormatTag = 3;
waveFormat.nChannels = num_channels;
waveFormat.nSamplesPerSec = sample_rate;
waveFormat.nAvgBytesPerSec = sample_rate * 4;
waveFormat.nBlockAlign = num_channels * 4;
waveFormat.wBitsPerSample = 32;
waveFormat.cbSize = 0;
hr = FAudio_CreateSourceVoice(
context->faudio,
&context->source_voice,
&waveFormat,
0,
FAUDIO_DEFAULT_FREQ_RATIO,
NULL,
&sends,
voice_effect[AudioVoiceType_Source]
);
if (hr != 0)
{
return;
}
context->voices[AudioVoiceType_Source] = context->source_voice;
FAudioVoice_SetVolume(context->source_voice, 1.0f, FAUDIO_COMMIT_NOW);
// submit the array
SDL_zero(context->buffer);
context->buffer.AudioBytes = 4 * buffer_size * num_channels;
context->buffer.pAudioData = (uint8_t *)buffer;
context->buffer.Flags = FAUDIO_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 faudio_reverb_set_params(AudioContext *context)
{
FAudioVoice_SetEffectParameters(
context->voices[context->effect_on_voice],
0,
&context->reverb_params,
sizeof(context->reverb_params),
FAUDIO_COMMIT_NOW
);
}
void faudio_wave_load(AudioContext *context, AudioSampleWave sample, bool stereo)
{
if (context->source_voice)
{
FAudioVoice_DestroyVoice(context->source_voice);
FAudioVoice_DestroyVoice(context->submix_voice);
FAudioVoice_DestroyVoice(context->mastering_voice);
}
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);
faudio_reverb_set_params(context);
}
void faudio_wave_play(AudioContext *context)
{
FAudioSourceVoice_Stop(context->source_voice, 0, FAUDIO_COMMIT_NOW);
FAudioSourceVoice_FlushSourceBuffers(context->source_voice);
FAudioSourceVoice_SubmitSourceBuffer(context->source_voice, &context->buffer, NULL);
FAudioSourceVoice_Start(context->source_voice, 0, FAUDIO_COMMIT_NOW);
}
void faudio_wave_stop(AudioContext *context)
{
FAudioSourceVoice_Stop(context->source_voice, FAUDIO_PLAY_TAILS, FAUDIO_COMMIT_NOW);
}
void faudio_effect_change(AudioContext *context, bool enabled, ReverbParameters *params)
{
if (context->reverb_enabled && !enabled)
{
FAudioVoice_DisableEffect(
context->voices[context->effect_on_voice],
0,
FAUDIO_COMMIT_NOW
);
context->reverb_enabled = enabled;
}
else if (!context->reverb_enabled && enabled)
{
FAudioVoice_EnableEffect(
context->voices[context->effect_on_voice],
0,
FAUDIO_COMMIT_NOW
);
context->reverb_enabled = enabled;
}
context->reverb_params = *params;
faudio_reverb_set_params(context);
}
AudioContext *faudio_create_context(bool output_5p1, AudioVoiceType effect_on_voice)
{
// setup function pointers
audio_destroy_context = faudio_destroy_context;
audio_create_voice = faudio_create_voice;
audio_wave_load = faudio_wave_load;
audio_wave_play = faudio_wave_play;
audio_wave_stop = faudio_wave_stop;
audio_effect_change = faudio_effect_change;
// create Faudio object
FAudio *faudio;
uint32_t hr = FAudioCreate(&faudio, 0, FAUDIO_DEFAULT_PROCESSOR);
if (hr != 0)
{
return NULL;
}
// return a context object
AudioContext *context = new AudioContext();
context->faudio = faudio;
context->output_5p1 = output_5p1;
context->effect_on_voice = effect_on_voice;
context->source_voice = NULL;
context->submix_voice = NULL;
context->mastering_voice = NULL;
context->wav_samples = NULL;
SDL_zero(context->reverb_params);
context->reverb_enabled = false;
// load the first wave
audio_wave_load(context, (AudioSampleWave) 0, false);
return context;
}