ValueTreeState parameters not working

I have been following the guide from https://www.youtube.com/watch?v=nkQPsYOdIrk&t=702s&ab_channel=TheAudioProgrammer and https://www.youtube.com/watch?v=xgoSzXgUPpc&ab_channel=TheAudioProgrammer to try set up a panner plugin controlled by a slider with a button to toggle between linear and constant power mode. I have placed a ‘*’ before the panPosition parameter variable and I wonder if this might be causing it. I have placed these as if I don’t, I get a std::atomic error.
Processor.cpp

#include "PluginProcessor.h"
#include "PluginEditor.h"

//==============================================================================
PannerWithGUIAudioProcessor::PannerWithGUIAudioProcessor()
#ifndef JucePlugin_PreferredChannelConfigurations
     : AudioProcessor (BusesProperties()
                     #if ! JucePlugin_IsMidiEffect
                      #if ! JucePlugin_IsSynth
                       .withInput  ("Input",  juce::AudioChannelSet::stereo(), true)
                      #endif
                       .withOutput ("Output", juce::AudioChannelSet::stereo(), true)
                     #endif
                       ), aptvs (*this, nullptr, "Parameters", createParameters())
#endif
{
}

PannerWithGUIAudioProcessor::~PannerWithGUIAudioProcessor()
{
}

//==============================================================================
const juce::String PannerWithGUIAudioProcessor::getName() const
{
    return JucePlugin_Name;
}

bool PannerWithGUIAudioProcessor::acceptsMidi() const
{
   #if JucePlugin_WantsMidiInput
    return true;
   #else
    return false;
   #endif
}

bool PannerWithGUIAudioProcessor::producesMidi() const
{
   #if JucePlugin_ProducesMidiOutput
    return true;
   #else
    return false;
   #endif
}

bool PannerWithGUIAudioProcessor::isMidiEffect() const
{
   #if JucePlugin_IsMidiEffect
    return true;
   #else
    return false;
   #endif
}

double PannerWithGUIAudioProcessor::getTailLengthSeconds() const
{
    return 0.0;
}

int PannerWithGUIAudioProcessor::getNumPrograms()
{
    return 1;   // NB: some hosts don't cope very well if you tell them there are 0 programs,
                // so this should be at least 1, even if you're not really implementing programs.
}

int PannerWithGUIAudioProcessor::getCurrentProgram()
{
    return 0;
}

void PannerWithGUIAudioProcessor::setCurrentProgram (int index)
{
}

const juce::String PannerWithGUIAudioProcessor::getProgramName (int index)
{
    return {};
}

void PannerWithGUIAudioProcessor::changeProgramName (int index, const juce::String& newName)
{
}

//==============================================================================
void PannerWithGUIAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    // Use this method as the place to do any pre-playback
    // initialisation that you need..
}

void PannerWithGUIAudioProcessor::releaseResources()
{
    // When playback stops, you can use this as an opportunity to free up any
    // spare memory, etc.
}

#ifndef JucePlugin_PreferredChannelConfigurations
bool PannerWithGUIAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
{
  #if JucePlugin_IsMidiEffect
    juce::ignoreUnused (layouts);
    return true;
  #else
    // This is the place where you check if the layout is supported.
    // In this template code we only support mono or stereo.
    // Some plugin hosts, such as certain GarageBand versions, will only
    // load plugins that support stereo bus layouts.
    if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono()
     && layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
        return false;

    // This checks if the input layout matches the output layout
   #if ! JucePlugin_IsSynth
    if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
        return false;
   #endif

    return true;
  #endif
}
#endif

void PannerWithGUIAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    juce::ScopedNoDenormals noDenormals;
    auto totalNumInputChannels  = getTotalNumInputChannels();
    auto totalNumOutputChannels = getTotalNumOutputChannels();

    // In case we have more outputs than inputs, this code clears any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    // This is here to avoid people getting screaming feedback
    // when they first compile a plugin, but obviously you don't need to keep
    // this code if your algorithm always overwrites all the output channels.
    for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear (i, 0, buffer.getNumSamples());
    
    auto *panPosition = aptvs.getRawParameterValue("PanPosition");
    std::cout << panPosition->load() << std::endl;
    
    auto buttonState = aptvs.getRawParameterValue("Mode");
    std::cout  << buttonState->load() << std::endl;
    
    // Calculate p for Linear Panning Mode.
    float pLinear = (*panPosition + 1.0f) / 2.0f;
        
    // Calculate p for Constant Power Mode. Note that M_PI = Pi.
    float pConstantPower = (M_PI * (*panPosition + 1.0f)) / 4;
    
    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {
        auto* channelData = buffer.getWritePointer (channel);
        
        for (int i = 0; i < buffer.getNumSamples(); i++)
        {
            // Linear Algorithm.
            if (buttonState == 0)
            {
                if (channel == 0)
                {
                    channelData[i] = channelData[i] * (1.0 - pLinear);
                }
                else
                {
                    channelData[i] = channelData[i] * pLinear;
                }
            }
            // Constant Power Algorithm.
            else
            {
                if (channel == 0)
                {
                    channelData[i] = channelData[i] * cos(pConstantPower);
                }
                else
                {
                    channelData[i] = channelData[i] * sin(pConstantPower);
                }
            }
        }
    }
}

