목록juce (34)
음악, 삶, 개발
processBlock(); 은 DAW 가 호출하는 AudioProcessor 클래스의 pure virtual 함수이다. 따라서 이 클래스의 서브 클래스는 반드시 이 함수를 정의해줘야한다. 이 함수는 내가 호출하지않고, DAW 가 호출하는 콜백함수이다. 오디오와 미디 프로세싱이 일어나는 가장 초입이라고 할수있다. 아래의 오디오 인터페이스 셋팅이 있다고 가정해보자. Sample Rate : 48000 Buffer Size : 512 Latency : 10.75ms 샘플레이트만 생각하면 1초에 48000번을 샘플링한다. 하지만 오디오 프로세싱은 샘플 하나 하나를 처리하지않고, 일정량을 모아서 처리하는데, 이 일정..
Juce 미디 메세지 클래스가 아닌, 말 그대로 미디 메세지에 대해 알아보려 한다. MIDI Message 에 관하여 Summary of MIDI Messages MIDI에서 사용되는 NRPN과 RPN system Exclusive,nrpn,rpn 이해가 안됩니다. It's about time. Timing in MIDI files Tempo-relative timing in Max
아직 Juce 로 Step Sequencer 를 만드는것에 대해 명확한 답을 찾지못했다. 포럼에 있는 포스팅들을 다 찾아보자 MidiMessageSequence MidiMessageSequence::MidiEventHolder MidiMessage MidiMessageMetadata MidiBuffer MidiBufferIterator MidiBuffer::Iterator MidiFile Problem making a step sequencer Best practice for timing (Audio thread) Best way to make scrollable/zoomable sequencer GUI Creating MIDI - some basic ques..
AudioPlayHead 클래스 AudioPlayHead::CurrentPositionInfo 클래스 아래는 AudioProcessor 클래스안에 getPlayHead() 함수에 대한 설명이다. 읽어보자. AudioPlayHead 클래스는 내가 단독으로 객체를 만들면 안되고, AudioProcessor 클래스안의 processBlock 함수에서 getPlayHead() 라는 함수를 통해 AudioPlayHead 객체에 접근해야한다. getPlayHead() 는 AudioPlayHead 포인터를 return 하는데, 이 포인터를 절대 저장하지말고, 오디오 thread 가 아닌곳에서 접근하려하지말라고한다. 한마디로 processBloc..
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...