Описание
Предоставляет доступ к образцам аудио, созданным объектами Unity, такими как VideoPlayer.
Этот класс предназначен для использования вне основного потока, и реализация предполагает, что один потребитель одновременно вызывает AudioSampleProvider.ConsumeSampleFrames. Доступ к аудиоданным можно получить как из C#, так и из C++, в зависимости от того, что нужно делать с этими данными.
Ниже приведен пример доступа к примерам из C# с помощью метода доступа, полученного из 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 buffer = new NativeArray(
(int)sampleFrameCount * provider.channelCount, Allocator.Temp))
{
var sfCount = provider.ConsumeSampleFrames(buffer);
Debug.LogFormat("SetupSoftwareAudioOut.Available got {0} sample frames.", sfCount);
// Сделаем что-нибудь с образцами..
}
}
}
Ниже приведен пример доступа к примерам из 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);
}
А вот и подключаемый модуль C++:
#include
#include
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.
// Но мы также можем регулярно вызывать это из другого потока, например из потока, предоставляющего
// образцы на аудиоустройство.
const uint32_t consumedSampleFrameCount = ConsumeSampleFrames(
providerId, buffer, std::min(bufferSampleFrameCount, sampleFrameCount));
// Сделаем что-нибудь с образцами.
}
Статические Свойства
consumeSampleFramesNativeFunction | Указатель на встроенную функцию, обеспечивающую доступ к кадрам аудиосэмплов. . |
Свойства
availableSampleFrameCount | Количество выборочных кадров, доступных для использования с помощью AudioSampleProvider.ConsumeSampleFrames. |
channelCount | Количество аудиоканалов на образец кадра . |
enableSampleFramesAvailableEvents | Включает события AudioSampleProvider.sampleFramesAvailable. |
enableSilencePadding | Если установлено значение true, буферы, создаваемые ConsumeSampleFrames, будут дополняться при тишине, если их меньше, чем запрошено. В противном случае дополнительные кадры выборки в буфере останутся без изменений. |
freeSampleFrameCount | Количество фреймов сэмплов, которые еще могут быть записаны производителем семплов до переполнения. |
freeSampleFrameCountLowThreshold | Затем количество бесплатных образцов падает ниже этого порога, генерируется событие AudioSampleProvider.sampleFramesAvailable и связанный с ним собственный код. |
id | Уникальный идентификатор для этого экземпляра. |
maxSampleFrameCount | Максимальное количество выборочных кадров, которое может быть накоплено во внутреннем буфере до того, как возникнет событие переполнения. |
owner | Объект, откуда пришел этот провайдер. |
sampleRate | Ожидаемая скорость воспроизведения образцов кадров, созданных этим классом. |
trackIndex | Индекс дорожки в объекте, создавшем этот провайдер. |
valid | True - если объект действителен. |
Публичные Методы
ClearSampleFramesAvailableNativeHandler | Очищает набор собственных обработчиков с помощью AudioSampleProvider.SetSampleFramesAvailableNativeHandler. |
ClearSampleFramesOverflowNativeHandler | Очищает собственный набор обработчиков с помощью AudioSampleProvider.SetSampleFramesOverflowNativeHandler. |
ConsumeSampleFrames | Потребляйте образцы кадров из внутреннего буфера. |
Dispose | Высвобождает внутренние ресурсы. Унаследовано от IDisposable. |
SetSampleFramesAvailableNativeHandler | Устанавливает собственный обработчик событий для событий, генерируемых, когда количество доступных выборочных кадров превышает пороговое значение. |
SetSampleFramesOverflowNativeHandler | Устанавливает собственный обработчик событий для событий, генерируемых при переполнении внутреннего буфера выборочного кадра. |
События
sampleFramesAvailable | Вызывается, когда количество доступных выборочных кадров превышает пороговое значение, установленное с помощью AudioSampleProvider.freeSampleFrameCountLowThreshold. |
sampleFramesOverflow | Вызывается, когда количество доступных выборочных кадров превышает максимальное значение, которое помещается во внутренний буфер. |
Делегаты
ConsumeSampleFramesNativeFunction | Тип, представляющий собственный указатель функции для использования выборочных кадров. |
SampleFramesEventNativeFunction | Тип, представляющий собственный указатель функции для обработки событий образца кадра. |
SampleFramesHandler | Делегат для выборочных событий кадра. |