//==============================================================================
bool PannerWithGUIAudioProcessor::hasEditor() const
{
    return true; // (change this to false if you choose to not supply an editor)
}

juce::AudioProcessorEditor* PannerWithGUIAudioProcessor::createEditor()
{
    return new PannerWithGUIAudioProcessorEditor (*this);
}

//==============================================================================
void PannerWithGUIAudioProcessor::getStateInformation (juce::MemoryBlock& destData)
{
    auto *panPosition = aptvs.getRawParameterValue("PanPosition");
    std::cout << panPosition->load() << std::endl;
    // Create a memory stream object
    juce::MemoryOutputStream stream(destData, true);
    // Store a float into memory
    stream.writeFloat(*panPosition);
}

void PannerWithGUIAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
    auto *panPosition = aptvs.getRawParameterValue("PanPosition");
    std::cout << panPosition->load() << std::endl;
    // Create a memory stream object
    juce::MemoryInputStream stream(data, static_cast<size_t> (sizeInBytes), false);
    // Read a float from memory i.e. retrieve the parameter value
    *panPosition = stream.readFloat();
}

//==============================================================================
// This creates new instances of the plugin..
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
    return new PannerWithGUIAudioProcessor();
}

juce::AudioProcessorValueTreeState::ParameterLayout PannerWithGUIAudioProcessor::createParameters()
{
    std::vector<std::unique_ptr<juce::RangedAudioParameter>> params;
    params.push_back (std::make_unique<juce::AudioParameterInt>("Mode", "Mode", 0, 1, 0));
    params.push_back (std::make_unique<juce::AudioParameterFloat>("PanPosition", "PanPosition", -1.0f, 1.0f, 0.0f));
    return { params.begin(), params.end() };
}

Processor.h

#pragma once

#include <JuceHeader.h>

//==============================================================================
/**
*/
class PannerWithGUIAudioProcessor  : public juce::AudioProcessor
{
public:
    //==============================================================================
    PannerWithGUIAudioProcessor();
    ~PannerWithGUIAudioProcessor() override;

    //==============================================================================
    void prepareToPlay (double sampleRate, int samplesPerBlock) override;
    void releaseResources() override;

   #ifndef JucePlugin_PreferredChannelConfigurations
    bool isBusesLayoutSupported (const BusesLayout& layouts) const override;
   #endif

    void processBlock (juce::AudioBuffer<float>&, juce::MidiBuffer&) override;

    //==============================================================================
    juce::AudioProcessorEditor* createEditor() override;
    bool hasEditor() const override;

    //==============================================================================
    const juce::String getName() const override;

    bool acceptsMidi() const override;
    bool producesMidi() const override;
    bool isMidiEffect() const override;
    double getTailLengthSeconds() const override;

    //==============================================================================
    int getNumPrograms() override;
    int getCurrentProgram() override;
    void setCurrentProgram (int index) override;
    const juce::String getProgramName (int index) override;
    void changeProgramName (int index, const juce::String& newName) override;

    //==============================================================================
    void getStateInformation (juce::MemoryBlock& destData) override;
    void setStateInformation (const void* data, int sizeInBytes) override;

    juce::AudioProcessorValueTreeState aptvs;
    
private:

    juce::AudioProcessorValueTreeState::ParameterLayout createParameters();
    
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PannerWithGUIAudioProcessor)
};

Editor.cpp

#include "PluginProcessor.h"
#include "PluginEditor.h"

//==============================================================================
PannerWithGUIAudioProcessorEditor::PannerWithGUIAudioProcessorEditor (PannerWithGUIAudioProcessor& p)
: AudioProcessorEditor (&p), panMode("Pan Mode", juce::Colour (38, 38, 38), juce::Colour (58, 58, 58), juce::Colour (38, 38, 38)), audioProcessor (p)
{
    // Make sure that before the constructor has finished, you've set the
    // editor's size to whatever you need it to be.
    setSize (200, 200);
    
    // add gainSlider, make rotary, set range and startup value.
    addAndMakeVisible(panPosition);
    panPosition.setSliderStyle(juce::Slider::RotaryVerticalDrag);
    panPosition.setRange(0.0f, 100.0f);
    panPosition.setValue(50.0f);
    panPosition.getLookAndFeel().setColour(juce::Slider::rotarySliderFillColourId, juce::Colour (101,191,116));
    panPosition.getLookAndFeel().setColour(juce::Slider::rotarySliderOutlineColourId, juce::Colour (87, 87, 87));
    getLookAndFeel().setColour(juce::Slider::thumbColourId, juce::Colour (101,191,116));
    
    SliderAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(audioProcessor.aptvs, "PanPosition", panPosition);
    
    // Button.
    juce::Path buttonShape;
    panMode.setClickingTogglesState(true);
    buttonShape.addEllipse(100, 100, 100, 100);
    panMode.setShape(buttonShape, false, false, false);
    addAndMakeVisible(panMode);
    panMode.addListener(this);
    panMode.setInterceptsMouseClicks(true, false);
    
    ButtonAttachment = std::make_unique<juce::AudioProcessorValueTreeState::ButtonAttachment>(audioProcessor.aptvs, "Mode", panMode);
    
    // remove gain value text box.
    panPosition.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::NoTextBox, true, 0, 0);
    
    addAndMakeVisible(border);
    border.setText("");
    border.getLookAndFeel().setColour(juce::GroupComponent::textColourId, juce::Colours::white);
    border.getLookAndFeel().setColour(juce::GroupComponent::outlineColourId, juce::Colour (28, 28, 28));
}

