Skip to content

File ChannelLayout.h

File List > Amplitude > DSP > ChannelLayout.h

Go to the documentation of this file

// Copyright (c) 2026-present Sparky Studios. All rights reserved.
//
// 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.

#pragma once

#ifndef _AM_DSP_CHANNEL_LAYOUT_H
#define _AM_DSP_CHANNEL_LAYOUT_H

#include <array>
#include <initializer_list>

#include <SparkyStudios/Audio/Amplitude/Core/Common.h>

namespace SparkyStudios::Audio::Amplitude
{
    constexpr AmUInt16 kAmMaxLayoutChannelCount = 8;

    constexpr AmReal32 kAmSpreadNative = -1.0f;

    enum eChannelLayout : AmUInt8
    {
        eChannelLayout_Mono = 0,
        eChannelLayout_Stereo,
        eChannelLayout_Quad,
        eChannelLayout_Surround_5_1,
        eChannelLayout_Surround_7_1,
        eChannelLayout_COUNT,
    };

    enum eSpeaker : AmUInt8
    {
        eSpeaker_FrontLeft = 0,
        eSpeaker_FrontRight,
        eSpeaker_FrontCenter,
        eSpeaker_LowFrequency,
        eSpeaker_BackLeft,
        eSpeaker_BackRight,
        eSpeaker_SideLeft,
        eSpeaker_SideRight,
    };

    struct AM_API_PUBLIC ChannelMatrix
    {
        AmUInt16 inputCount = 0;
        AmUInt16 outputCount = 0;
        std::array<std::array<AmReal32, kAmMaxLayoutChannelCount>, kAmMaxLayoutChannelCount> gains{};
    };

    class AM_API_PUBLIC ChannelLayout
    {
    public:
        static const ChannelLayout& Get(eChannelLayout layout);

        static const ChannelLayout* FromChannelCount(AmUInt16 channelCount);

        static const ChannelLayout& LargestFitting(AmUInt16 channelCount);

        static ChannelMatrix GetFoldDownMatrix(const ChannelLayout& from, const ChannelLayout& to);

        [[nodiscard]] AM_INLINE eChannelLayout GetType() const
        {
            return _type;
        }

        [[nodiscard]] AM_INLINE AmUInt16 GetChannelCount() const
        {
            return _channelCount;
        }

        [[nodiscard]] eSpeaker GetSpeaker(AmUInt16 channel) const;

        [[nodiscard]] AmReal32 GetAzimuth(AmUInt16 channel) const;

        [[nodiscard]] bool IsLfe(AmUInt16 channel) const;

        [[nodiscard]] AmInt32 GetLfeChannel() const;

        [[nodiscard]] AmInt32 FindSpeaker(eSpeaker speaker) const;

        [[nodiscard]] AmReal32 GetNativeWidth() const;

        [[nodiscard]] AM_INLINE bool operator==(const ChannelLayout& other) const
        {
            return _type == other._type;
        }

    private:
        struct SpeakerPosition
        {
            eSpeaker speaker;
            AmReal32 azimuth;
        };

        ChannelLayout(eChannelLayout type, std::initializer_list<SpeakerPosition> speakers);

        eChannelLayout _type;
        AmUInt16 _channelCount;
        std::array<eSpeaker, kAmMaxLayoutChannelCount> _speakers{};
        std::array<AmReal32, kAmMaxLayoutChannelCount> _azimuths{};
    };
} // namespace SparkyStudios::Audio::Amplitude

#endif // _AM_DSP_CHANNEL_LAYOUT_H