SHA256
Add Chunked Audio Clip Store
This commit is contained in:
1 parent
4e556a4632
commit
0a12c12ff5
7 files changed
+1412
No files matched your search
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ADOFAIRenderer.Util.Audio.Clip;
|
||||
|
||||
/// <summary>
|
||||
/// Copies a Unity <see cref="AudioClip"/> into memory for clips without a file on disk
|
||||
/// (built-in hit sounds from Resources, official/DLC level audio).
|
||||
/// <see cref="AudioClip.GetData(float[], int)"/> runs on the main thread only, so the whole clip is copied once on the main thread
|
||||
/// and the decoder thread reads the copy through a <see cref="MemoryPCMReader"/>.
|
||||
/// Streaming clips (<see cref="AudioClipLoadType.Streaming"/>) are rejected because GetData does not read them.
|
||||
/// Reference: https://docs.unity3d.com/ScriptReference/AudioClip.GetData.html
|
||||
/// </summary>
|
||||
internal static class UnityClipLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// Copies <paramref name="clip"/> in blocks of <see cref="AudioClipSource.ChunkFloats"/> floats or less
|
||||
/// (FramesPerBlock = ChunkFloats / channels frames per GetData call). Main thread only.
|
||||
/// Block memory is counted in <paramref name="store"/> and released block by block as the decoder thread reads it.
|
||||
/// </summary>
|
||||
public static MemoryPCMReader Load(AudioClip clip, AudioClipStore store)
|
||||
{
|
||||
if (!clip) throw new ArgumentNullException(nameof(clip));
|
||||
if (clip.loadType == AudioClipLoadType.Streaming)
|
||||
throw new NotSupportedException($"AudioClip '{clip.name}' is a streaming clip; GetData cannot read it.");
|
||||
|
||||
if (clip.loadState == AudioDataLoadState.Unloaded)
|
||||
clip.LoadAudioData();
|
||||
|
||||
var channels = clip.channels;
|
||||
var totalFrames = (long)clip.samples;
|
||||
var framesPerBlock = AudioClipSource.ChunkFloats / channels;
|
||||
var blocks = new List<float[]>();
|
||||
try
|
||||
{
|
||||
for (long start = 0; start < totalFrames; start += framesPerBlock)
|
||||
{
|
||||
var frames = (int)Math.Min(framesPerBlock, totalFrames - start);
|
||||
var block = store.AllocateExactArray(frames * channels);
|
||||
blocks.Add(block);
|
||||
// GetData fills the whole array; the offset is in frames (samples per channel).
|
||||
if (!clip.GetData(block, (int)start))
|
||||
throw new InvalidOperationException($"AudioClip.GetData failed for '{clip.name}' at frame {start} (load state {clip.loadState}).");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
foreach (var block in blocks) store.FreeExactArray(block);
|
||||
throw;
|
||||
}
|
||||
|
||||
return new MemoryPCMReader(blocks, framesPerBlock, channels, clip.frequency, totalFrames, store.FreeExactArray);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user