PannerWithGUIAudioProcessorEditor::~PannerWithGUIAudioProcessorEditor()
{
}

//==============================================================================
void PannerWithGUIAudioProcessorEditor::paint (juce::Graphics& g)
{
    g.fillAll(juce::Colour (28, 28, 28));
}

void PannerWithGUIAudioProcessorEditor::resized()
{
    panPosition.setBounds(50, 50, 100, 100);
    panMode.setTopLeftPosition(getWidth()/2, getHeight()/2);
    panMode.setBounds(80, 80, 40, 40);
    border.setBounds(5, 5, 190, 190);
}

void PannerWithGUIAudioProcessorEditor::buttonClicked (juce::Button *button)
{
}

void PannerWithGUIAudioProcessorEditor::buttonStateChanged(juce::Button *button)
{
    juce::Logger::writeToLog(std::to_string(button->getToggleState()));
    prevButtonState = button->getToggleState();

    if (button->getToggleState() == 0)
    {
        //Green
        panPosition.getLookAndFeel().setColour(juce::Slider::rotarySliderFillColourId, juce::Colour (101,191,116));
        panPosition.getLookAndFeel().setColour(juce::Slider::rotarySliderOutlineColourId, juce::Colour (87, 87, 87));
        getLookAndFeel().setColour(juce::Slider::thumbColourId, juce::Colour (101,191,116));
        border.setText("");
    }
    else
    {
        //Blue
        panPosition.getLookAndFeel().setColour(juce::Slider::rotarySliderFillColourId, juce::Colour (39,110,184));
        panPosition.getLookAndFeel().setColour(juce::Slider::rotarySliderOutlineColourId, juce::Colour (87, 87, 87));
        getLookAndFeel().setColour(juce::Slider::thumbColourId, juce::Colour (39,110,184));
        border.setText("");
    }
}

Editor.h

#pragma once

#include <JuceHeader.h>
#include "PluginProcessor.h"

//==============================================================================
/**
*/
class PannerWithGUIAudioProcessorEditor  : public juce::AudioProcessorEditor,
                                           public juce::Button::Listener
{
public:
    PannerWithGUIAudioProcessorEditor (PannerWithGUIAudioProcessor&);
    ~PannerWithGUIAudioProcessorEditor() override;

    //==============================================================================
    void paint (juce::Graphics&) override;
    void resized() override;

private:

    juce::Slider panPosition;
    juce::ShapeButton panMode;
    juce::GroupComponent border;

    std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> SliderAttachment;
    std::unique_ptr<juce::AudioProcessorValueTreeState::ButtonAttachment> ButtonAttachment;
    
    void buttonClicked (juce::Button *button) override;
    void buttonStateChanged (juce::Button *button) override;
    int prevButtonState;
    
    PannerWithGUIAudioProcessor& audioProcessor;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PannerWithGUIAudioProcessorEditor)
};

ChatGPT can fix this code for you quite effectively.

Try to understand what ->load() is doing and why/when you need to use it.

void PannerWithGUIAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    juce::ScopedNoDenormals noDenormals;
    auto totalNumInputChannels  = getTotalNumInputChannels();
    auto totalNumOutputChannels = getTotalNumOutputChannels();

    // Clear any output channels that don't have input data
    for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear(i, 0, buffer.getNumSamples());
    
    // Retrieve pan position and mode state
    auto *panPosition = aptvs.getRawParameterValue("PanPosition");
    auto *buttonState = aptvs.getRawParameterValue("Mode");

    float pan = panPosition->load();
    int mode = static_cast<int>(buttonState->load());  // Ensure integer comparison

    DBG("Pan Position: " << pan);
    DBG("Mode: " << mode);

    // Calculate panning values
    float pLinear = (pan + 1.0f) / 2.0f;
    float pConstantPower = (M_PI * (pan + 1.0f)) / 4.0f;

    // Ensure stereo processing
    if (totalNumInputChannels >= 2)
    {
        auto* leftChannel = buffer.getWritePointer(0);
        auto* rightChannel = buffer.getWritePointer(1);
        
        for (int i = 0; i < buffer.getNumSamples(); i++)
        {
            if (mode == 0) // Linear panning
            {
                leftChannel[i] *= (1.0f - pLinear);
                rightChannel[i] *= pLinear;
            }
            else // Constant power panning
            {
                leftChannel[i] *= cos(pConstantPower);
                rightChannel[i] *= sin(pConstantPower);
            }
        }
    }
}