First of all, great example and it almost works! Many thanks Minus_Kelvin, that example really helped me to integrate my audio needs… at least partially. I had this done previously using GeneratePCMData but latency was huge (>300ms), and the approach with QueueAudio is much more elegant and latency is acceptable (23ms).
However, there are some problems (UE 4.14):
- When PlaySineWaveFrequency is started in BeginPlay event it works correctly in PIE, but in a standalone game GenerateData is called only few times and then calling stops. Buffers are still being played, but garbage/uninitialised data samples are heard. The MySoundWaveProcedural is still valid (checked using IsValidLowLevel method) and attached and plays, just the GenerateData is not called thus giving garbage sound output.
A crude hack is to fire PlaySineWaveFrequency slightly later after BeginPlay (~2 seconds was enough) using timers or TickComponent and then it is OK. It seems something is being GC’ed or cleaned up a while after BeginPlay event that stops GenerateData calls. And that happens only during standalone play. Is this correct behaviour, maybe I’m just doing something wrong?
- I’m not able to make it working with stereo data buffers. Simple code changes for stereo gives strange clicks and it seems the GenerateData is not called often enough and buffer underruns.
// in constructor, two channels
NumChannels = 2;
// two oscilators
SineOsc1.SetFrequency(440.0f);
SineOsc2.SetFrequency(880.0f);
// then in GenerateData:
const int32 QueuedSamples = GetAvailableAudioByteCount() / (sizeof(int16)*2); // *2 for stereo
const int32 SamplesNeeded = SamplesRequested - QueuedSamples;
SampleData.Reset(SamplesNeeded);
for (int32 i = 0; i < SamplesNeeded; ++i)
{
// left channel
float SampleValueFloat = SineOsc1.NextSample();
int16 SampleValue = (int16)(32767.0f * SampleValueFloat);
SampleData.Add(SampleValue);
// right channel
SampleValueFloat = SineOsc2.NextSample();
SampleValue = (int16)(32767.0f * SampleValueFloat);
SampleData.Add(SampleValue);
}
// Now call the audio queue to queue up some data
InProceduralWave->QueueAudio((uint8*)SampleData.GetData(), SamplesNeeded * (sizeof(int16)*2)); // note change, *2 for stereo
What I’m doing wrong here?
And finally, I have one serious comment. Why in the hell this topic has completely mismatched topic? I mean seriously, I spent long time to dig this out and I’ve found this thread just by luck! First of all this example with SineOsc should be included in the documentation…
Thanks