Beispiel #1
0
        protected override void OnUpdate()
        {
            var    mgr         = EntityManager;
            Entity audioEntity = m_audioEntity;
            double currentTime = World.Time.ElapsedTime;

            ClearAudioBuffers();

            Entities
            .WithEntityQueryOptions(EntityQueryOptions.IncludeDisabled)
            .ForEach((Entity e, in AudioSourceID audioSourceID) =>
            {
                if (!mgr.HasComponent <AudioSource>(e) || mgr.HasComponent <AudioSourceStop>(e) || mgr.HasComponent <Disabled>(e))
                {
                    DynamicBuffer <EntityToStop> entitiesToStop = mgr.GetBuffer <EntityToStop>(audioEntity);
                    entitiesToStop.Add(e);

                    if (audioSourceID.sourceID > 0)
                    {
                        DynamicBuffer <SourceIDToStop> sourceIDsToStop = mgr.GetBuffer <SourceIDToStop>(audioEntity);
                        sourceIDsToStop.Add(audioSourceID.sourceID);
                    }
                }
            }).Run();

            int numEntitiesToStop = mgr.GetBuffer <EntityToStop>(audioEntity).Length;

            for (int i = 0; i < numEntitiesToStop; i++)
            {
                Entity e = mgr.GetBuffer <EntityToStop>(audioEntity)[i];

                if (mgr.HasComponent <AudioSourceStop>(e))
                {
                    mgr.RemoveComponent <AudioSourceStop>(e);
                }

                if (!mgr.HasComponent <AudioSource>(e))
                {
                    mgr.RemoveComponent <AudioSourceID>(e);
                }
            }

            Entities
            .ForEach((Entity e, in AudioSource audioSource) =>
            {
                bool audioSourceStarting = mgr.HasComponent <AudioSourceStart>(e);
                if (audioSourceStarting || audioSource.isPlaying)
                {
                    mgr.GetBuffer <EntityPlaying>(audioEntity).Add(e);
                }
            }).Run();

            for (int i = 0; i < mgr.GetBuffer <EntityPlaying>(audioEntity).Length; i++)
            {
                Entity e = mgr.GetBuffer <EntityPlaying>(audioEntity)[i];

                if (!mgr.HasComponent <AudioSourceID>(e))
                {
                    AudioSourceID audioNativeSource = new AudioSourceID()
                    {
                        sourceID = 0
                    };
                    mgr.AddComponentData(e, audioNativeSource);
                }
            }

            // Get the listener position.
            LocalToWorld listenerLocalToWorld = new LocalToWorld();
            bool         foundListener        = false;

            Entities
            .WithAll <AudioListener>()
            .ForEach((Entity e, in LocalToWorld localToWorld) =>
            {
                if (!foundListener)
                {
                    listenerLocalToWorld = localToWorld;
                    foundListener        = true;
                }
            }).Run();

            int numEntitiesPlaying = mgr.GetBuffer <EntityPlaying>(audioEntity).Length;

            for (int i = 0; i < numEntitiesPlaying; i++)
            {
                Entity e = mgr.GetBuffer <EntityPlaying>(audioEntity)[i];

                if (mgr.HasComponent <AudioDistanceAttenuation>(e))
                {
                    AudioDistanceAttenuation distanceAttenuation = mgr.GetComponentData <AudioDistanceAttenuation>(e);
                    float distanceAttenuationVolume = 0.0f;

                    if (foundListener && mgr.HasComponent <LocalToWorld>(e))
                    {
                        LocalToWorld localToWorld       = mgr.GetComponentData <LocalToWorld>(e);
                        float        xDist              = localToWorld.Position.x - listenerLocalToWorld.Position.x;
                        float        yDist              = localToWorld.Position.y - listenerLocalToWorld.Position.y;
                        float        zDist              = localToWorld.Position.z - listenerLocalToWorld.Position.z;
                        float        distanceToListener = math.sqrt(xDist * xDist + yDist * yDist + zDist * zDist);

                        if (distanceToListener <= distanceAttenuation.minDistance)
                        {
                            distanceAttenuationVolume = 1.0f;
                        }
                        else if (distanceToListener > distanceAttenuation.maxDistance)
                        {
                            distanceAttenuationVolume = 0.0f;
                        }
                        else
                        {
                            // Reduce distanceToListener by minDistance because, in our simulation, we start lowering the volume after a sound is min distance away from the listener.
                            distanceToListener -= distanceAttenuation.minDistance;

                            if (distanceAttenuation.rolloffMode == AudioRolloffMode.Linear)
                            {
                                float attenuationRange = distanceAttenuation.maxDistance - distanceAttenuation.minDistance;
                                distanceAttenuationVolume = 1.0f - (distanceToListener / attenuationRange);
                            }
                            else if (distanceAttenuation.rolloffMode == AudioRolloffMode.Logarithmic)
                            {
                                // In Unity's original implementation of logarithmic attenuation, the volume is halved every minDistance units. We are copying that approach here.
                                float volumeHalfLives = distanceToListener / distanceAttenuation.minDistance;
                                distanceAttenuationVolume = 1.0f / math.pow(2.0f, volumeHalfLives);
                            }
                        }
                    }

                    distanceAttenuation.volume = distanceAttenuationVolume;
                    mgr.SetComponentData <AudioDistanceAttenuation>(e, distanceAttenuation);
                }

                if (HasComponent <Audio3dPanning>(e))
                {
                    Audio3dPanning panning = mgr.GetComponentData <Audio3dPanning>(e);
                    float          pan     = 0.0f;

                    if (foundListener && mgr.HasComponent <LocalToWorld>(e))
                    {
                        LocalToWorld localToWorld    = mgr.GetComponentData <LocalToWorld>(e);
                        float3       listenerRight   = math.normalize(listenerLocalToWorld.Right);
                        float3       listenerToSound = math.normalize(localToWorld.Position - listenerLocalToWorld.Position);
                        pan = math.dot(listenerRight, listenerToSound);
                    }

                    panning.pan = pan;
                    mgr.SetComponentData <Audio3dPanning>(e, panning);
                }
            }

#if ENABLE_DOTSRUNTIME_PROFILER
            ProfilerStats.GatheredStats |= ProfilerModes.ProfileAudio;

            ProfilerStats.AccumStats.audioPlayingSources.value = 0;
            ProfilerStats.AccumStats.audioPausedSources.value  = 0;
            Entities.ForEach((Entity e, ref AudioSource source) =>
            {
                if (source.isPlaying)
                {
                    ProfilerStats.AccumStats.audioPlayingSources.Accumulate(1);
                }
                else
                {
                    ProfilerStats.AccumStats.audioPausedSources.Accumulate(1);
                }
            }).Run();

            // No concept of multiple clips playing per audio source in Tiny Audio
            ProfilerStats.AccumStats.audioNumSoundChannelInstances = ProfilerStats.AccumStats.audioPlayingSources;
#endif
        }
