예제 #1
0
파일: AudioEngine.cs 프로젝트: xxami/Pulsus
        private void AddInstance(SoundInstance soundInstance, int polyphony)
        {
            if (soundInstance.sound.data.Length == 0)
            {
                return;
            }

            SoundInstanceInternal instance = new SoundInstanceInternal(soundInstance);

            if (!dataInstanceCount.ContainsKey(instance.sound))
            {
                dataInstanceCount.Add(instance.sound, 0);
            }

            lock (audibleSounds)
                instance.offsetStart = GetBufferOffset();
            instance.position = soundInstance.startPosition;

            EnforcePolyphony(polyphony, instance, instance.offsetStart);

            lock (audibleSounds)
            {
                audibleSounds.Add(instance);
                dataInstanceCount[instance.sound] = dataInstanceCount[instance.sound] + 1;
            }
        }
예제 #2
0
파일: AudioEngine.cs 프로젝트: xxami/Pulsus
        public void PlayScheduled(double position, SoundInstance soundInstance, int polyphony)
        {
            if (soundInstance.sound.data.Length == 0)
            {
                return;
            }

            SoundInstanceInternal instance = new SoundInstanceInternal(soundInstance);

            if (!dataInstanceCount.ContainsKey(instance.sound))
            {
                dataInstanceCount.Add(instance.sound, 0);
            }

            double bufferPosition = (position - lastCallback) * ((double)audioSpec.freq);
            uint   offset         = (uint)(bufferPosition * bytesPerSample);

            if (offset % 4 != 0)
            {
                offset += 4 - (offset % 4);
            }

            instance.offsetStart = offset;
            instance.position    = soundInstance.startPosition;

            EnforcePolyphony(polyphony, instance, offset);

            lock (audibleSounds)
            {
                audibleSounds.Add(instance);
                dataInstanceCount[instance.sound] = dataInstanceCount[instance.sound] + 1;
            }
        }
예제 #3
0
파일: AudioEngine.cs 프로젝트: xxami/Pulsus
        public byte[] RenderAudio()
        {
            if (audioDriver != AudioDriver.File)
            {
                return(null);
            }

            uint streamLength = 0;

            for (int i = 0; i < audibleSounds.Count; ++i)
            {
                SoundInstanceInternal instance = audibleSounds[i];
                if (streamLength < instance.offsetStart + instance.endPosition)
                {
                    streamLength = instance.offsetStart + instance.endPosition;
                }
            }

            if (streamLength == 0)
            {
                return(null);
            }

            byte[]   bytes  = new byte[(int)streamLength];
            GCHandle stream = GCHandle.Alloc(bytes, GCHandleType.Pinned);

            for (int i = 0; i < audibleSounds.Count; ++i)
            {
                SoundInstanceInternal instance = audibleSounds[i];

                int playLength = (int)(instance.offsetStop - instance.offsetStart);
                if (playLength > instance.endPosition)
                {
                    playLength = (int)instance.endPosition;
                }
                else if (playLength <= 0)
                {
                    playLength = (int)instance.endPosition;
                }

                IntPtr streamOffset = stream.AddrOfPinnedObject();
                streamOffset += (int)instance.offsetStart;

                byte finalVolume = (byte)Math.Round(Math.Min(volume * instance.volume * SDL.SDL_MIX_MAXVOLUME, SDL.SDL_MIX_MAXVOLUME));
                SDL_MixAudioFormat(streamOffset, instance.sound.data, audioSpec.format, (uint)playLength, finalVolume);
            }

            stream.Free();
            audibleSounds.Clear();

            return(bytes);
        }
예제 #4
0
파일: AudioEngine.cs 프로젝트: xxami/Pulsus
        private void EnforcePolyphony(int polyphony, SoundInstanceInternal instance, uint offset)
        {
            if (polyphony == 0)
            {
                return;
            }

            SoundData sound = instance.sound;

            if (dataInstanceCount[sound] < polyphony)
            {
                return;
            }

            int removeCount = dataInstanceCount[sound] - polyphony + 1;

            lock (audibleSounds)
            {
                for (int i = 0; i < audibleSounds.Count; ++i)
                {
                    SoundInstanceInternal audibleInstance = audibleSounds[i];
                    if (audibleInstance.sound != sound)
                    {
                        continue;
                    }

                    if (audibleInstance.remove)
                    {
                        continue;
                    }

                    // only apply polyphony to identical slices
                    if (audibleInstance.instance.startPosition != instance.instance.startPosition ||
                        audibleInstance.instance.endPosition != instance.instance.endPosition)
                    {
                        continue;
                    }

                    // mark instance for later removal
                    audibleInstance.paused     = true;
                    audibleInstance.remove     = true;
                    audibleInstance.offsetStop = offset;

                    removeCount--;
                    if (removeCount <= 0)
                    {
                        break;
                    }
                }
            }
        }
예제 #5
0
파일: AudioEngine.cs 프로젝트: xxami/Pulsus
        private void CopySample(SoundInstanceInternal instance, IntPtr userData, IntPtr stream, int length)
        {
            uint sampleLeft = Math.Min(instance.endPosition - instance.position, (uint)length);

            uint startOffset = instance.offsetStart;
            uint pauseOffset = instance.offsetStop;

            if (startOffset < length)
            {
                uint copyLength = Math.Min(sampleLeft + startOffset, (uint)length) - startOffset;

                if (instance.paused)
                {
                    if (startOffset <= pauseOffset)
                    {
                        copyLength = Math.Min(pauseOffset - startOffset, copyLength);
                    }
                    else
                    {
                        copyLength = 0;
                    }
                    instance.offsetStop = 0;
                }

                // audio clip starts playing at starting offset
                Array.Copy(instance.sound.data, instance.position, audioBuffer, startOffset, copyLength);

                instance.position   += copyLength;
                instance.offsetStart = 0;
            }
            else
            {
                instance.offsetStart -= (uint)length;
            }

            if (instance.position >= instance.endPosition)
            {
                instance.remove = true;
            }
        }
예제 #6
0
파일: AudioEngine.cs 프로젝트: xxami/Pulsus
        private void MixAudio(IntPtr userData, IntPtr stream, int length)
        {
            for (int i = 0; i < audibleSounds.Count; ++i)
            {
                SoundInstanceInternal instance = audibleSounds[i];

                // fill temporary buffer with silence
                Array.Copy(emptyBuffer, 0, audioBuffer, 0, length);

                CopySample(instance, userData, stream, length);

                byte finalVolume = (byte)Math.Round(Math.Min(volume * instance.volume * SDL.SDL_MIX_MAXVOLUME, SDL.SDL_MIX_MAXVOLUME));
                SDL_MixAudioFormat(stream, audioBuffer, audioSpec.format, (uint)length, finalVolume);

                if (instance.remove)
                {
                    audibleSounds.RemoveAt(i);
                    dataInstanceCount[instance.sound] = dataInstanceCount[instance.sound] - 1;
                    i--;
                }
            }
        }