2using NaughtyAttributes;
6using System.Collections;
7using System.Collections.Generic;
10using Random = UnityEngine.Random;
20 [AddComponentMenu(
"Ryle Radio/Radio Output")]
21 [RequireComponent(typeof(AudioSource))]
43 protected List<RadioTrackPlayer>
players =
new();
63 public List<RadioObserver>
Observers {
get;
private set; } =
new();
68 public Action<float>
OnTune {
get;
set; } =
new(_ => { });
73 public Action
OnInit {
get;
set; } =
new(() => { });
104 get => Mathf.Round(
tune * 10) / 10;
146 List<AudioClip> unloadedClips =
new List<AudioClip>();
151 if (wrapper.TryGetClip(out AudioClip clip))
152 unloadedClips.Add(clip);
156 while (unloadedClips.Count > 0)
159 for (
int i = 0; i < unloadedClips.Count; i++)
162 if (unloadedClips[i].loadState == AudioDataLoadState.Loaded)
165 unloadedClips.Remove(unloadedClips[i]);
221 int indexInData =
Data.TrackIDs.IndexOf(_player.TrackW.id);
224 int indexForNewPlayer =
players.Count;
227 for (
int i = 0; i <
players.Count; i++)
229 if (
Data.TrackIDs.IndexOf(
players[i].TrackW.id) > indexInData)
231 indexForNewPlayer = i;
240 players.Insert(indexForNewPlayer, _player);
281 player.DoDestroy += player =>
293 Debug.LogWarning($
"Can't find track with id {_id} to play as a one-shot!");
321 Debug.LogWarning($
"Can't find track with id {_id} to play as a loop!");
339 bool _createNew =
false,
344 var found =
players.Where(p => p.TrackW.id == _trackID);
347 if (found.Count() > 1)
350 switch (_multiplePlayerSelector)
354 _player = found.Last();
359 _player = found.First();
364 int index =
Random.Range(0, found.Count());
365 _player = found.ElementAt(index);
374 else if (found.Count() > 0)
377 _player = found.First();
412 int monoSampleCount = _data.Length / _channels;
415 for (
int index = 0; index < monoSampleCount; index++)
419 float combinedVolume = 0;
431 combinedVolume += outVolume;
437 int indexWithChannels = index * _channels;
440 for (
int channel = indexWithChannels; channel < indexWithChannels + _channels; channel++)
441 _data[channel] += sample;
A scene component that holds a reference to a RadioData.
RadioData Data
Read-only accessor for data.
RadioData data
The RadioData (aka just radio) that this component is linked to.
A component used to watch for specific happenings on a RadioOutput, e.g: a clip being a certain volum...
string[] AffectedTracks
The tracks selected on this Observer.
void AssignEvents(RadioTrackPlayer _player)
Assigns each event to a RadioTrackPlayer for one of our AffectedTracks. This is called when a new Rad...
The main scene component for a radio that plays it through an AudioSource.
RadioTrackPlayer PlayLoop(string _id)
Plays a track as a loop. A loop restarts when the track ends, then continues to play.
Action< float > OnTune
Event called whenever Tune is changed.
List< RadioObserver > Observers
Every RadioObserver associated with this output.
float Tune01
Tune scaled to [0 - 1], useful for UI
void LocalInit()
Initializes the RadioData- this needs to be separated from Init() as it would be recursive otherwise.
virtual void OnAudioFilterRead(float[] _data, int _channels)
Gets a set of samples from the radio to play from the AudioSource- this preserves the settings on the...
IEnumerator AwaitLoadingThenInit()
Waits for all AudioClips used in this radio to be loaded before initializing the radio....
float Tune
The tune clamped to the full range.
void StartPlayers()
Creates every RadioTrackPlayer that this output needs for playback.
Vector3 cachedPos
The position of this object as of the last frame update. We can't access transform....
float DisplayTune
Tune with limited decimal points- looks better when displayed, more like an actual radio
Action playEvents
Called at the end of every audio cycle so that we don't interrupt threads when manipulating RadioTrac...
override void Init()
Initializes the output itself, and creates all required every required RadioTrackPlayer.
float tune
The current tune value of this output- akin to the frequency of a real radio. Controls what tracks ca...
List< RadioTrackPlayer > players
The players used by this output.
Action OnInit
Event called when this output is finished initializing- mainly useful for WebGL when we use AwaitLoad...
MultiplePlayersSelector
The method by which a RadioTrackPlayer is chosen from this output. Really only matters when you're pl...
@ Oldest
Selects the oldest player.
@ Random
Selects a random player (probably useless but funny to have)
@ Youngest
Selects the youngest player.
void PlayerCreation(RadioTrackPlayer _player)
Sets up and stores a new RadioTrackPlayer and alerts any RadioObserver of its creation.
float baseSampleRate
The normal sample rate of this output, applied to each RadioTrackPlayer.
void ExecOnTune()
Called when tune is modified in the inspector.
bool TryGetPlayer(string _trackID, out RadioTrackPlayer _player, bool _createNew=false, MultiplePlayersSelector _multiplePlayerSelector=MultiplePlayersSelector.Youngest)
Gets an active RadioTrackPlayer from this output.
virtual void Update()
Updates cachedPos.
RadioTrackPlayer PlayOneShot(string _id)
Plays a track as a one-shot. A one-shot destroys itself when its track ends.
The central data object defining the radio. Contains the tracks and information required to play the ...
const float LOW_TUNE
The lower limit for tune on this radio. This may become non-const at some point.
const float HIGH_TUNE
The upper limit for tune on this radio. This may become non-const at some point.
A class that plays a certain RadioTrack at runtime. It's created newly for each track on each RadioOu...
float GetSample(float _tune, Vector3 _receiverPosition, float _otherVolume, out float _outVolume, bool _applyVolume=true)
Gets the current sample from the track according to playback. I would recommend reading the code comm...
PlayerType
The different types of Player- mainly changes what it does when the end of the track is reached.
void IncrementSample()
Move this player to the next sample.
A wrapper class for RadioTrack so that track types can be switched between in the inspector!...
bool playOnInit
If true, this track plays on RadioData.Init() - usually on game start.
Base interfaces and classes for components, e.g: track accessors, output accessors.
Components to be placed on scene objects, e.g: Outputs, Broadcasters, Observers.
Tracks to be used on a radio- includes base classes.