Я разрабатываю аудио приложение в C# и UWP, используя AudioGraph API. Мои настройки AudioGraph следующие: AudioFileInputNode -> AudioSubmixNode -> AudioDeviceOutputNode.
Я добавил собственный эффект эха на AudioSubmixNode. Если я играю AudioFileInputNode, я слышу эхо. Но когда воспроизведение AudioFileInputNode заканчивается, эхо-звук жестоко прекращается. Я хотел бы, чтобы это прекратилось постепенно только через несколько секунд. Если я использую EchoEffectDefinition из AudioGraph API, звук эха не прекращается после завершения воспроизведения семпла.
Я не знаю, возникает ли проблема из-за моей реализации эффекта или это странное поведение AudioGraph API ... Поведение идентично в образце "AudioCreation" в SDK, сценарий 6.
Вот моя реализация пользовательских эффектов:
public sealed class AudioEchoEffect : IBasicAudioEffect
{
public AudioEchoEffect()
{
}
private readonly AudioEncodingProperties[] _supportedEncodingProperties = new AudioEncodingProperties[]
{
AudioEncodingProperties.CreatePcm(44100, 1, 32),
AudioEncodingProperties.CreatePcm(48000, 1, 32),
};
private AudioEncodingProperties _currentEncodingProperties;
private IPropertySet _propertySet;
private readonly Queue<float> _echoBuffer = new Queue<float>(100000);
private int _delaySamplesCount;
private float Delay
{
get
{
if (_propertySet != null && _propertySet.TryGetValue("Delay", out object val))
{
return (float)val;
}
return 500.0f;
}
}
private float Feedback
{
get
{
if (_propertySet != null && _propertySet.TryGetValue("Feedback", out object val))
{
return (float)val;
}
return 0.5f;
}
}
private float Mix
{
get
{
if (_propertySet != null && _propertySet.TryGetValue("Mix", out object val))
{
return (float)val;
}
return 0.5f;
}
}
public bool UseInputFrameForOutput { get { return true; } }
public IReadOnlyList<AudioEncodingProperties> SupportedEncodingProperties { get { return _supportedEncodingProperties; } }
public void SetProperties(IPropertySet configuration)
{
_propertySet = configuration;
}
public void SetEncodingProperties(AudioEncodingProperties encodingProperties)
{
_currentEncodingProperties = encodingProperties;
// compute the number of samples for the delay
_delaySamplesCount = (int)MathF.Round((this.Delay / 1000.0f) * encodingProperties.SampleRate);
// fill empty samples in the buffer according to the delay
for (int i = 0; i < _delaySamplesCount; i++)
{
_echoBuffer.Enqueue(0.0f);
}
}
unsafe public void ProcessFrame(ProcessAudioFrameContext context)
{
AudioFrame frame = context.InputFrame;
using (AudioBuffer buffer = frame.LockBuffer(AudioBufferAccessMode.ReadWrite))
using (IMemoryBufferReference reference = buffer.CreateReference())
{
((IMemoryBufferByteAccess)reference).GetBuffer(out byte* dataInBytes, out uint capacity);
float* dataInFloat = (float*)dataInBytes;
int dataInFloatLength = (int)buffer.Length / sizeof(float);
// read parameters once
float currentWet = this.Mix;
float currentDry = 1.0f - currentWet;
float currentFeedback = this.Feedback;
// Process audio data
float sample, echoSample, outSample;
for (int i = 0; i < dataInFloatLength; i++)
{
// read values
sample = dataInFloat[i];
echoSample = _echoBuffer.Dequeue();
// compute output sample
outSample = (currentDry * sample) + (currentWet * echoSample);
dataInFloat[i] = outSample;
// compute delay sample
echoSample = sample + (currentFeedback * echoSample);
_echoBuffer.Enqueue(echoSample);
}
}
}
public void Close(MediaEffectClosedReason reason)
{
}
public void DiscardQueuedFrames()
{
// reset the delay buffer
_echoBuffer.Clear();
for (int i = 0; i < _delaySamplesCount; i++)
{
_echoBuffer.Enqueue(0.0f);
}
}
}
РЕДАКТИРОВАТЬ: я изменил свой звуковой эффект для микширования входных выборок с синусоидой. Метод эффекта ProcessFrame работает непрерывно до и после воспроизведения семпла (когда эффект активен). Таким образом, синусоида должна быть услышана до и после воспроизведения сэмпла. Но AudioGraph API, кажется, игнорирует вывод эффекта, когда нет активного воспроизведения ...
Вот снимок экрана аудио выхода:
Итак, мой вопрос: как встроенный EchoEffectDefinition может выводить звук после завершения воспроизведения? Доступ к исходному коду EchoEffectDefinition очень помог бы ...