117afeec05
- Remove old/unneeded material: mockups/, docs/Image (ChatGPT imgs·GIFs), character art docs (IMAGE_GEN_*, *.md.old, BRAND_CHARACTERS, CHARACTER_PROFILES), asset backups (Characters_OriginalBackup, SourceCandidates), unused puppet variants (LeeSoriExtended/Regenerated/Upper/V2/V3), tools/ art scripts - Keep active assets only: LeeSori + LeeSoriDance puppets, Live2DPreview, Live2DHost, mascot PNGs - Fix dangling references in kept docs (README, CLAUDE, ARCHITECTURE, TYPOGRAPHY, CHARACTER_UI_INTEGRATION) - Refresh HANDOFF.md to live state (LeeSoriDance puppet, D:\Project paths) - Redirect all build output to Build/ via Directory.Build.props (bin+obj) - Add .gitignore and untrack previously committed bin/obj artifacts Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8.4 KiB
8.4 KiB
ARCHITECTURE
1. 기술 스택 (확정)
| 영역 | 선택 | 이유 |
|---|---|---|
| 런타임 | .NET 8 | 최신 LTS, 네이티브 Windows |
| UI | WPF + WPF-UI (lepoco) | Fluent Design System / Mica·다크모드 / WinUI 감성. 텍스트 UI 아님 |
| 차트 | LiveCharts2 | 애니메이션되는 아름다운 EQ 커브. (대안: ScottPlot=정적·경량) |
| MVVM | CommunityToolkit.Mvvm | 소스제너레이터 기반, 보일러플레이트 최소 |
| DB | SQLite (Microsoft.Data.Sqlite) | 로컬 프로파일 인덱스 |
| AI | Anthropic REST (HttpClient) 또는 Anthropic.SDK NuGet |
구조화 출력(tool use) |
| 패키징 | MSIX 또는 velopack/single-file | 배포. 라이선스 제외 옵션과 연동 |
WPF-UI가 Mica 배경 + Fluent 컨트롤 + 다크테마를 제공해 다크·Fluent 룩앤필을 네이티브로 재현할 수 있다. 그래프는 LiveCharts2의
CartesianChart로 로그 X축(주파수)
- 선형 Y축(dB), 영역 그라데이션 채우기.
2. 컴포넌트 구성
DansoriEQ.sln
├─ DansoriEQ.App (WPF, WPF-UI) ── Views/ViewModels, 그래프, 프롬프트 독
├─ DansoriEQ.Core (class lib)
│ ├─ Profiles/ ProfileRepository, AutoEqParser, DbUpdater
│ ├─ Eq/ EqState, Filter(model), ApoRenderer, PreampCalculator
│ ├─ Ai/ ClaudeClient, EqPromptBuilder, EqDeltaSchema
│ └─ Apo/ ApoLocator, ApoConfigInstaller(승격 1회), IncludeWriter
└─ DansoriEQ.Setup (elevated helper, 최초 1회 UAC — 아래 4장)
3. 데이터 흐름
프로파일 선택 → ProfileRepository.Load(id) → EqState(base)
→ ApoRenderer → IncludeWriter.Write(ai_eq.txt) → APO 라이브 리로드 → 그래프 갱신
프롬프트 입력 → EqPromptBuilder(현재 EqState + 헤드폰 메타 + 요청)
→ ClaudeClient(tool use, EqDeltaSchema) → EqDelta(JSON)
→ EqState.Apply(delta) → PreampCalculator → ApoRenderer → IncludeWriter → APO
→ AI 설명 텍스트를 응답 패널에 표시 / 히스토리 스택 push
4. APO 연동 & 저권한 전략 (중요)
문제: APO의 config.txt는 C:\Program Files\EqualizerAPO\config\ 아래라 쓰기에 승격 필요.
매번 승격은 "저권한" 원칙 위반.
채택 방식 — "1회 승격 설정, 이후 무승격":
- 최초 실행 설정 마법사(DansoriEQ.Setup, UAC 1회):
- APO 설치 경로 탐지: 레지스트리
HKLM\SOFTWARE\EqualizerAPO→InstallPath. - 사용자 쓰기 가능한 EQ 파일 준비. 권장:
config폴더 내ai_eq.txt를 만들고 그 파일(또는 폴더)에 현재 사용자 쓰기 ACL 부여(icacls). 그리고config.txt에Include: ai_eq.txt한 줄 추가(중복 방지 검사). - 완료 플래그 저장(
%LOCALAPPDATA%\DansoriEQ\setup.json).
- APO 설치 경로 탐지: 레지스트리
- 이후 실행: 앱은
ai_eq.txt만 갱신 → 승격 불필요. APO가 저장 즉시 리로드.
⚠️ M1에서 검증할 스파이크: APO
Include:가 절대경로를 허용하는지 확인.
- 허용 O →
ai_eq.txt를%APPDATA%\DansoriEQ\에 두고 절대경로 Include(ACL 불필요, 가장 깔끔).- 허용 X(상대경로만) → 위 4-1의 config 폴더 내 파일 + ACL 부여 방식으로. 두 경로 모두 "1회 승격, 이후 무승격"을 만족. 스파이크 결과로 하나 확정.
APO 필터 문법(렌더 타깃):
Preamp: -6.0 dB
Filter 1: ON PK Fc 3000 Hz Gain 3.0 dB Q 1.20
Filter 2: ON LSC Fc 90 Hz Gain 4.0 dB Q 0.70
Filter 3: ON HSC Fc 10000 Hz Gain -1.5 dB Q 0.70
- 타입 매핑: PK=peaking, LSC=low-shelf, HSC=high-shelf, (LP/HP 확장 가능).
- Preamp = -(양의 게인 총합) 또는 최소 -(최대 양의 게인) − 여유 1dB. 클리핑 방지 필수.
5. 프로파일 DB & 라이선스 분리
폴더 레이아웃
data/
├─ profiles/
│ ├─ open/ ← 재배포 허용(퍼미시브) 소스. 배포 빌드에 포함
│ └─ restricted/ ← 재배포 불가 소스. 배포 빌드에서 제외
├─ manifest.json ← 소스별 {name, license, distributable, url, commit}
└─ dansorieq.db ← SQLite 인덱스(open+restricted 모두 인덱싱)
원칙
- 수집(개발 중 1회): AutoEQ repo를 zip/clone로 확보 → 파싱 → 소스 라이선스에 따라
open/또는restricted/로 분류 저장 → SQLite에 upsert. - UI: DB를 조회할 때 라이선스 구분 없이 병합해서 보여준다(IEM/헤드폰만 구분).
- 배포: 패키징 시
--exclude-restricted옵션 →restricted/폴더와 해당 DB 행 제외. (개인 사용 로컬 빌드는 전체 포함.) - DB 스키마:
CREATE TABLE headphone(
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
brand TEXT,
type TEXT CHECK(type IN ('iem','headphone')) NOT NULL,
source TEXT, -- 측정/소스명
license TEXT, -- 예: 'CC-BY', 'restricted'
distributable INTEGER, -- 0/1 (UI에선 필터하지 않음)
target TEXT, -- 예: 'Harman IE 2019'
preamp_db REAL,
filters_json TEXT, -- [{type,fc,gain,q}]
raw_text TEXT, -- 원본 ParametricEQ.txt
updated_at TEXT
);
CREATE INDEX ix_hp_type ON headphone(type);
CREATE INDEX ix_hp_name ON headphone(name);
앱 내 업데이트
- "DB 업데이트" → 최신 소스(zip) 재확보 → 파싱 → upsert(변경분만) → manifest commit/날짜 갱신.
- UI 하단에
N profiles · 최신: YYYY-MM-DD표시.
6. AI 레이어 스키마 (구조화 출력)
EqDelta (Claude가 tool use로 반환):
{
"preamp_db": -6.0,
"filters": [
{ "type": "PK", "fc": 3000, "gain": 3.0, "q": 1.2, "enabled": true },
{ "type": "LSC", "fc": 90, "gain": 4.0, "q": 0.7, "enabled": true }
],
"explanation": "보컬 존재감을 위해 3kHz +3dB…",
"replace": false // false=현재 상태에 병합, true=전체 교체
}
시스템 프롬프트 요지:
- 역할: 파라메트릭 EQ 전문가. APO 제약(타입 PK/LSC/HSC, Fc 20–20000Hz, Gain ±12dB 권장, Q 0.3–6) 안에서만 출력.
- 입력으로 현재 EqState + 헤드폰 모델/타입 + 사용자 요청 제공 → 요청을 delta로 반영.
- 오디오 상식 힌트(보컬≈2–5kHz, 저음 단단히≈40–80Hz 무게+150–250Hz 뭉침 컷, 치찰음≈6–8kHz).
- Preamp 안전값 계산 규칙 명시.
- 런타임 모델: 기본 Claude Sonnet(요청당 2–5k 토큰), 옵션으로 Opus.
7. 오픈 이슈 → DEV_PLAN 참조
- APO Include 절대경로 허용 여부(스파이크).
- AutoEQ repo 구조/소스 라이선스 최신 상태 확인(수집 스크립트에서).
- 다중 출력 장치별 APO config 타깃팅(고급 옵션, MVP 이후).
8. EQ 프리셋 공유 포맷 (.tweq)
사용자가 만든 EQ를 다른 사용자와 공유하기 위한 파일. JSON, 확장자 .tweq.
{
"format": "dansorieq.eq",
"version": 1,
"app_version": "0.1.0",
"created_utc": "2026-07-01T12:00:00Z",
"author_note": "밝고 보컬 중심 튜닝",
"target": {
"name": "Truthear x Crinacle Zero",
"brand": "Truthear",
"type": "iem",
"source": "AutoEQ",
"target_curve": "Harman IE 2019"
},
"eq": {
"preamp_db": -6.0,
"filters": [
{ "type": "PK", "fc": 3000, "gain": 3.0, "q": 1.2, "enabled": true }
]
},
"history": [
{ "role": "user", "text": "보컬 가까이, 저음 단단히", "ts": "..." },
{ "role": "ai", "text": "3kHz +3dB, 180Hz -2.5dB…", "ts": "..." }
]
}
- 내보내기: 현재 EqState + 대상 기기 메타 + 대화 히스토리(간략)를 직렬화해 저장.
- 가져오기: 검증(format/version, 값 범위 클램프, 크기 상한) → 정보 패널(대상 기기 / 히스토리 / 작성자 노트) 표시 → EQ 적용.
- 라이선스 안전: 파일엔 측정 데이터가 아니라 기기 이름/메타만 포함 → 재배포 문제 없음.
- 보안: history 텍스트는 표시 전용(실행/링크 처리 안 함), 항목 수·길이 상한, API 키 미포함.
9. 설정 & Claude API 키 관리
- 별도 설정 화면(WPF-UI NavigationView: Home/EQ ↔ Settings).
- 섹션: [AI · API 키] / [테마] / [APO] / [데이터베이스].
- API 키: 등록 / 삭제 / 교체, "연결 테스트", DPAPI 암호화 저장(
%LOCALAPPDATA%\DansoriEQ). - 모델 선택: 기본 Claude Sonnet / 옵션 Opus.
- 키 미등록 시 프롬프트 독 비활성 + 등록 안내.