목록개발 공부/Juce 공부방 (40)
음악, 삶, 개발
Adobe 의 Illustrator 를 보면 아래와 같은 Gradient 패널을 볼수있다. Gradient 는 Linear 와 Radial 라는 2개의 종류로 나뉜다. Linear : 시작점에서 끝점으로. Radial : 중심에서 바깥으로, 우리가 일러스트레이터에서 에서 Gradient 를 만들듯이, Juce 에서 이를 코드로써 표현하면 된다. 하지만, 이런 Gradient 디자인을 코드로 하기전에, 일러스트레이터로 먼저 작업해봄으로써 디자인을 확정하는것이 많은 프로그래머들이 추천하는 방식이다. 코드는 계속해서 컴파일을 해야 결과를 볼수있기때문에, 컴파일을 해가며 디자인을 해나가는것은 굉장히 시간 낭비이기때문이다. 결국 훌륭한 GUI 디자인을 위해서, 더나아가 VST 개발을 위해 Illust..
class Plugin : public juce::AudioProcessor {} class PluginWindow : public juce::AudioProcessorEditor {} class MidiEffect {}
Juce 는 굉장히 거대한 프레임워크이기때문에, 바로 디테일로 들어가면 이해가 하나도 안된다. 따라서 가장 기본이 되는 VST3 의 골격 구조를 코드로 정리해놓고, 머리속에 넣어두자. Juce 에서 VST3 을 만들때 가장 필수 클래스는 juce::AudioProcessor 와 juce::AudioProcessorEditor 이다. 이 둘을 상속받아 클래스를 만들고, 그후 하위 클래스들을 객체로 배치해나가면서 플러그인을 만드는것이다. 나는 미디 플러그인을 기준으로, 필요한 클래스는 다음과 같다. 1. Main.cpp : createPluginFilter() 를 실행하며, Juce 에서는 main() 함수 역할을 한다. 2. 파생클래스 from juce::AudioProcessor (추상클래스) : Val..
기본 Juce 의 GUI 를 사용하는 방법은 2가지가 있다. 1. 내가 직접 그린다. = Component 클래스를 상속받아 paint() 를 override 한다. 2. Juce 가 주는 GUI 를 사용한다 = Component 클래스를 상속받은 클래스에 private member 로 GUI 객체를 추가한다. 3. 내가 만든 Component 클래스를 다른 Component 클래스의 멤버로 사용한다. (부모 자식 관계) - 일종의 포토샵 레이어 내가 직접 그린다. = Component 클래스를 상속받아 paint() 를 override 한다. 1. Component 클래스를 상속받은 클래스를 생성한다. 2. paint() 를 override 하여, 이 안에 그린다. 3. resized() 라는 콜백안에..
설명 valueTree 는 내가 Max 에서 사용했던 dict 와 같은 것이다. 플러그인의 파라미터들 저장하고, 변경하고 다른 클래스의 객체들과 송신하는것이다. valueTree 에서 행해지는 변화는 juce::ValueTree::Listener 를 사용하여 notify 받는다. 중요한건, 반드시 tree.addListener(this) 를 constructor 로 호출해야한다. 이 valueTree 는 복사해도 실제로 복사되지않고, 하나인 global 로 존재한다고한다. 따라서 이 valueTree 를 다른 클래스의 객체로 넘길때 pass-by-value 해도 실제로 복사되지는않는다고한다. 아래와 같이 다른 class 가 valueTree 가 변화될때 캐치할수있도록 한다. 아래는 Component 클래..
몇번이고 까먹어서, 여기에 정리해놓으려한다. 무조건 juce::AudioProcessor 를 상속받은 main processor 에서 정의되어야한다. 결국 valueTree 를 지니고있는 AudioProcessorValueTreeState 의 객체를 생성후, 이안에 add 한다. 이 apvts 안에는 state 라는 valueTree 가 있는데, 이 state 를 통해 다른 클래스의 객체들과 송신한다. (gui callback 같은) class MainProcessor : public juce::AudioProcessor { public : MainProcessor() // 3. 초기화 : apvts(*this, nullptr, "valueTreeName", createParams()) { } // 2...
Max 에서는 screensize 라는 오브젝트가 있는데, Juce 에서는 Desktop 이라는 클래스를 통해 얻어와야한다. 조금은 복잡하다. const auto userMonitor = juce::Desktop::getInstance().getDisplays().getMainDisplay().totalArea; DBG(userMonitor.getWidth()); // 2560 DBG(userMonitor.getHeight()); // 1600 일단 juce::Desktop::getInstance() 함수로 Desktop instance 를 얻고, 이 instance 에 다시 getDisplays() 를 호출하여 디스플레이"들" 을 얻고, (모니터가 여러대 일수도있으므로) 이중 사용자의 주요 디스플레이를..
VST3 를 컴파일할수있는 가장 기본적인 코드. 이 코드를 기본으로 깔고, 기능을 만들어가면됨. #include class MainProcessor : public juce::AudioProcessor { public: MainProcessor() : AudioProcessor(BusesProperties().withOutput("Output", juce::AudioChannelSet::stereo(), true)) { } ~MainProcessor() override { } bool hasEditor() const override { return true; } juce::AudioProcessorEditor* createEditor() override; const juce::String getName(..
코드 class Arp : public juce::AudioProcessor { public : void prepareToPlay(double sampleRate, int maximumExpectedSamplesPerBlock) override { notes.clear(); // [1]: First, we empty the SortedSet of MIDI note numbers. currentNote = 0; // [2]: The currentNote variable temporarily holds the current index for the SortedSet of notes. lastNoteValue = -1; // [3]: The lastNoteValue variable temporarily hol..
코드 void transposeByInterval(juce::MidiBuffer& midiBuffer, int interval) { juce::MidiBuffer transposedMidi; for (const auto metaData : midiBuffer) { auto midiMessage { metaData.getMessage() }; if (midiMessage.isNoteOnOrOff()) { midiMessage.setNoteNumber(midiMessage.getNoteNumber() + interval); transposedMidi.addEvent(midiMessage, metaData.samplePosition); } } midiBuffer.swapWith(transposedMidi); ..