Skip to content

File Node.h

File List > Amplitude > Mixer > Node.h

Go to the documentation of this file

// Copyright (c) 2024-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_MIXER_NODE_H
#define _AM_MIXER_NODE_H

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

namespace SparkyStudios::Audio::Amplitude
{
    class AmplimixLayer;
    class PipelineInstance;

    class AM_API_PUBLIC NodeInstance
    {
        friend class PipelineInstance;

    public:
        virtual void Initialize(AmObjectID id, const AmplimixLayer* layer, const PipelineInstance* pipeline, AmSize paramCount);

        virtual ~NodeInstance() = default;

        [[nodiscard]] AmObjectID GetId() const;

        [[nodiscard]] const AmplimixLayer* GetLayer() const;

        virtual void Reset() = 0;

        virtual AmReal32 GetParameter(AmSize index);

        virtual void SetParameter(AmSize index, AmReal32 value);

        virtual void Configure(AmUInt64 frameCount, AmUInt16 channelCount);

        [[nodiscard]] virtual AmUInt64 GetOutputFrameCount() const;

        [[nodiscard]] virtual AmUInt16 GetOutputChannelCount() const;

        [[nodiscard]] virtual bool ShouldSkip() const;

    protected:
        AmUInt64 m_inputFrameCount = 0;

        AmUInt16 m_inputChannelCount = 0;

        AmObjectID m_id;

        const AmplimixLayer* m_layer;

        const PipelineInstance* m_pipeline;

        AmUInt32 m_numParamsChanged;

        std::vector<AmReal32> m_parameters;
    };

    class AM_API_PUBLIC ConsumerNodeInstance
    {
    public:
        virtual ~ConsumerNodeInstance() = default;

        virtual void Consume() = 0;

        virtual void Connect(AmObjectID provider) = 0;
    };

    class AM_API_PUBLIC ProviderNodeInstance
    {
    public:
        virtual ~ProviderNodeInstance() = default;

        virtual const AudioBuffer* Provide() = 0;
    };

    class AM_API_PUBLIC ProcessorNodeInstance
        : public NodeInstance
        , public ConsumerNodeInstance
        , public ProviderNodeInstance
    {
    public:
        explicit ProcessorNodeInstance(bool processOnEmptyBuffer = false);

        ~ProcessorNodeInstance() override = default;

        virtual const AudioBuffer* Process(const AudioBuffer* input) = 0;

        void Consume() final;

        void Connect(AmObjectID provider) final;

        const AudioBuffer* Provide() final;

        void Reset() override;

        void Configure(AmUInt64 frameCount, AmUInt16 channelCount) override;

        [[nodiscard]] AM_INLINE AmObjectID GetProvider() const
        {
            return m_provider;
        }

    protected:
        AmObjectID m_provider;

        AudioBuffer _output;

    private:
        const AudioBuffer* _processingBuffer;
        const AudioBuffer* _lastOutputBuffer;
        bool _processOnEmptyInputBuffer;
        ProviderNodeInstance* _cachedProvider;
    };

    class AM_API_PUBLIC MixerNodeInstance
        : public NodeInstance
        , public ConsumerNodeInstance
        , public ProviderNodeInstance
    {
    public:
        MixerNodeInstance();

        ~MixerNodeInstance() override = default;

        void Consume() final;

        void Connect(AmObjectID provider) final;

        void Connect(const std::vector<AmObjectID>& providers);

        const AudioBuffer* Provide() final;

        void Reset() override;

        void Configure(AmUInt64 frameCount, AmUInt16 channelCount) override;

        [[nodiscard]] AM_INLINE const std::vector<AmObjectID>& GetProviders() const
        {
            return m_providers;
        }

    protected:
        std::vector<AmObjectID> m_providers;

        AudioBuffer _mixBuffer;

    private:
        std::vector<const AudioBuffer*> _processingBuffers;
        bool _processed;
        std::vector<ProviderNodeInstance*> _cachedProviders;
    };

    class AM_API_PUBLIC InputNodeInstance
        : public NodeInstance
        , public ProviderNodeInstance
    {
        friend class PipelineInstance;

    public:
        InputNodeInstance();

        ~InputNodeInstance() override = default;

        void SetInput(AudioBuffer* buffer);

        const AudioBuffer* Provide() override;

        void Reset() override;

    private:
        AudioBuffer* _buffer;
        std::shared_ptr<FilterInstance> _filter;
    };

    class AM_API_PUBLIC OutputNodeInstance
        : public NodeInstance
        , public ConsumerNodeInstance
    {
        friend class PipelineInstance;

    public:
        OutputNodeInstance();

        ~OutputNodeInstance() override = default;

        void SetOutput(AudioBuffer* buffer);

        void Consume() override;

        void Connect(AmObjectID provider) override;

        void Reset() override;

    private:
        AmObjectID _provider;
        AudioBuffer* _buffer;
        ProviderNodeInstance* _cachedProvider;
    };

    class AM_API_PUBLIC Node
    {
    public:
        explicit Node(AmString name);

        virtual ~Node();

        virtual std::shared_ptr<NodeInstance> CreateInstance() const = 0;

        [[nodiscard]] const AmString& GetName() const;

        [[nodiscard]] virtual bool CanConsume() const = 0;

        [[nodiscard]] virtual bool CanProduce() const = 0;

        [[nodiscard]] virtual AmSize GetMaxInputCount() const = 0;

        [[nodiscard]] virtual AmSize GetMinInputCount() const = 0;

        [[nodiscard]] virtual AmSize GetParameterCount() const;

        [[nodiscard]] virtual AmString GetParameterName(AmSize index) const;

        [[nodiscard]] virtual eParameterType GetParameterType(AmSize index) const;

        [[nodiscard]] virtual AmReal32 GetParameterMax(AmSize index) const;

        [[nodiscard]] virtual AmReal32 GetParameterMin(AmSize index) const;

        static void Register(std::shared_ptr<Node> node);

        static void Unregister(std::shared_ptr<const Node> node);

        static std::shared_ptr<Node> Find(const AmString& name);

        static std::shared_ptr<NodeInstance> Construct(const AmString& name);

        static void LockRegistry();

        static void UnlockRegistry();

        static const std::map<AmString, std::shared_ptr<Node>>& GetRegistry();

    protected:
        AmString m_name;
    };
} // namespace SparkyStudios::Audio::Amplitude

#endif // _AM_MIXER_NODE_H