实验性:此 API 为实验性功能,未来可能会发生更改或删除。
AudioSampleProvider
UnityEngine.Experimental.Audio 中的类
/
实现于:UnityEngine.AudioModule
建议更改
成功!
感谢您帮助我们提高 Unity 文档的质量。虽然我们无法接受所有提交的内容,但我们确实会阅读用户提出的每个建议更改,并在适用情况下进行更新。
关闭
提交失败
由于某种原因,您的建议更改无法提交。请<a>稍后再试</a>。感谢您抽出时间帮助我们提高 Unity 文档的质量。
关闭
描述
提供对 Unity 对象(如 VideoPlayer)生成的音频样本的访问权限。
using UnityEngine;
using Unity.Collections;
using UnityEngine.Experimental.Video;
using UnityEngine.Experimental.Audio;
using UnityEngine.Video;
public class ManagedAudioOutput : MonoBehaviour
{
AudioSampleProvider provider;
void Start()
{
VideoPlayer vp = GetComponent<VideoPlayer>();
vp.audioOutputMode = VideoAudioOutputMode.APIOnly;
vp.prepareCompleted += Prepared;
vp.Prepare();
}
void Prepared(VideoPlayer vp)
{
provider = vp.GetAudioSampleProvider(0);
provider.sampleFramesAvailable += SampleFramesAvailable;
provider.enableSampleFramesAvailableEvents = true;
provider.freeSampleFrameCountLowThreshold = provider.maxSampleFrameCount / 4;
vp.Play();
}
void SampleFramesAvailable(AudioSampleProvider provider, uint sampleFrameCount)
{
using (NativeArray<float> buffer = new NativeArray<float>(
(int)sampleFrameCount * provider.channelCount, Allocator.Temp))
{
var sfCount = provider.ConsumeSampleFrames(buffer);
Debug.LogFormat("SetupSoftwareAudioOut.Available got {0} sample frames.", sfCount);
// Do something with the samples here...
}
}
}
以下是如何从 C++ 访问样本的示例。设置必须在 C# 中完成,然后 Unity 的核心和本机插件可以相互调用,而无需通过托管代码。
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Experimental.Video;
using UnityEngine.Experimental.Audio;
using UnityEngine.Video;
public class NativeAudioOutput : MonoBehaviour
{
AudioSampleProvider provider;
AudioSampleProvider.SampleFramesEventNativeFunction sampleFramesAvailableNativeHandler =
SampleFramesAvailable;
void Start()
{
VideoPlayer vp = GetComponent<VideoPlayer>();
vp.audioOutputMode = VideoAudioOutputMode.APIOnly;
vp.prepareCompleted += Prepared;
vp.Prepare();
}
void Prepared(VideoPlayer vp)
{
provider = vp.GetAudioSampleProvider(0);
provider.freeSampleFrameCountLowThreshold = provider.maxSampleFrameCount - 1024;
SetConsumeSampleFramesFunction(
AudioSampleProvider.consumeSampleFramesNativeFunction, provider.id,
provider.channelCount, provider.sampleRate);
provider.SetSampleFramesAvailableNativeHandler(
sampleFramesAvailableNativeHandler, (IntPtr)0);
vp.Play();
}
private const string pluginName =
#if UNITY_IPHONE
"__Internal"
#else
"NativeAudioOutputPlugin"
#endif
;
[DllImport(pluginName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern void SetConsumeSampleFramesFunction(
AudioSampleProvider.ConsumeSampleFramesNativeFunction cb, uint id, ushort channelCount, uint sampleRate);
[AOT.MonoPInvokeCallback(typeof(AudioSampleProvider.SampleFramesEventNativeFunction))]
[DllImport(pluginName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern void SampleFramesAvailable(IntPtr userData, uint id, uint sampleFrameCount);
}
#include <algorithm>
#include <stdint.h>
typedef uint32_t(__cdecl *ConsumeSampleFramesFunction)(
uint32_t providerId, float* interleavedSampleFrames, uint32_t sampleFrameCount);
ConsumeSampleFramesFunction ConsumeSampleFrames = NULL;
uint32_t providerId = -1;
float* buffer = NULL;
uint32_t bufferSampleFrameCount = 0;
uint32_t availableSampleFrameCount = 0;
extern "C" __cdecl void SetConsumeSampleFramesFunction(
ConsumeSampleFramesFunction function, uint32_t id, uint16_t channelCount, uint32_t sampleRate)
{
ConsumeSampleFrames = function;
providerId = id;
delete[] buffer;
buffer = new float[channelCount * sampleRate]; // 1s worth of sample frames.
bufferSampleFrameCount = sampleRate;
}
extern "C" __cdecl void SampleFramesAvailable(void* userData, uint32_t id, uint32_t sampleFrameCount)
{
if (ConsumeSampleFrames == NULL)
return;
// We consume the sample frames from the handler that tells us that there are some available.
// But we could also invoke this regularly from another thread, for example the thread providing
// samples to an audio device.
const uint32_t consumedSampleFrameCount = ConsumeSampleFrames(
providerId, buffer, std::min(bufferSampleFrameCount, sampleFrameCount));
// Do something with the samples here...
}