载入中...
搜索中...
未找到
AudioZone.cpp
浏览该文件的文档.
1#include "audio/AudioZone.h"
2#include "audio/Source.h"
3
4#include <algorithm>
5#include <cmath>
6
7namespace eve::audio {
8namespace {
9bool finiteItem(const AudioZoneItem& v) { return std::isfinite(v.volume)&&std::isfinite(v.fadeInTime)&&
10 std::isfinite(v.fadeOutTime)&&std::isfinite(v.duration)&&v.volume>=0&&v.fadeInTime>=0&&v.fadeOutTime>=0&&v.duration>=0; }
11float unit(std::uint32_t seed) { seed=seed*1664525u+1013904223u; return float(seed>>8u)*(1.f/16777216.f); }
12}
14 if(!finiteItem(item)) return Result<int>::failure(
15 Diagnostic::error(DiagnosticCode::InvalidArgument,"audio-zone track values must be finite and non-negative","audio.zone"));
16 items_.push_back(item); return Result<int>::success(itemCount()-1);
17}
18const AudioZoneItem* AudioZoneProfile::itemAt(int index) const noexcept {
19 return index>=0&&index<itemCount()?&items_[static_cast<std::size_t>(index)]:nullptr;
20}
22 float px,float py,float pz,float master,std::uint32_t seed) {
23 if(!std::isfinite(now)||!std::isfinite(px)||!std::isfinite(py)||!std::isfinite(pz)||!std::isfinite(master)||
24 !std::isfinite(p.x)||!std::isfinite(p.y)||!std::isfinite(p.z)||!std::isfinite(p.radius)||
25 !std::isfinite(p.minimumBreakTime)||!std::isfinite(p.maximumBreakTime)||!std::isfinite(p.deactivationTime)||
26 now<0||master<0||p.radius<0||p.minimumBreakTime<0||p.maximumBreakTime<p.minimumBreakTime||p.deactivationTime<0)
28 Diagnostic::error(DiagnosticCode::InvalidArgument,"audio-zone inputs must be finite and ranges valid","audio.zone"));
30 const float dx=p.x-px,dy=p.y-py,dz=p.z-pz;
31 const bool inRange=p.global||dx*dx+dy*dy+dz*dz<=p.radius*p.radius;
32 if(inRange) {
33 if(next.phase!=AudioZonePhase::Active) { next.phase=AudioZonePhase::Active; next.deactivateAt=0; }
34 } else if(next.phase==AudioZonePhase::Active) {
35 next.phase=AudioZonePhase::BecomingInactive; next.deactivateAt=now+p.deactivationTime;
36 } else if(next.phase==AudioZonePhase::BecomingInactive && now>next.deactivateAt) {
37 next.phase=AudioZonePhase::Inactive; next.playing=false; out.stop=true; next.selectedTrack=-1;
38 }
39 if(next.phase==AudioZonePhase::Active && p.itemCount()>0 && !next.playing && now>next.nextTrackStarts) {
40 int chosen=std::min(p.itemCount()-1,int(unit(seed)*p.itemCount()));
41 if(chosen==next.selectedTrack && p.itemCount()>1) chosen=(chosen+1)%p.itemCount();
42 const auto* item=p.itemAt(chosen); next.selectedTrack=chosen; next.playing=true; next.trackStarted=now;
43 next.fadeInEnds=now+item->fadeInTime; next.fadeOutBegins=now+item->duration-item->fadeOutTime;
44 next.fadeOutEnds=now+item->duration; next.nextTrackStarts=next.fadeOutEnds+
45 p.minimumBreakTime+(p.maximumBreakTime-p.minimumBreakTime)*unit(seed^0x9e3779b9u);
46 out.play=true; out.trackIndex=chosen;
47 }
48 if(next.playing) {
49 const auto* item=p.itemAt(next.selectedTrack); float volume=item?item->volume:0.f;
50 if(now<next.fadeInEnds && next.fadeInEnds>next.trackStarted)
51 volume=item->volume*(now-next.trackStarted)/(next.fadeInEnds-next.trackStarted);
52 else if(now>=next.fadeOutBegins && now<next.fadeOutEnds && next.fadeOutEnds>next.fadeOutBegins)
53 volume=item->volume*(next.fadeOutEnds-now)/(next.fadeOutEnds-next.fadeOutBegins);
54 else if(now>=next.fadeOutEnds) { volume=0; next.playing=false; out.stop=true; }
55 out.volume=std::min(volume,master);
56 }
58}
60 if(!source||!std::isfinite(output.volume)||output.volume<0.f)
62 Diagnostic::error(DiagnosticCode::InvalidArgument,"audio-zone output requires a source and finite non-negative volume","audio.zone"));
63 source->setVolume(output.volume);
64 if(output.stop) source->stop();
65 if(output.play) source->play();
66 return Result<void>::success();
67}
68} // namespace eve::audio
std::string output
double volume
float py
float pz
glm::vec4 p[6]
float v
std::vector< Colorf > px
std::uint32_t seed
Definition PointSet.cpp:807
float dz
float dy
float dx
TacticalUnit * unit
uint32_t index
const UnitySourceAsset & source
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Caller-owned Pcg audio-zone configuration and track list.
Definition AudioZone.h:18
int itemCount() const noexcept
Definition AudioZone.h:24
const AudioZoneItem * itemAt(int index) const noexcept
Borrow track data.
Definition AudioZone.cpp:18
Result< int > addItem(const AudioZoneItem &item)
Add one validated track profile.
Definition AudioZone.cpp:13
A playable audio source (static buffer or streaming decoder). Not thread-safe for playback control ex...
Definition Source.h:30
Result< AudioZoneOutput > evaluateAudioZone(const AudioZoneProfile &p, AudioZoneState &state, float now, float px, float py, float pz, float master, std::uint32_t seed)
Evaluate PcgAudioManager/PcgAudioZone for one explicit time and player observation.
Definition AudioZone.cpp:21
Result< void > applyAudioZoneOutput(Source *source, const AudioZoneOutput &output)
Apply one evaluated command to the caller-selected track Source without retaining it.
Definition AudioZone.cpp:59
One Pcg audio-zone track timing and gain profile.
Definition AudioZone.h:14
Commands to apply to a caller-owned audio Source.
Definition AudioZone.h:43
Persistent playback state owned by the caller.
Definition AudioZone.h:36