ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 튜닝 모드 변경
    JDTuner/개발기록 2026. 4. 23. 15:46

    환절기에 골골대느라 2주를 날렸다.

    꽃가루 알레르기, 비염, 감기 난리가 해가 갈수록 심해진다...

     

    이 프로젝트의 마지막으로 추가할 기능인 튜닝 모드 변경 기능을 만들어봤다.

     

    대상 주파수의 외부 주입

    TunerResult JDTuner::getGuitarTunerResult(float frequency)
    {
      if (frequency < 40.0f || frequency > 500.0f)
        return {result};
    
      // 1. 기타 6줄의 표준 주파수 배열
      float guitarStrings[] = {82.41f, 110.00f, 146.83f, 196.00f, 246.94f, 329.63f};
      const char *guitarNoteNames[] = {"6E", "5A", "4D", "3G", "2B", "1E"};
      
      // 이 주파수 배열을 이용한 주파수 검출...
    
    }

     

    기존은 위와 같이 함수 내에서 목표 주파수와 노트를 직접 입력해놓은 코드였다.

    튜닝 모드를 변경하기 위해서는 이런 하드 코딩보단 외부에서 받아서 사용할 필요가 있었다.

     

    프리셋 생성

      presetDictionary = {
        {"GuitarStandardE", {
          {82.41f, "6E"}, {110.00f, "5A"}, {146.83f, "4D"},
          {196.00f, "3G"}, {246.94f, "2B"}, {329.63f, "1E"}
        }},
        {"GuitarDropD", {
          {73.42f, "6D"}, {110.00f, "5A"}, {146.83f, "4D"},
          {196.00f, "3G"}, {246.94f, "2B"}, {329.63f, "1E"}
        }},
        
        // ...
      };

     

    presetDictionary 프로퍼티를 만들고 튜너 생성시 초기화 되도록 만들었다.

    이것도 별도의 객체로 만들어 놓고 싶었지만 지금은 거기까진 필요없어서 일단 이렇게 했다.

     

    튜닝 모드 변경 메서드 구현

    // JDTuner
    
    void JDTuner::setTuningMode(const std::string& modeName) {
      auto it = presetDictionary.find(modeName);
      
      if (it != presetDictionary.end()) {
        targetNotes = it->second;
      } else {
        targetNotes = presetDictionary.at("GuitarStandardE");
      }
    }
    
    // JDTunerEngine
    
    void JDTunerEngine::setTuningMode(const std::string &modeName) {
      jdTuner.setTuningMode(modeName);
    }
    
    // JDTunerWrapper
    
    - (void)setTuningMode:(NSString *)modeName {
      if (engine) {
        std::string cppModeName = [modeName UTF8String];
        engine->setTuningMode(cppModeName);
      }
    }

     

    튜너부터 시작해 engine, wrapper에서 각각 튜닝 모드 변경 메서드를 만들어

    뷰에서 wrapper의 메서드를 사용하도록 만들었다.

     

    뷰 구현

    // enum
    enum TuningMode: String, CaseIterable {
      case guitarStandard = "GuitarStandardE"
      case guitarDropD = "GuitarDropD"
      case bassStandard = "BassStadardE"
      
      var displayName: String {
        switch self {
        case .guitarStandard: return "Guitar Standard (E)"
        case .guitarDropD: return "Guitar Drop D"
        case .bassStandard: return "Bass Standard (E)"
        }
      }
    }
    
    // State...
    
    @State private var selectedMode: TuningMode = .guitarStandard
    
    
    // View...
         HStack {
              Text("Tuning Mode")
                .font(.headline)
                .foregroundColor(.white.opacity(0.6))
              
              Spacer()
              
              Picker("Tuning Mode", selection: $selectedMode) {
                ForEach(TuningMode.allCases, id: \.self) { mode in
                  Text(mode.displayName).tag(mode)
                }
              }
              .pickerStyle(.menu)
              .tint(.white)
              .lineLimit(1)
              .fixedSize(horizontal: true, vertical: false)
              // 값이 변경될 때마다 C++ Wrapper로 전달
              .onChange(of: selectedMode, initial: false, { oldValue, newValue in
                if oldValue != newValue {
                  wrapper.setTuningMode(newValue.rawValue)
                }
              })
            }
            .padding(.horizontal, 24)
            .padding(.top, 20)

     

    열거형을 정의하고 (지금보니까 오타가 있는데 나중에 수정해야겠다) 간단한 Picker를 만들어 튜닝 모드를 변경했다.

     

    결과

    결과 영상

     

    튜닝 모드까지 변경하는 기능을 만들었다.

    마지막으로 실기기 테스트와 시연 영상 만들고 이 프로젝트는 마무리 예정!

    마무리 포스트에 소감을 작성하겠지만 c++보다 iOS쪽 작업이 더 많았다...

    얼른 마무리하고 다음 프로젝트로 가야지!!!

    'JDTuner > 개발기록' 카테고리의 다른 글

    완성 및 마무리  (0) 2026.05.04
    프로젝트 구조 변경 - 튜너를 외부로 분리  (0) 2026.04.03
    UI 수정  (0) 2026.03.15
    정확도 개선 2 - 1차 IIR 필터  (0) 2026.03.11
    정확도 개선 1 - Parabolic Interpolation  (0) 2026.03.11
Designed by Tistory.