음악, 삶, 개발

DAW 의 파라미터에 대한 모든것 : 파트2 본문

개발 공부/Juce 공부방

DAW 의 파라미터에 대한 모든것 : 파트2

Lee_____ 2020. 10. 12. 20:37

앞선 포스트에서 우리의 고민 사항은 아래와 같았다.

 

1. 어디에 나의 파라미터를 추가할것인지?

2. 어떻게 나의 파라미터를 추가할수있는지? 

3. 어떻게 나의 VST 출력은 이 파라미터 값을 반영할수있는지? 

4. 어떻게 나의 파라미터를 GUI 에 연결할수있는지? 

5. 어떻게 나의 파라미터 값을 이 GUI 로 변경할수있는지?


< 해결된 문제 >

1. 어디에 나의 파라미터를 추가할것인지?

2. 어떻게 나의 파라미터를 추가할수있는지?  

 

를 해결하여 아래의 코드를 완성했다.

class VSTPlugin  : public juce::AudioProcessor {

    public :

        VSTPlugin() : apvts(*this, nullptr, juce::Identifier("APVTS"), createParams()) // apvts 초기화!
        
        {



        }
		
        // 2. 어떻게 나의 파라미터를 추가할수있는지?
        using Params = juce::AudioProcessorValueTreeState::ParameterLayout;
        using ParamInt = juce::AudioParameterInt;
		
        Params createParams() {

            Params params;
	
            params.add(std::make_unique<ParamInt>("Test", "Test", 0, 10, 0)); // Id, Display Name, Min, Max, Default

            return params;

        }


    private :

        juce::AudioProcessorValueTreeState apvts; // 1. 어디에 나의 파라미터를 추가할것인지? apvts 객체 생성!

}

이제 다음 문제들을 해결해보자.


3. 어떻게 나의 VST 출력은 이 파라미터 값을 반영할수있는지? 

 

VST 출력은 곧 audio thread 이다.

결국 audio thread 에서 apvts 에 접근을 해야하는데,

 

apvts.getRawParameterValue(Stringref paramterID) 

apvts.getParameter(Stringref paramterID) 

 

위의 두개의 방법중 하나를 사용한다.

이때 thread 안전성에 대해 걱정을 했는데,

Peter 말에 의하면,

Parameter APVTS 와 약간 독립적으로 존재한다고한다.

따라서 processBlock() 안에서 위의 함수들을 호출하는것은 APVTS 를 읽거나 쓰는것이 아니라고한다.

(이게, APVTS 를 읽는 행위가 아니라면, 무엇이 읽는것이는 추후 물어보고 설명하겠음)

따라서 thread 안전하다고..

 

< 결과물 >

class VSTPlugin  : public juce::AudioProcessor {

    public :

        VSTPlugin() : apvts(*this, nullptr, juce::Identifier("APVTS"), createParams()) // apvts 초기화!
        
        {
            
            // 3.2 init testParameter
            testParameter = apvts.getRawParameterValue("test"); 

        }
		
        // 2. 어떻게 나의 파라미터를 추가할수있는지?
        using Params = juce::AudioProcessorValueTreeState::ParameterLayout;
        using ParamInt = juce::AudioParameterInt;
		
        Params createParams() {

            Params params;
	
            params.add(std::make_unique<ParamInt>("test", "Test", 0, 10, 0)); // Id, Display Name, Min, Max, Default

            return params;

        }

        // 3. 어떻게 나의 VST 출력은 이 파라미터 값을 반영할수있는지? 
        void processBlock (juce::AudioSampleBuffer& buffer, juce::MidiBuffer& midiBuffer) override {

            auto test = *testParameter; // 3.3 get testParameter as dereferencing.
            
            /*

                Use test parameter's value here!

            */
            
        }


    private :

        juce::AudioProcessorValueTreeState apvts; // 1. 어디에 나의 파라미터를 추가할것인지? apvts 객체 생성!

        std::atomic<int>* testParameter {nullptr}; // 3.1 create pointer of test parameter.
        
}

< 추가 : Peter 와의 대화후..>

 

위의 코드처럼, atomic 포인터를 만들 필요없이 바로 processBlock() 에서 읽어드려도 된다.

class VSTPlugin  : public juce::AudioProcessor {

    public :

        VSTPlugin() : apvts(*this, nullptr, juce::Identifier("APVTS"), createParams()) // apvts 초기화!
        
        {
            

        }
		
        // 2. 어떻게 나의 파라미터를 추가할수있는지?
        using Params = juce::AudioProcessorValueTreeState::ParameterLayout;
        using ParamInt = juce::AudioParameterInt;
		
        Params createParams() {

            Params params;
	
            params.add(std::make_unique<ParamInt>("test", "Test", 0, 10, 0)); // Id, Display Name, Min, Max, Default

            return params;

        }

        // 3. 어떻게 나의 VST 출력은 이 파라미터 값을 반영할수있는지? 
        void processBlock (juce::AudioSampleBuffer& buffer, juce::MidiBuffer& midiBuffer) override {

            auto value = *(apvts.getRawParameterValue("test")); // 포인터 역참조!

            /* use value here! */
            
        }


    private :

        juce::AudioProcessorValueTreeState apvts; // 1. 어디에 나의 파라미터를 추가할것인지? apvts 객체 생성!

        
}

 

참고링크 : https://forum.juce.com/t/getrawparametervalue-vs-getparameter/38395


< 다음 단계로..>

 

1,2,3 단계의 가장 중요한 단계를 해결하였다.

이제 AudioProcessor 의 서브 클래스안에서 해야할 모든것은 끝이 났다.

이 단계들이 선행되어야 GUI 단계에서 뭘 할수있는것이다.