Beispiel #2
0
        protected override unsafe void OnUpdate()
        {
            var         mgr         = EntityManager;
            Entity      audioEntity = m_audioEntity;
            double      currentTime = World.Time.ElapsedTime;
            int         uncompressedAudioMemoryBytes = m_uncompressedAudioMemoryBytes;
            double      worldElapsedTime             = World.Time.ElapsedTime;
            AudioConfig ac = GetSingleton <AudioConfig>();

            NativeList <Entity> entitiesPlayed = new NativeList <Entity>(Allocator.Temp);

            base.OnUpdate();

            AudioNativeCalls.PauseAudio(ac.paused);
            ReinitIfDefaultDeviceChanged();
            ReinitIfNoAudioConsumed(ac.paused);

            // We are starting to make AudioSource play/stop and property changes, so block the audio mixer thread from doing any work
            // on this state until we are done.
            AudioNativeCalls.SoundSourcePropertyMutexLock();

            for (int i = 0; i < mgr.GetBuffer <SourceIDToStop>(audioEntity).Length; i++)
            {
                uint id = mgr.GetBuffer <SourceIDToStop>(audioEntity)[i];
                AudioNativeCalls.Stop(id);
            }

            // Play sounds.
            Entities
            .WithAll <AudioSource, AudioSourceStart>()
            .ForEach((Entity e) =>
            {
                uint sourceID = PlaySource(mgr, e);
                if (sourceID > 0)
                {
                    AudioSourceID audioSourceID = mgr.GetComponentData <AudioSourceID>(e);
                    audioSourceID.sourceID      = sourceID;
                    mgr.SetComponentData <AudioSourceID>(e, audioSourceID);

                    entitiesPlayed.Add(e);
                }
            }).Run();

            for (int i = 0; i < entitiesPlayed.Length; i++)
            {
                mgr.RemoveComponent <AudioSourceStart>(entitiesPlayed[i]);
            }

            Entities
            .ForEach((Entity e, ref AudioClipUsage audioClipUsage) =>
            {
                audioClipUsage.playingRefCount = 0;
            }).Run();

            // Re-calculate the playing ref count for each audio clip. Also, update AudioSource's isPlaying bool and remove
            // any AudioSource entities from the list if they are no longer playing.
            Entities
            .ForEach((Entity e, in AudioSource audioSource) =>
            {
                bool audioSourceStarting = mgr.HasComponent <AudioSourceStart>(e);
                if (audioSourceStarting || audioSource.isPlaying)
                {
                    Entity clipEntity             = audioSource.clip;
                    AudioClipUsage audioClipUsage = mgr.GetComponentData <AudioClipUsage>(clipEntity);
                    audioClipUsage.playingRefCount++;
                    audioClipUsage.lastTimeUsed = currentTime;
                    mgr.SetComponentData <AudioClipUsage>(clipEntity, audioClipUsage);
                }
            }).Run();

            if (uncompressedAudioMemoryBytes > ac.maxUncompressedAudioMemoryBytes)
            {
                Entities
                .ForEach((Entity e, ref DynamicBuffer <AudioClipUncompressed> audioClipUncompressed) =>
                {
                    if (audioClipUncompressed.Length > 0)
                    {
                        AudioClipUsage audioClipUsage = mgr.GetComponentData <AudioClipUsage>(e);

                        bool notRecentlyUsed = (audioClipUsage.lastTimeUsed + 15.0f < currentTime);
                        bool largeAudioAsset = audioClipUncompressed.Length > 2 * 1024 * 1024;

                        if ((uncompressedAudioMemoryBytes > ac.maxUncompressedAudioMemoryBytes) &&
                            (audioClipUsage.playingRefCount <= 0) &&
                            (notRecentlyUsed || largeAudioAsset))
                        {
                            int clipUncompressedAudioMemoryBytes = audioClipUncompressed.Length * sizeof(short);

                            AudioNativeClip audioNativeClip = mgr.GetComponentData <AudioNativeClip>(e);
                            AudioNativeCalls.SetUncompressedMemory(audioNativeClip.clipID, (IntPtr)null, 0);

                            AudioClip audioClip = mgr.GetComponentData <AudioClip>(e);
                            audioClip.status    = AudioClipStatus.Loading;
                            mgr.SetComponentData <AudioClip>(e, audioClip);

                            audioClipUncompressed.ResizeUninitialized(0);
                            uncompressedAudioMemoryBytes -= clipUncompressedAudioMemoryBytes;
                        }
                    }
                }).Run();

                Entities
                .ForEach((Entity e, ref DynamicBuffer <AudioClipUncompressed> audioClipUncompressed) =>
                {
                    if (audioClipUncompressed.Length > 0)
                    {
                        AudioClipUsage audioClipUsage = mgr.GetComponentData <AudioClipUsage>(e);

                        if ((uncompressedAudioMemoryBytes > ac.maxUncompressedAudioMemoryBytes) &&
                            (audioClipUsage.playingRefCount <= 0))
                        {
                            int clipUncompressedAudioMemoryBytes = audioClipUncompressed.Length * sizeof(short);

                            AudioNativeClip audioNativeClip = mgr.GetComponentData <AudioNativeClip>(e);
                            AudioNativeCalls.SetUncompressedMemory(audioNativeClip.clipID, (IntPtr)null, 0);

                            AudioClip audioClip = mgr.GetComponentData <AudioClip>(e);
                            audioClip.status    = AudioClipStatus.Loading;
                            mgr.SetComponentData <AudioClip>(e, audioClip);

                            audioClipUncompressed.ResizeUninitialized(0);
                            uncompressedAudioMemoryBytes -= clipUncompressedAudioMemoryBytes;
                        }
                    }
                }).Run();
            }

            DynamicBuffer <EntityPlaying> entitiesPlaying = mgr.GetBuffer <EntityPlaying>(m_audioEntity);

            for (int i = 0; i < entitiesPlaying.Length; i++)
            {
                Entity      e           = entitiesPlaying[i];
                AudioSource audioSource = mgr.GetComponentData <AudioSource>(e);

                audioSource.isPlaying = (IsPlaying(mgr, e) == 1) ? true : false;
                mgr.SetComponentData <AudioSource>(e, audioSource);

                if (audioSource.isPlaying)
                {
                    float volume = audioSource.volume;
                    if (mgr.HasComponent <AudioDistanceAttenuation>(e))
                    {
                        AudioDistanceAttenuation distanceAttenuation = mgr.GetComponentData <AudioDistanceAttenuation>(e);
                        volume *= distanceAttenuation.volume;
                    }
                    SetVolume(mgr, e, volume);

                    if (mgr.HasComponent <Audio3dPanning>(e))
                    {
                        Audio3dPanning panning = mgr.GetComponentData <Audio3dPanning>(e);
                        SetPan(mgr, e, panning.pan);
                    }
                    else if (mgr.HasComponent <Audio2dPanning>(e))
                    {
                        Audio2dPanning panning = mgr.GetComponentData <Audio2dPanning>(e);
                        SetPan(mgr, e, panning.pan);
                    }

                    if (mgr.HasComponent <AudioPitch>(e))
                    {
                        AudioPitch pitchEffect = mgr.GetComponentData <AudioPitch>(e);
                        float      pitch       = (pitchEffect.pitch > 0.0f) ? pitchEffect.pitch : 1.0f;
                        SetPitch(mgr, e, pitch);
                    }
                }
            }

            // We are done making AudioSource property changes, so unblock the audio mixer thread.
            AudioNativeCalls.SoundSourcePropertyMutexUnlock();

#if ENABLE_DOTSRUNTIME_PROFILER
            ProfilerStats.GatheredStats |= ProfilerModes.ProfileAudio;
            ProfilerStats.AccumStats.audioDspCPUx10.value = (long)(AudioNativeCalls.GetCpuUsage() * 10);

            ProfilerStats.AccumStats.memAudioCount.value         = 0;
            ProfilerStats.AccumStats.memAudio.value              = 0;
            ProfilerStats.AccumStats.memReservedAudio.value      = 0;
            ProfilerStats.AccumStats.memUsedAudio.value          = 0;
            ProfilerStats.AccumStats.audioStreamFileMemory.value = 0;
            ProfilerStats.AccumStats.audioSampleMemory.value     = 0;

            Entities
            .ForEach((Entity e, in DynamicBuffer <AudioClipCompressed> audioClipCompressed, in DynamicBuffer <AudioClipUncompressed> audioClipUncompressed) =>
            {
                int audioClipCompressedBytes   = audioClipCompressed.Length;
                int audioClipUncompressedBytes = audioClipUncompressed.Length * sizeof(short);
                int audioClipTotalBytes        = audioClipCompressedBytes + audioClipUncompressedBytes;

                ProfilerStats.AccumStats.memAudioCount.Accumulate(1);
                ProfilerStats.AccumStats.memAudio.Accumulate(audioClipTotalBytes);
                ProfilerStats.AccumStats.memReservedAudio.Accumulate(audioClipTotalBytes);
                ProfilerStats.AccumStats.memUsedAudio.Accumulate(audioClipTotalBytes);
                ProfilerStats.AccumStats.audioSampleMemory.Accumulate(audioClipTotalBytes);
            }).Run();