| data_no | gall_date_title | data_nick | gall_tit_string | data_uid | data_ip | content | deleted_time | toxicity_score | question | media |
|---|---|---|---|---|---|---|---|---|---|---|
| 514730 |
2026-07-28 15:19:24 |
한플 | secs 알고리즘 gpt한테 던져봄[14] | znffjrznf123 | - | 역필터, 저역하한 탐색, 타겟 블렌딩, 피크크러시 이런것들 내가 구상하고 ai가 구축한건데 이렇게 보니까 새롭네 SECS.py 알고리즘 분석 요약 SECS는 측정 응답을 무조건 평탄하게 만드는 프로그램이 아니다. 측정 IR에서 신뢰 가능한 대역을 판별한 다음, 유효 대역에서는 이상적인 Target을 추종하고 저역·고역 한계에서는 스피커의 자연스러운 롤오프를 보존하는 적응형 보정 방식이다. 측정 IR WAV → 응답/위상 분석 → 적응형 Target 생성 → 역필터 생성 → 잔차 보정 → 지연 및 L/R 정렬 → WAV 저장 1. 입력된 측정치 해석 입력값은 주파수 응답 CSV가 아니라 Impulse Response WAV 다. 프로그램은 WAV 파일을 불러온 뒤 다음과 같이 전처리한다. 최대 절댓값이 1e-6 미만이면 무음으로 판단 입력 신호 중 최대 5초까지만 사용 FFT 계산에 적합한 길이로 zero padding Mono/Stereo 자동 판별 출력 Sample Rate가 다르면 polyphase 방식으로 리샘플링 측정 IR에서 추출하는 정보 측정 정보 알고리즘에서의 의미 가장 큰 Impulse 위치 음향 도달 시간과 L/R 시간차 계산 FFT 절댓값 스피커와 룸이 합쳐진 크기 응답 Minimum-phase 응답 크기 응답으로부터 예측되는 기본 위상 Excess phase Minimum phase만으로 설명되지 않는 실제 위상 저역·고역 감쇠 무리하지 않고 보정할 수 있는 자연 대역 한계 L/R Peak 주변 RMS 좌우 채널의 초기 Gain 차이 주파수 응답 스무딩 하나의 고정 스무딩을 전 대역에 적용하지 않는다. 100/150/200/300Hz를 경계로 5개 대역을 만들고, 각 대역에 서로 다른 Fractional Octave Smoothing을 적용한다. Normal 모드 기준으로 저역부터 대략 1/24, 1/12, 1/6, 1/3, 1 Octave 스무딩을 사용한다. 저역 공진은 비교적 세밀하게 분석 고역의 촘촘한 Comb Filtering은 강하게 평균화 기준 레벨 100Hz~10kHz 구간의 원래 Magnitude 중 35 Percentile 을 기준 크기(ref_mag)로 사용한다. ref_mag = percentile(|H|, 35) 평균값이나 최대값을 쓰는 것보다 룸 피크의 영향을 덜 받는 기준이다. 자연스러운 보정 대역 판정 저역 Cutoff: 1~10kHz 평균보다 6dB 낮은 레벨을 처음 통과하는 주파수. 최종 범위는 10~300Hz로 제한된다. 고역 Cutoff: 2~22.05kHz 응답의 95 Percentile보다 10dB 이상 낮지 않은 마지막 주파수. 최종 범위는 6~20kHz로 제한된다. 200~1000Hz 평균보다 약 30dB 이상 약한 저역은 신뢰도가 낮은 측정 구간으로 취급한다. 위상 해석 측정 Magnitude에서 Cepstrum 방식으로 Minimum-phase 응답을 만들고, 실제 측정 응답과의 차이로 Excess phase를 계산한다. Excess phase 역보정 ≈ conj(H_measured_aligned / H_minimum) 신호가 약한 주파수에서는 이 위상 역보정을 점진적으로 무보정 상태로 섞는다. 따라서 SNR이 나쁜 구간의 위상을 억지로 뒤집지 않는다. 참고로 코드의 _linearity_score() 는 이름과 달리 위상 직선성을 직접 측정하는 값은 아니다. 1~10kHz에서 초기 100ms와 100ms 이후 구간의 감쇠량을 비교하는 지표이며, 필터 생성에는 사용되지 않고 룸 어쿠스틱 추천 문구에만 사용된다. 2. Target 생성 핵심은 이상적인 평탄 응답과 측정된 자연 롤오프를 주파수별로 혼합하는 것이다. 기본 Ideal Target B(f) = [f⁴ / (f⁴ + 1⁴)] × [20000⁴ / (f⁴ + 20000⁴)] 가청대역에서는 거의 Flat이지만 DC와 20kHz 이상에서는 자연스럽게 감쇠하는 4차 필터 형태다. 측정 적응형 Target 먼저 측정 응답을 기준 레벨로 정규화한다. N(f) = Smoothed Measurement(f) / Reference 기준보다 낮은 부분만 자연 롤오프로 사용한다. 측정된 피크를 Target에 그대로 복사하지는 않는다. R(f) = min(1, N(f)) Track Weight를 w(f)라고 하면 다음 구간에서 1에 가까워진다. 검출된 저역 Cutoff 이하 고역 Cutoff 부근 및 그 이상 200Hz 이하에서 측정 신호가 매우 약한 구간 T0(f) = R(f)^w(f) × B(f)^[1-w(f)] w = 0: 이상적인 Flat Target 사용 w = 1: 측정된 자연 롤오프를 따라감 중간값: 두 응답을 로그 Magnitude 기준으로 혼합 1kHz 이상에서는 Target이 기본 Ideal보다 커지지 않도록 한 번 더 제한한다. 고역 롤오프를 무리하게 끌어올리지 않기 위한 처리다. Bass Boost Bass Gain dB(f) = 설정 Gain × fc² / (f² + fc²) 매우 낮은 주파수에서는 설정 Gain 전체가 적용되고, 지정한 Bass Frequency에서는 설정값의 절반 dB가 적용된다. 따라서 UI의 “dB @ Frequency”라기보다는 저역 Shelf의 전환 주파수에 가깝다. Tilt Tilt Gain dB(f) = Tilt × log2(f / 1000) 1kHz를 기준으로 옥타브당 설정 dB만큼 기울어진다. 단, Track Weight가 큰 자연 롤오프 구간에서는 Tilt도 약화된다. 3. 보정 과정 3-1. 초기 Magnitude 역필터 G_inv(f) = Target(f) / Normalized Measurement(f) 이 값을 사용자가 지정한 Boost 한도까지 제한한 다음, Cepstrum 방식으로 Minimum-phase 필터로 변환한다. mag_inv = clip(Target / Measurement, 0, 10^(Max Boost / 20)) 3-2. Curtain 처리 Curtain 주파수부터 그 2배 주파수까지 Magnitude 역보정을 Unity, 즉 무보정 상태로 Fade한다. 예를 들어 Curtain이 300Hz라면: 300Hz 이하: 계산된 Magnitude 보정 적용 300~600Hz: 보정을 점진적으로 해제 600Hz 이상: 초기 Magnitude 역필터는 Unity Curtain은 Minimum-phase Magnitude 역필터에 대한 경계다. Normal 모드의 Excess-phase 보정 전체를 끄는 경계는 아니다. 3-3. 동작 모드별 위상 보정 모드 보정 방식 Normal Minimum-phase Magnitude 보정과 Excess-phase 보정을 함께 적용. 저역은 설정 Delay 전체, 중역은 약 절반, 고역은 약 1/4 수준의 Pre-ringing만 허용한다. Low-Latency Excess-phase 보정을 사용하지 않고 Minimum-phase 필터만 사용. Stereo L/R 도달 시간은 정렬한다. Zero-Latency Minimum-phase 필터만 사용하며 L/R 정렬을 위한 추가 지연도 넣지 않는다. Normal 모드에서는 저역 역필터에 최대 500ms의 긴 Window, 고역에는 10ms의 짧은 Window를 사용한다. 저역 Decay는 충분히 표현하면서 고역 Ringing은 제한하려는 구조다. 3-4. 시뮬레이션 기반 잔차 보정 초기 필터를 측정 응답에 적용한 결과를 내부에서 시뮬레이션하고, Target과 다시 비교해 잔차를 보정한다. Macro EQ Target과 시뮬레이션 결과의 비율을 약 ±6dB로 제한해 보정한다. 10~20kHz에서는 양의 Boost만 점차 억제한다. 저역 Peak Crush Target보다 높은 부분만 검출해 Cut한다. 300Hz 이하는 적용, 300~500Hz는 Fade, 500Hz 이상에서는 적용하지 않는다. Tilt 적용 Tilt를 포함한 Post-EQ를 Minimum-phase 필터로 만들고 초기 필터와 결합한다. 즉 잔여 저역 Peak는 줄이지만, 저역 Null을 같은 강도로 억지로 채우지는 않는 방향이다. 3-5. 자동 Delay 선택 첫 측정의 Normal 모드에서는 2~10ms 후보를 1ms 간격으로 시험한다. 각 후보 필터를 측정 응답에 Convolution한 뒤, 자연 저역 Cutoff부터 300Hz까지 Target과의 오차를 계산한다. Metric = Weighted MAE + 0.35 × Shape MAE 낮은 주파수에 더 큰 가중치를 주며, Stereo 합산 평가에서는 두 채널의 합이 단일 채널보다 약 6dB 높다는 점을 Target에 반영한다. 3-6. Stereo 정렬 두 채널 중 더 늦게 도착한 Impulse를 기준으로 시간 정렬 Peak 주변 ±5ms RMS를 이용해 초기 Gain 정렬 보정 후 20~1000Hz의 L/R Median 차이를 다시 계산 R 채널을 최대 ±6dB 범위에서 추가 조정 3-7. 최종 출력 Filter Peak 앞에 선택한 Delay만큼 샘플이 남도록 약 510ms 길이로 Crop 마지막 5ms에 제곱 형태의 Fade-out 적용 Filter의 최대 주파수 Magnitude가 1을 넘으면 전체 정규화 Mono 또는 L/R 개별 FLOAT WAV 파일로 저장 4. 코드상 주의할 점 1. rm_eq는 현재 실질적으로 동작하지 않음 코드에서 rm_eq는 항상 1인 배열이다. 실제 Room Mode Cut 역할은 저역 Peak Crush가 담당한다. 2. Boost는 최종 필터 전체의 절대 상한이 아님 Boost 제한은 초기 역필터에 적용된다. 이후 Macro EQ와 Tilt가 추가되므로 최종 필터의 Boost가 설정값을 완전히 넘지 않는다고 보장되지는 않는다. 3. 자동 Delay Fine Search가 비활성화되어 있음 0.5ms 단위 관련 상수는 존재하지만 실제 자동 검색은 enable_stage2=False라서 1ms 단위로만 수행된다. 4. Stereo Preview의 Delay 평가는 왼쪽 채널 중심 Preview에서는 처리 속도를 위해 왼쪽 채널만 이용해 Delay 후보를 평가한다. 따라서 최종 L+R 합산 기준 최적 Delay와 차이가 날 수 있다. 5. Preamp 표시값 해석에 주의 저장되는 Filter는 이미 최대 Magnitude 1로 정규화된다. 그런데 UI에는 정규화 이전 Gain에 해당하는 음수 Preamp도 표시된다. 저장된 Filter에 이 음수 Preamp를 별도로 다시 적용하면 감쇠가 중복될 가능성이 있다. 최종 평가 SECS는 단순한 Full-band Inverse EQ가 아니라 측정 신뢰도에 따라 보정 강도를 바꾸는 적응형 Mixed-phase 보정기 에 가깝다. 중심 대역은 이상적인 Target을 적극적으로 추종 자연스러운 저·고역 한계에서는 측정 롤오프를 보존 저역 Peak는 세밀하게 Cut 신호가 약한 구간의 과도한 Boost와 위상 역보정은 억제 Normal 모드에서는 제한적인 Excess-phase 보정까지 수행 전체적으로 룸과 스피커의 측정 한계를 어느 정도 인정하면서 과도한 역보정을 피하도록 설계된 알고리즘이라고 볼 수 있다. | - | 0.01 | - | 1 |
| comment_no | parent_no | user_id | name | ip | reg_date | memo | depth | c_no | w_del | del_time |
|---|---|---|---|---|---|---|---|---|---|---|
| 2764531 | 514730 | - | ㅇㅇ | 211.36 |
07.28 15:24:50 |
핵심은 이상적인 평탄 응답과 측정된 자연 롤오프를 주파수별로 혼합하는 것이다. 이거 무슨 뜻임? | - | 0 | - | - |
| 2764535 | 514730 | znffjrznf123 | 한플 | - |
07.28 15:26:27 |
ㄴ 과교정 방지용으로 타겟 하한 주파수 아래에서는 스피커 자연 롤오프 따라가게 냅뒀음 | 1 | 2764531 | - | - |
| 2764537 | 514730 | znffjrznf123 | 한플 | - |
07.28 15:26:46 |
ㄴ @한플 정확히는 스피커 롤오프가 아니라 측정된 인룸 롤오프 | 1 | 2764531 | - | - |
| 2765803 | 514730 | scholar7270 | ㅇㅇ | - |
07.29 20:41:25 |
혹시 이 알고리즘이랑 secs 코드 개발하는데 갖다써도 됨? REW조차도 들어갈 필요없고 측정만 하면 앱 하나로 룸보정해주는 왕초보자용 앱을 만들고 있는데 단순 보정보다는 secs 알고리즘이 좋으니 쓰고싶음 개발하려는 앱은 여기 봐줘 https://gall.dcinside.com/mgallery/board/view/?id=speakers&no=514803&page=3 | - | 0 | - | - |
| 2765806 | 514730 | scholar7270 | ㅇㅇ | - |
07.29 20:43:50 |
ㄴ 그리고 가장 추천하는 secs 기본값 설정좀 알려주면 좋겠음. 초보자 입장에서 고급 옵션 들어가는거 아니면 아예 설정 건들 필요도 없게끔 하려고 | 1 | 2765803 | - | - |
| 2765842 | 514730 | znffjrznf123 | 한플 | - |
07.29 21:15:38 |
ㄴ 가능하지 프로그램 안에 자연스럽게 녹여낼거면 소개글에 원본 링크 하나만 걸어주셈 마음대로 수정하거나 개선해도 괜찮음 | 1 | 2765803 | - | - |
| 2765849 | 514730 | znffjrznf123 | 한플 | - |
07.29 21:17:35 |
ㄴ @ㅇㅇ 그냥 하나만 남기라면 기본설정에다가 컴포트모드 or 컴포트에서 틸트 0인걸로 할거같음 그래도 뭔가 부족하다는 사람이 생길 수 있으니 프리셋 여럿 두는게 나을듯 | 1 | 2765803 | - | - |
| 2765853 | 514730 | znffjrznf123 | 한플 | - |
07.29 21:19:00 |
ㄴ 다만 이미 https://m.dcinside.com/board/speakers/514172 이런게 있어서 뭔가 차별점을 둬도 괜찮을거같음 | 1 | 2765803 | - | - |
| 2765899 | 514730 | scholar7270 | ㅇㅇ | - |
07.29 21:48:21 |
ㄴ @한플 ㄱㅅㄱㅅ | 1 | 2765803 | - | - |
| 2766189 | 514730 | scholar7270 | ㅇㅇ | - |
07.30 09:25:41 |
ㄴ @한플 SECS 기능 추가 개발하고 있는데 혹시 2.1채널에서도 SECS 알고리즘 그대로 사용해도 돼? 클로드가 “공유 서브 대역을 두 채널이 다르게 보정하면 측정 노이즈와 싸우게 된다”라고 하는데, 내가 만든 앱에 룸보정 전 이미 서브우퍼-메인 간 위상, 크로스오버, 딜레이 최적점 찾기 기능이 있어서 저런 말을 한 것 같음. 음향학 지식이 많이 없어서 물어보게 됨 ㅈㅅ - dc App | 1 | 2765803 | - | - |
| 2766190 | 514730 | znffjrznf123 | 한플 | - |
07.30 09:26:36 |
ㄴ @ㅇㅇ 크로스오버 처리를 minimum phase로 한 다음 최종 보정에 excess phase 처리가 들어가면 될듯함 | 1 | 2765803 | - | - |
| 2768789 | 514730 | scholar7270 | ㅇㅇ | - |
08.01 11:31:15 |
ㄴ @한플 SECS 기능 추가한 버전 곧 공개하려는데 오픈소스라지만 클로드가 라이선스가 명시적으로 없어서 좀 그렇다 하네 | 1 | 2765803 | - | - |
| 2768791 | 514730 | scholar7270 | ㅇㅇ | - |
08.01 11:31:50 |
ㄴ @ㅇㅇ MIT 라이선스로 이해하고, 작성글이랑 코드 주석에 원작자 출처 밝히는 정도로 괜찮을까? | 1 | 2765803 | - | - |
| 2769171 | 514730 | znffjrznf123 | 한플 | - |
08.01 21:56:36 |
ㄴ @ㅇㅇ ㄱㄱ | 1 | 2765803 | - | - |
게시글 및 댓글
SECS.py 알고리즘 분석
요약
SECS는 측정 응답을 무조건 평탄하게 만드는 프로그램이 아니다.
측정 IR에서 신뢰 가능한 대역을 판별한 다음,
유효 대역에서는 이상적인 Target을 추종하고 저역·고역 한계에서는
스피커의 자연스러운 롤오프를 보존하는 적응형 보정 방식이다.
측정 IR WAV → 응답/위상 분석 → 적응형 Target 생성 → 역필터 생성
→ 잔차 보정 → 지연 및 L/R 정렬 → WAV 저장
1. 입력된 측정치 해석
입력값은 주파수 응답 CSV가 아니라
Impulse Response WAV
다.
프로그램은 WAV 파일을 불러온 뒤 다음과 같이 전처리한다.
최대 절댓값이 1e-6 미만이면 무음으로 판단
입력 신호 중 최대 5초까지만 사용
FFT 계산에 적합한 길이로 zero padding
Mono/Stereo 자동 판별
출력 Sample Rate가 다르면 polyphase 방식으로 리샘플링
측정 IR에서 추출하는 정보
측정 정보
알고리즘에서의 의미
가장 큰 Impulse 위치
음향 도달 시간과 L/R 시간차 계산
FFT 절댓값
스피커와 룸이 합쳐진 크기 응답
Minimum-phase 응답
크기 응답으로부터 예측되는 기본 위상
Excess phase
Minimum phase만으로 설명되지 않는 실제 위상
저역·고역 감쇠
무리하지 않고 보정할 수 있는 자연 대역 한계
L/R Peak 주변 RMS
좌우 채널의 초기 Gain 차이
주파수 응답 스무딩
하나의 고정 스무딩을 전 대역에 적용하지 않는다.
100/150/200/300Hz를 경계로 5개 대역을 만들고,
각 대역에 서로 다른 Fractional Octave Smoothing을 적용한다.
Normal 모드 기준으로 저역부터 대략
1/24, 1/12, 1/6, 1/3, 1 Octave
스무딩을 사용한다.
저역 공진은 비교적 세밀하게 분석
고역의 촘촘한 Comb Filtering은 강하게 평균화
기준 레벨
100Hz~10kHz 구간의 원래 Magnitude 중
35 Percentile
을 기준 크기(ref_mag)로 사용한다.
ref_mag = percentile(|H|, 35)
평균값이나 최대값을 쓰는 것보다 룸 피크의 영향을 덜 받는 기준이다.
자연스러운 보정 대역 판정
저역 Cutoff:
1~10kHz 평균보다 6dB 낮은 레벨을 처음 통과하는 주파수.
최종 범위는 10~300Hz로 제한된다.
고역 Cutoff:
2~22.05kHz 응답의 95 Percentile보다 10dB 이상 낮지 않은
마지막 주파수. 최종 범위는 6~20kHz로 제한된다.
200~1000Hz 평균보다 약 30dB 이상 약한 저역은
신뢰도가 낮은 측정 구간으로 취급한다.
위상 해석
측정 Magnitude에서 Cepstrum 방식으로 Minimum-phase 응답을 만들고,
실제 측정 응답과의 차이로 Excess phase를 계산한다.
Excess phase 역보정 ≈ conj(H_measured_aligned / H_minimum)
신호가 약한 주파수에서는 이 위상 역보정을 점진적으로
무보정 상태로 섞는다. 따라서 SNR이 나쁜 구간의 위상을
억지로 뒤집지 않는다.
참고로 코드의
_linearity_score()
는 이름과 달리
위상 직선성을 직접 측정하는 값은 아니다.
1~10kHz에서 초기 100ms와 100ms 이후 구간의 감쇠량을 비교하는 지표이며,
필터 생성에는 사용되지 않고 룸 어쿠스틱 추천 문구에만 사용된다.
2. Target 생성
핵심은 이상적인 평탄 응답과 측정된 자연 롤오프를
주파수별로 혼합하는 것이다.
기본 Ideal Target
B(f) = [f⁴ / (f⁴ + 1⁴)] × [20000⁴ / (f⁴ + 20000⁴)]
가청대역에서는 거의 Flat이지만 DC와 20kHz 이상에서는
자연스럽게 감쇠하는 4차 필터 형태다.
측정 적응형 Target
먼저 측정 응답을 기준 레벨로 정규화한다.
N(f) = Smoothed Measurement(f) / Reference
기준보다 낮은 부분만 자연 롤오프로 사용한다.
측정된 피크를 Target에 그대로 복사하지는 않는다.
R(f) = min(1, N(f))
Track Weight를 w(f)라고 하면 다음 구간에서 1에 가까워진다.
검출된 저역 Cutoff 이하
고역 Cutoff 부근 및 그 이상
200Hz 이하에서 측정 신호가 매우 약한 구간
T0(f) = R(f)^w(f) × B(f)^[1-w(f)]
w = 0:
이상적인 Flat Target 사용
w = 1:
측정된 자연 롤오프를 따라감
중간값:
두 응답을 로그 Magnitude 기준으로 혼합
1kHz 이상에서는 Target이 기본 Ideal보다 커지지 않도록 한 번 더 제한한다.
고역 롤오프를 무리하게 끌어올리지 않기 위한 처리다.
Bass Boost
Bass Gain dB(f) = 설정 Gain × fc² / (f² + fc²)
매우 낮은 주파수에서는 설정 Gain 전체가 적용되고,
지정한 Bass Frequency에서는 설정값의 절반 dB가 적용된다.
따라서 UI의 “dB @ Frequency”라기보다는
저역 Shelf의 전환 주파수에 가깝다.
Tilt
Tilt Gain dB(f) = Tilt × log2(f / 1000)
1kHz를 기준으로 옥타브당 설정 dB만큼 기울어진다.
단, Track Weight가 큰 자연 롤오프 구간에서는 Tilt도 약화된다.
3. 보정 과정
3-1. 초기 Magnitude 역필터
G_inv(f) = Target(f) / Normalized Measurement(f)
이 값을 사용자가 지정한 Boost 한도까지 제한한 다음,
Cepstrum 방식으로 Minimum-phase 필터로 변환한다.
mag_inv = clip(Target / Measurement, 0, 10^(Max Boost / 20))
3-2. Curtain 처리
Curtain 주파수부터 그 2배 주파수까지
Magnitude 역보정을 Unity, 즉 무보정 상태로 Fade한다.
예를 들어 Curtain이 300Hz라면:
300Hz 이하: 계산된 Magnitude 보정 적용
300~600Hz: 보정을 점진적으로 해제
600Hz 이상: 초기 Magnitude 역필터는 Unity
Curtain은 Minimum-phase Magnitude 역필터에 대한 경계다.
Normal 모드의 Excess-phase 보정 전체를 끄는 경계는 아니다.
3-3. 동작 모드별 위상 보정
모드
보정 방식
Normal
Minimum-phase Magnitude 보정과 Excess-phase 보정을 함께 적용.
저역은 설정 Delay 전체, 중역은 약 절반, 고역은 약 1/4 수준의
Pre-ringing만 허용한다.
Low-Latency
Excess-phase 보정을 사용하지 않고 Minimum-phase 필터만 사용.
Stereo L/R 도달 시간은 정렬한다.
Zero-Latency
Minimum-phase 필터만 사용하며 L/R 정렬을 위한 추가 지연도 넣지 않는다.
Normal 모드에서는 저역 역필터에 최대 500ms의 긴 Window,
고역에는 10ms의 짧은 Window를 사용한다.
저역 Decay는 충분히 표현하면서 고역 Ringing은 제한하려는 구조다.
3-4. 시뮬레이션 기반 잔차 보정
초기 필터를 측정 응답에 적용한 결과를 내부에서 시뮬레이션하고,
Target과 다시 비교해 잔차를 보정한다.
Macro EQ
Target과 시뮬레이션 결과의 비율을 약 ±6dB로 제한해 보정한다.
10~20kHz에서는 양의 Boost만 점차 억제한다.
저역 Peak Crush
Target보다 높은 부분만 검출해 Cut한다.
300Hz 이하는 적용, 300~500Hz는 Fade,
500Hz 이상에서는 적용하지 않는다.
Tilt 적용
Tilt를 포함한 Post-EQ를 Minimum-phase 필터로 만들고
초기 필터와 결합한다.
즉 잔여 저역 Peak는 줄이지만,
저역 Null을 같은 강도로 억지로 채우지는 않는 방향이다.
3-5. 자동 Delay 선택
첫 측정의 Normal 모드에서는 2~10ms 후보를 1ms 간격으로 시험한다.
각 후보 필터를 측정 응답에 Convolution한 뒤,
자연 저역 Cutoff부터 300Hz까지 Target과의 오차를 계산한다.
Metric = Weighted MAE + 0.35 × Shape MAE
낮은 주파수에 더 큰 가중치를 주며,
Stereo 합산 평가에서는 두 채널의 합이 단일 채널보다
약 6dB 높다는 점을 Target에 반영한다.
3-6. Stereo 정렬
두 채널 중 더 늦게 도착한 Impulse를 기준으로 시간 정렬
Peak 주변 ±5ms RMS를 이용해 초기 Gain 정렬
보정 후 20~1000Hz의 L/R Median 차이를 다시 계산
R 채널을 최대 ±6dB 범위에서 추가 조정
3-7. 최종 출력
Filter Peak 앞에 선택한 Delay만큼 샘플이 남도록 약 510ms 길이로 Crop
마지막 5ms에 제곱 형태의 Fade-out 적용
Filter의 최대 주파수 Magnitude가 1을 넘으면 전체 정규화
Mono 또는 L/R 개별 FLOAT WAV 파일로 저장
4. 코드상 주의할 점
1. rm_eq는 현재 실질적으로 동작하지 않음
코드에서 rm_eq는 항상 1인 배열이다.
실제 Room Mode Cut 역할은 저역 Peak Crush가 담당한다.
2. Boost는 최종 필터 전체의 절대 상한이 아님
Boost 제한은 초기 역필터에 적용된다.
이후 Macro EQ와 Tilt가 추가되므로 최종 필터의 Boost가
설정값을 완전히 넘지 않는다고 보장되지는 않는다.
3. 자동 Delay Fine Search가 비활성화되어 있음
0.5ms 단위 관련 상수는 존재하지만
실제 자동 검색은 enable_stage2=False라서 1ms 단위로만 수행된다.
4. Stereo Preview의 Delay 평가는 왼쪽 채널 중심
Preview에서는 처리 속도를 위해 왼쪽 채널만 이용해 Delay 후보를 평가한다.
따라서 최종 L+R 합산 기준 최적 Delay와 차이가 날 수 있다.
5. Preamp 표시값 해석에 주의
저장되는 Filter는 이미 최대 Magnitude 1로 정규화된다.
그런데 UI에는 정규화 이전 Gain에 해당하는 음수 Preamp도 표시된다.
저장된 Filter에 이 음수 Preamp를 별도로 다시 적용하면
감쇠가 중복될 가능성이 있다.
최종 평가
SECS는 단순한 Full-band Inverse EQ가 아니라
측정 신뢰도에 따라 보정 강도를 바꾸는 적응형 Mixed-phase 보정기
에 가깝다.
중심 대역은 이상적인 Target을 적극적으로 추종
자연스러운 저·고역 한계에서는 측정 롤오프를 보존
저역 Peak는 세밀하게 Cut
신호가 약한 구간의 과도한 Boost와 위상 역보정은 억제
Normal 모드에서는 제한적인 Excess-phase 보정까지 수행
전체적으로 룸과 스피커의 측정 한계를 어느 정도 인정하면서
과도한 역보정을 피하도록 설계된 알고리즘이라고 볼 수 있다.