您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

196 行
6.0 KiB

// #define SEQUENCER_PARANOIA
using System.Collections.Generic;
using UnityEngine;
namespace AxelF {
public enum CueStatus {
Playing,
Stopped,
Repeating
}
public struct Cue {
public AudioEmitter emitter;
public int index;
public uint cueHandle;
public uint keyHandle;
public int lastFrame;
public float modVolume;
public float currentTime;
public float totalTime;
public int repeatIndex;
public int repeatCount;
public bool looping;
bool UpdateModVolume(out float vol, float dt) {
float v = 1f;
bool set = false;
if (emitter.zone) {
if (emitter.zone.hasPeripheralFade) {
v *= emitter.zone.volumeInfluence;
set = true;
}
if (emitter.zone.isVolumeExcluded) {
v *= 1f - emitter.zone.volumeExclusion;
set = true;
}
}
if (emitter.isModulated) {
var c = emitter.modulation.custom;
if (c != null) {
v *= c.GetCustomModulation();
set = true;
} else {
float t = currentTime / emitter.modulation.period * (Mathf.PI * 2f);
float x = 1f - (Mathf.Cos(t) + 1f) * 0.5f;
float y = emitter.modulation.volume.GetRangedValue(x);
if (emitter.modulation.inverted)
y = 1f - y;
v *= y;
set = true;
}
}
vol = modVolume = Mathf.Lerp(modVolume, v, 2f * dt);
return set;
}
public CueStatus Update(float dt) {
var s = CueStatus.Playing;
if (lastFrame == Time.frameCount)
return s;
lastFrame = Time.frameCount;
if (!emitter.paused) {
currentTime += dt;
if (totalTime > 0f && currentTime >= totalTime) {
s = CueStatus.Stopped;
if (repeatCount < 0 || ++repeatIndex < repeatCount)
s = CueStatus.Repeating;
#if SEQUENCER_PARANOIA
Debug.LogFormat(
Time.frameCount.ToString("X4") +
" Cue.Update: {0} {1} {2} {3}/{4} {5}/{6}",
emitter.name, emitter.patches[index] ? emitter.patches[index].name : "???",
s, currentTime, totalTime, repeatIndex, repeatCount);
#endif
}
float v;
if (UpdateModVolume(out v, dt))
if (keyHandle != 0)
Synthesizer.SetModVolume(keyHandle, v);
}
return s;
}
public bool KeyOn() {
#if SEQUENCER_PARANOIA
Debug.LogFormat(
Time.frameCount.ToString("X4") +
" Sequencer.KeyOn: {0} {1}",
emitter.name, emitter.patches[index] ? emitter.patches[index].name : "???");
#endif
if (Randomizer.zeroToOne <= emitter.randomization.chance) {
if (emitter.auxiliary.source) {
if (!emitter.patches[index].hasTimings)
Synthesizer.KeyOn(emitter.patches[index], emitter.auxiliary.source, 0f, emitter.volume);
} else {
var t =
emitter.attachment.useListenerTransform ? Heartbeat.listenerTransform :
emitter.attachment.transform ? emitter.attachment.transform :
emitter.transform;
float r = emitter.randomization.distance.GetRandomValue();
var p = Vector3.zero;
if (!Mathf.Approximately(r, 0f)) {
float a = Randomizer.plusMinusOne * Mathf.PI * 2f;
r *= emitter.zone.radius;
p.x = Mathf.Sin(a) * r;
p.z = Mathf.Cos(a) * r;
}
float v;
UpdateModVolume(out v, 1000f);
keyHandle = Synthesizer.KeyOn(
out looping, emitter.patches[index], t, p, 0f, emitter.volume, v);
}
}
return emitter.patches[index].GetCueInfo(out totalTime, out repeatCount) || looping;
}
public void KeyOff(float release, EnvelopeMode mode) {
#if SEQUENCER_PARANOIA
Debug.LogFormat(
Time.frameCount.ToString("X4") +
" Sequencer.KeyOff: {0} {1} : {2} {3}",
emitter.name, emitter.patches[index] ? emitter.patches[index].name : "???",
release, mode);
#endif
if (keyHandle != 0)
Synthesizer.KeyOff(keyHandle, release, mode);
Reset();
}
public void Reset() {
keyHandle = 0;
currentTime = 0f;
looping = false;
}
}
public static class Sequencer {
public static List<Cue> activeCues0 = new List<Cue>(64);
public static List<Cue> activeCues1 = new List<Cue>(64);
public static void Reset() {
activeCues0.Clear();
activeCues1.Clear();
}
public static uint CueIn(AudioEmitter e, int i) {
var c = new Cue {emitter = e, index = i, cueHandle = Synthesizer.GetNextHandle()};
if (!c.KeyOn())
return 0;
activeCues0.Add(c);
return c.cueHandle;
}
public static void CueOut(uint handle, float release = 0f, EnvelopeMode mode = EnvelopeMode.None) {
for (var x = activeCues0.GetEnumerator(); x.MoveNext();) {
var z = x.Current;
if (z.cueHandle == handle)
z.KeyOff(release, mode);
else
activeCues1.Add(z);
}
Swap(ref activeCues0, ref activeCues1);
activeCues1.Clear();
}
static void Swap<T>(ref List<T> a, ref List<T> b) {
var y = a;
a = b;
b = y;
}
public static void Update(float dt) {
for (var x = activeCues0.GetEnumerator(); x.MoveNext();) {
var z = x.Current;
var s = z.Update(dt);
if (s == CueStatus.Repeating) {
z.Reset();
z.KeyOn();
}
if (s != CueStatus.Stopped)
activeCues1.Add(z);
}
Swap(ref activeCues0, ref activeCues1);
activeCues1.Clear();
}
}
} // AxelF