Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel wird beschrieben, wie Sie eine Windows-Runtime Komponente erstellen, die die IBasicAudioEffect-Schnittstelle implementiert, um benutzerdefinierte Effekte für Audiostreams zu erstellen. Sie können benutzerdefinierte Effekte mit AudioGraph, MediaCapture und MediaComposition verwenden.
Note
Die IBasicAudioEffect Schnittstelle ist eine Windows-Runtime-API im Windows.Media.Effects Namespace. Diese APIs funktionieren in WinUI 3-Desktop-Apps auf die gleiche Weise wie in UWP. Der Hauptunterschied besteht darin, wie Sie das Projekt einrichten und auf die Effektkomponente verweisen.
Hinzufügen einer Windows-Runtime Komponente für den Audioeffekt
Fügen Sie in Visual Studio Ihrer WinUI 3-Lösung ein Windows-Runtime Component -Projekt (C#) hinzu:
- Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf Ihre Lösung, und wählen Sie"Neue Project> aus.
- Wählen Sie die Projektvorlage Windows-Runtime Komponente aus.
- Benennen Sie das Projekt "AudioEffectComponent".
- Fügen Sie diesem Komponentenprojekt einen Projektverweis aus Ihrer WinUI 3-Haupt-App hinzu.
- Benennen Sie die Standardklassendatei in ExampleAudioEffect.cs um.
Implementieren der IBasicAudioEffect-Schnittstelle
Ihr Audioeffekt muss alle Methoden und Eigenschaften der IBasicAudioEffect-Schnittstelle implementieren.
using System.Collections.Generic;
using Windows.Media;
using Windows.Media.Effects;
using Windows.Media.MediaProperties;
using Windows.Foundation.Collections;
namespace AudioEffectComponent;
public sealed class ExampleAudioEffect : IBasicAudioEffect
{
private AudioEncodingProperties _currentEncodingProperties;
private IPropertySet _propertySet;
private float _echoDelay = 0.5f; // delay in seconds
private float _echoMix = 0.5f; // mix level (0-1)
public bool UseInputFrameForOutput => true;
public IReadOnlyList<AudioEncodingProperties> SupportedEncodingProperties
{
get
{
var supportedProperties = new List<AudioEncodingProperties>();
AudioEncodingProperties encodingProps1 =
AudioEncodingProperties.CreatePcm(44100, 1, 32);
encodingProps1.Subtype = MediaEncodingSubtypes.Float;
supportedProperties.Add(encodingProps1);
AudioEncodingProperties encodingProps2 =
AudioEncodingProperties.CreatePcm(48000, 1, 32);
encodingProps2.Subtype = MediaEncodingSubtypes.Float;
supportedProperties.Add(encodingProps2);
return supportedProperties;
}
}
public void SetEncodingProperties(
AudioEncodingProperties encodingProperties)
{
_currentEncodingProperties = encodingProperties;
}
public void SetProperties(IPropertySet configuration)
{
_propertySet = configuration;
// Read custom properties if provided
if (configuration != null &&
configuration.TryGetValue("EchoDelay", out object delay))
{
_echoDelay = (float)delay;
}
if (configuration != null &&
configuration.TryGetValue("EchoMix", out object mix))
{
_echoMix = (float)mix;
}
}
public void ProcessFrame(ProcessAudioFrameContext context)
{
// Audio processing logic goes here.
// See the echo effect example below.
}
public void Close(MediaEffectClosedReason reason)
{
// Clean up resources
}
public void DiscardQueuedFrames()
{
// Discard any cached frames
}
}
Erstellen eines Echoeffekts
Das folgende Beispiel zeigt eine ProcessFrame Implementierung, die einen Echoeffekt erstellt. Der Effekt speichert vorherige Audiodaten in einem Puffer und mischt sie nach einer konfigurierbaren Verzögerung mit den aktuellen Audiodaten.
Um auf den rohen Audiopuffer zuzugreifen, benötigen Sie die COM-Schnittstelle "IMemoryBufferByteAccess ". Fügen Sie die folgende Definition in Ihrem Effektnamespace hinzu:
using System.Runtime.InteropServices;
[ComImport]
[System.Runtime.InteropServices.Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
void GetBuffer(out byte* buffer, out uint capacity);
}
Important
Diese Technik greift auf einen systemeigenen, nicht verwalteten Audiopuffer zu. Sie müssen <AllowUnsafeBlocks>true</AllowUnsafeBlocks> zur Datei .csproj Ihres Projekts hinzufügen, um unsicheren Code zu aktivieren.
private float[] _echoBuffer;
private int _echoBufferPosition;
private float _echoDelay = 0.5f; // delay in seconds
private float _echoMix = 0.5f; // mix level (0-1)
private Windows.Media.MediaProperties.AudioEncodingProperties _currentEncodingProperties;
public unsafe void ProcessFrame(ProcessAudioFrameContext context)
{
AudioFrame inputFrame = context.InputFrame;
using (AudioBuffer inputBuffer =
inputFrame.LockBuffer(AudioBufferAccessMode.ReadWrite))
using (IMemoryBufferReference inputReference =
inputBuffer.CreateReference())
{
byte* dataInBytes;
uint capacityInBytes;
((IMemoryBufferByteAccess)inputReference).GetBuffer(
out dataInBytes, out capacityInBytes);
float* dataInFloat = (float*)dataInBytes;
int dataInFloatLength =
(int)capacityInBytes / sizeof(float);
// Initialize echo buffer on first call
if (_echoBuffer == null)
{
int delaySamples = (int)(
_currentEncodingProperties.SampleRate * _echoDelay);
_echoBuffer = new float[delaySamples];
}
for (int i = 0; i < dataInFloatLength; i++)
{
float input = dataInFloat[i];
float echo = _echoBuffer[_echoBufferPosition];
// Mix the original signal with the echo
dataInFloat[i] = input + (echo * _echoMix);
// Store the current sample in the echo buffer
_echoBuffer[_echoBufferPosition] = input;
_echoBufferPosition =
(_echoBufferPosition + 1) % _echoBuffer.Length;
}
}
}
Hinzufügen des Effekts zu einem Audiodiagramm
Um den benutzerdefinierten Effekt mit einem AudioGraph zu verwenden, erstellen Sie eine Instanz der Effektdefinition, und fügen Sie ihn einem Knoten hinzu:
using Windows.Media.Audio;
using Windows.Media.Effects;
var effectDefinition = new AudioEffectDefinition(
typeof(AudioEffectComponent.ExampleAudioEffect).FullName);
audioFileInputNode.EffectDefinitions.Add(effectDefinition);
Konfiguration an den Effekt übergeben
Sie können Konfigurationswerte mithilfe eines PropertySets an Ihren Effekt übergeben:
var properties = new PropertySet();
properties["EchoDelay"] = 0.3f;
properties["EchoMix"] = 0.6f;
var effectDefinition = new AudioEffectDefinition(
typeof(AudioEffectComponent.ExampleAudioEffect).FullName,
properties);
Lesen Sie in der SetProperties-Methode Ihres Effekts (zuvor gezeigt) diese Werte aus der Eigenschaftengruppe, um den Effekt zur Laufzeit zu konfigurieren.
Hinzufügen des Effekts zu "MediaCapture"
Sie können den benutzerdefinierten Audioeffekt auch einem MediaCapture-Audiostream hinzufügen:
var effectDefinition = new AudioEffectDefinition(
typeof(AudioEffectComponent.ExampleAudioEffect).FullName);
await _mediaCapture.AddAudioEffectAsync(effectDefinition);
Verwandte Inhalte
Windows developer