#if UNITY_EDITOR using UnityEditor; #endif using UnityEngine; #if UNITY_EDITOR [ExecuteInEditMode] #endif [AddComponentMenu("")] public class SfxrAudioPlayer : MonoBehaviour { /** * usfxr * * Copyright 2013 Zeh Fernando * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /** * SfxrAudioPlayer * This is the (internal) behavior script responsible for streaming audio to the engine * * @author Zeh Fernando */ // Properties private bool isDestroyed = false; // If true, this instance has been destroyed and shouldn't do anything yes private bool needsToDestroy = false; // If true, it has been scheduled for destruction (from outside the main thread) private bool runningInEditMode = false; // If true, it is running from the editor and NOT playing // Instances private SfxrSynth sfxrSynth; // SfxrSynth instance that will generate the audio samples used by this // ================================================================================================================ // INTERNAL INTERFACE --------------------------------------------------------------------------------------------- void Start() { // Creates an empty audio source so this GameObject can receive audio events AudioSource soundSource = gameObject.AddComponent(); soundSource.clip = new AudioClip(); soundSource.volume = 1f; soundSource.pitch = 1f; soundSource.priority = 128; } void Update() { // Destroys self in case it has been queued for deletion if (sfxrSynth == null) { // Rogue object (leftover) // When switching between play and edit mode while the sound is playing, the object is restarted // So, queues for destruction needsToDestroy = true; } if (needsToDestroy) { needsToDestroy = false; Destroy(); } } void OnAudioFilterRead(float[] __data, int __channels) { // Requests the generation of the needed audio data from SfxrSynth if (!isDestroyed && !needsToDestroy && sfxrSynth != null) { bool hasMoreSamples = sfxrSynth.GenerateAudioFilterData(__data, __channels); // If no more samples are needed, there's no more need for this GameObject so schedule a destruction (cannot do this in this thread) if (!hasMoreSamples) { needsToDestroy = true; if (runningInEditMode) { // When running in edit mode, Update() is not called on every frame // We can't call Destroy() directly either, since Destroy() must be ran from the main thread // So we just attach our Update() to the editor's update event #if UNITY_EDITOR EditorApplication.update += Update; #endif } } } } // ================================================================================================================ // PUBLIC INTERFACE ----------------------------------------------------------------------------------------------- public void SetSfxrSynth(SfxrSynth __sfxrSynth) { // Sets the SfxrSynth instance that will generate the audio samples used by this sfxrSynth = __sfxrSynth; } public void SetRunningInEditMode(bool __runningInEditMode) { // Sets the SfxrSynth instance that will generate the audio samples used by this runningInEditMode = __runningInEditMode; } public void Destroy() { // Stops audio immediately and destroys self if (!isDestroyed) { isDestroyed = true; sfxrSynth = null; if (runningInEditMode || !Application.isPlaying) { // Since we're running in the editor, we need to remove the update event, AND destroy immediately #if UNITY_EDITOR EditorApplication.update -= Update; #endif UnityEngine.Object.DestroyImmediate(gameObject); } else { UnityEngine.Object.Destroy(gameObject); } } } }