-
소리 데이터를 받아보자JDTuner/개발기록 2026. 2. 19. 19:17
튜너 알고리즘을 돌리기 전에 일단 소리 데이터를 받아서 확인할 필요가 있다.
juce::AudioIODeviceCallback 상속
class JDTunerEngine: public juce::AudioIODeviceCallback먼저 튜너 엔진 헤더 파일에서 juce::AudioIODeviceCallback 상속 코드를 작성해준다.
그러면 아래 이미지 처럼 에러가 발생하는데 추상 클래스 상속으로
필요 메서드 구현이 필요해서 나오는 에러다.
Swift에 익숙한 나는 왜 구현해야되는 메서드를 안알려줘???????? 이랬지만
c++은 그렇다고 한다.

추상 클래스 상속시 필수 메서드를 구현 안했을때 발생 어떤 메서드를 구현해야 하는지는
1. 해당 추상 클래스의 정의로 들어가서 메서드가 = 0 인 것
2. 이 추상 클래스를 상속한 이유가 되는 메인 기능 메서드
이 두개를 구현하면 된다고 한다 c++에 익숙해지면 어떤걸 구현해야하는지 파악이 빨라지겠지??
어쩌면 JUCE가 버전이 올라가면서 생긴 문제일거 같기도 하다.
그러면 아래의 3개의 메서드를 정의 해줘야한다.
audioDeviceIOCallbackWithContext
audioDeviceAboutToStart
audioDeviceStopped
필수 메서드 정의
class JDTunerEngine: public juce::AudioIODeviceCallback { public: // ... void audioDeviceIOCallbackWithContext( const float *const *inputChannelData, int numInputChannels, float *const *outputChannelData, int numOutputChannels, int numSamples, const juce::AudioIODeviceCallbackContext &context) override; void audioDeviceAboutToStart(juce::AudioIODevice *device) override; void audioDeviceStopped() override; // ... private: // ... }그런데 첫번째 메서드의
const float *const * 타입이 대체 뭐지?????????? 포인터 하나는 익숙해졌는데 2개가 나오면서 뇌가 다시 꼬인다.
포인터는 기본적으로 배열이다. 첫번째 메모리 주소를 가르키고 있다.
근데 *가 두개니까 이중배열이라는 뜻. Swift로 치면 [[Float]]이다.
const가 붙어 있으니 내용의 수정이 불가능하다.
이렇게 c++을 또 공부했다.
AudioDeviceManager 정의 및 콜백 인스턴스 추가
AudioIODeviceCallback를 상속한 클래스의 인스턴스가 제대로 사용되려면
AudioDeviceManaager에 등록이 되어야 한다.
class JDTunerEngine: public juce::AudioIODeviceCallback { public: JDTunerEngine() { deviceManager.initialise(1, 0, nullptr, true); deviceManager.addAudioCallback(this); } ~JDTunerEngine(); // deviceManager에 이 인스턴스를 addAudioCallback 해야 아래 메서드가 실행된다 void audioDeviceIOCallbackWithContext(const float *const *inputChannelData, int numInputChannels, float *const *outputChannelData, int numOutputChannels, int numSamples, const juce::AudioIODeviceCallbackContext &context) override; void audioDeviceAboutToStart(juce::AudioIODevice *device) override; void audioDeviceStopped() override; float getValue(); private: // 콜백 추가를 위한 AudioDeviceManager juce::AudioDeviceManager deviceManager; // 튜너 알고리즘 처리 후 뷰로 보낼 값 float value; }최종적으로 헤더 파일은 위와 같이 작성했고
initializer에서 deviceManager를 초기화 해주고 이 인스턴스를 추가해준다.
각 메서드 구현
void JDTunerEngine::audioDeviceIOCallbackWithContext(const float *const *inputChannelData, int numInputChannels, float *const *outputChannelData, int numOutputChannels, int numSamples, const juce::AudioIODeviceCallbackContext &context) { // 1. 입력 데이터 const float* inLeft = inputChannelData[0]; // 2. 입력된 소리의 볼륨 확인. 일정 이상일때만 튜너 알고리즘 실행 예정 float magnitude = 0.0f; for (int i = 0; i < numSamples; ++i) magnitude += std::abs(inLeft[i]); magnitude /= (float)numSamples; // 평균 볼륨 // 3. 이후 튜너 알고리즘 // 이번 작업에는 magnitude 값을 앱에 표시하는것까지 value = magnitude; std::string log = std::to_string(magnitude); juce::Logger::writeToLog(log); }.cpp 파일에서 구현 내용을 작성한다.
입력은 모노로 받기 때문에 첫번째 채널을 사용했고
입력된 소리의 크기의 평균값을 구해서 출력해보는 코드이다.
이제 디바이스에 빌드해서 확인해보자!!
결과

디바이스 자리가 없다 친구비를 안낸자의 최후
멤버십때 디바이스 등록을 몇개 했었는데 만료됐고
무료 프로비저닝은 디바이스 자리가 3개라서 자리가 없다고 이런 에러가 나왔다.
근데 왜 내 폰이 등록이 안되어 있는거지??
디바이스 목록은 이메일로 문의해서 삭제가 가능하다고 해서 문의 메일을 보낸 상태다.
해결되면 바로 magitude값 확인 후 본격적인 튜너 알고리즘 작업 예정!!
'JDTuner > 개발기록' 카테고리의 다른 글
주파수 검출 구현하기 2. (1) 2026.02.24 주파수 검출 구현하기 1. (0) 2026.02.20 디바이스 삭제와 마이크 입력 확인 (0) 2026.02.20 c++ 와 Swift 사이 값 주고 받기 (0) 2026.02.19 Objective-C 첫사용 (0) 2026.02.13