The synthesizer software adds a volume adjustment button

I added a button to my midi tutorial code to adjust my synthesizer volume, and it had no effect. I hope you can help me see, thank you.

struct SineWaveSound : public juce::SynthesiserSound {
SineWaveSound() {}

bool appliesToNote(int) override { return true; }
bool appliesToChannel(int) override { return true; }

};

//==============================================================================
struct SineWaveVoice : public juce::SynthesiserVoice {
SineWaveVoice() {}

bool canPlaySound(juce::SynthesiserSound* sound) override {
    return dynamic_cast<SineWaveSound*> (sound) != nullptr;
}

void startNote(int midiNoteNumber, float velocity, juce::SynthesiserSound*, int /*currentPitchWheelPosition*/) override {
    currentAngle = 0.0;
    level = velocity * 0.15;
    tailOff = 0.0;

    auto cyclesPerSecond = juce::MidiMessage::getMidiNoteInHertz(midiNoteNumber);
    auto cyclesPerSample = cyclesPerSecond / getSampleRate();

    angleDelta = cyclesPerSample * 2.0 * juce::MathConstants<double>::pi;
}

void stopNote(float /*velocity*/, bool allowTailOff) override {
    if (allowTailOff) {
        if (tailOff == 0.0)
            tailOff = 1.0;
    }
    else {
        clearCurrentNote();
        angleDelta = 0.0;
    }
}

void pitchWheelMoved(int) override {}
void controllerMoved(int, int) override {}

void renderNextBlock(juce::AudioSampleBuffer& outputBuffer, int startSample, int numSamples) override {
    if (angleDelta != 0.0) {
        if (tailOff > 0.0) {
            while (--numSamples >= 0) {
                auto currentSample = (float)(std::sin(currentAngle) * level * tailOff);

                for (auto i = outputBuffer.getNumChannels(); --i >= 0;)
                    outputBuffer.addSample(i, startSample, currentSample);

                currentAngle += angleDelta;
                ++startSample;

                tailOff *= 0.99;

                if (tailOff <= 0.005) {
                    clearCurrentNote();

                    angleDelta = 0.0;
                    break;
                }
            }
        }
        else {
            while (--numSamples >= 0) {
                auto currentSample = (float)(std::sin(currentAngle) * level);

                for (auto i = outputBuffer.getNumChannels(); --i >= 0;)
                    outputBuffer.addSample(i, startSample, currentSample);

                currentAngle += angleDelta;
                ++startSample;
            }
        }
    }
}

void setLevel(float newLevel) {
    level = newLevel * 0.15; 
}

private:
double currentAngle = 0.0, angleDelta = 0.0, level = 0.0, tailOff = 0.0;
};

//==============================================================================
class SynthAudioSource : public juce::AudioSource {
public:
SynthAudioSource(juce::MidiKeyboardState& keyState) : keyboardState(keyState) {
for (auto i = 0; i < 4; ++i)
synth.addVoice(new SineWaveVoice());

    synth.addSound(new SineWaveSound());
}

void setUsingSineWaveSound() {
    synth.clearSounds();
}

void prepareToPlay(int /*samplesPerBlockExpected*/, double sampleRate) override {
    synth.setCurrentPlaybackSampleRate(sampleRate);
}

void releaseResources() override {}

void getNextAudioBlock(const juce::AudioSourceChannelInfo& bufferToFill) override {
    bufferToFill.clearActiveBufferRegion();

    juce::MidiBuffer incomingMidi;
    keyboardState.processNextMidiBuffer(incomingMidi, bufferToFill.startSample, bufferToFill.numSamples, true);

    synth.renderNextBlock(*bufferToFill.buffer, incomingMidi, bufferToFill.startSample, bufferToFill.numSamples);
}

void setVolume(float newVolume) {
    for (auto i = 0; i < synth.getNumVoices(); ++i) {
        if (auto voice = dynamic_cast<SineWaveVoice*>(synth.getVoice(i))) {
            voice->setLevel(newVolume);
        }
    }
}

private:
juce::MidiKeyboardState& keyboardState;
juce::Synthesiser synth;
};

//==============================================================================
class MainContentComponent : public juce::AudioAppComponent,
private juce::Timer,
public juce::Slider::Listener {
public:
MainContentComponent() : synthAudioSource(keyboardState),
keyboardComponent(keyboardState, juce::MidiKeyboardComponent::horizontalKeyboard) {
addAndMakeVisible(keyboardComponent);
setAudioChannels(0, 2);

    volumeSlider.setRange(0.0, 1.0, 0.01);
    volumeSlider.setValue(0.5);
    volumeSlider.addListener(this);
    addAndMakeVisible(volumeSlider);

    volumeLabel.setText("Volume", juce::dontSendNotification);
    addAndMakeVisible(volumeLabel);

    setSize(600, 200);
    startTimer(400);
}

~MainContentComponent() override {
    shutdownAudio();
}

void resized() override {
    auto area = getLocalBounds();

    keyboardComponent.setBounds(area.removeFromTop(area.getHeight() - 50));

    auto sliderArea = area.removeFromBottom(50).reduced(10);
    volumeLabel.setBounds(sliderArea.removeFromLeft(80));
    volumeSlider.setBounds(sliderArea);
}

void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override {
    synthAudioSource.prepareToPlay(samplesPerBlockExpected, sampleRate);
}

void getNextAudioBlock(const juce::AudioSourceChannelInfo& bufferToFill) override {
    synthAudioSource.getNextAudioBlock(bufferToFill);
}

void releaseResources() override {
    synthAudioSource.releaseResources();
}

void sliderValueChanged(juce::Slider* slider) override {
    if (slider == &volumeSlider) {
        synthAudioSource.setVolume(volumeSlider.getValue());
    }
}

private:
void timerCallback() override {
keyboardComponent.grabKeyboardFocus();
stopTimer();
}

juce::MidiKeyboardState keyboardState;
SynthAudioSource synthAudioSource;
juce::MidiKeyboardComponent keyboardComponent;
juce::Slider volumeSlider;
juce::Label volumeLabel;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainContentComponent)

};