음악, 삶, 개발
미디 노트 Transpose 하기. 본문
코드
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);
}
설명
Juce 에서는 모든 midi 프로세싱은 processBlock 함수안에서 실행된다.
processBlock 함수는, 추상 클래스인 juce::AudioProcessor 안에서 순수 가상 함수 (pure virtual) 로 존재하기때문에,
반드시 나의 클래스에서 구현해야한다.
사용된 Juce 클래스
juce::MidiBuffer
juce::MidiMessageMetadata
juce::MidiMessage
개념적으로, MidiBuffer 안에 MidiMessageMetaData 가 존재하고,
MidiMessageMetaData 안에 MidiMessage 가 존재한다.
MidiMessage 안에 존재하는 미디 정보들은 여러 get 함수들로 가져올수있고,
set 함수로 메세지를 변경할수있다.
(MidiMessage 클래스는 꽤나 거대해서, 다른 포스트로 정리하도록 하겠다.)
시각적으로 표현하면 아래와 같다.
MidiBuffer -> MidiMessageMetaData -> MidiMessage -> 채널, 노트, 벨로시티등등..(get 함수로 가져옴)
사용된 Juce 함수
for (const juce::MidiMessageMetadata metaData : midiBuffer)
processBlock 안에서 midiBuffer 안에 MidiMessageMetaData type 의 객체를 range for 루프로 iteration 해야한다
위의 코드에서 const juce::MidiMessageMetaData 를 const auto 로 변경할수있다.
일단 공부하기위해 적어놓았다.
MidiMessageMetadata::getMessage() : MidiMessage 객체를 return 한다.
MidiMessage::isNoteOnOrOff() : 이 미디 메세지가 note on 또는 off 메세지인지 알려주는 bool 을 return
MidiMessage::setNoteNumber(const int newNoteNumber) : newNoteNumber 로 미디 메시지 노트 변경.
MidiBuffer::addEvent (const MidiMessage& m, int sampleNumber): sampleNumber 위치에, m 이라는 미디메세지 추가.
MidiBuffer::swapWith (MidiBuffer& other) : 다른 MidiBuffer 객체로 변경.