01. VSS 오디오 — 소리 하나를 내기 위해 필요한 모든 판단
출처: SR §6.1 (6.1.1 기능별 이벤트 음향 출력 / 6.1.2 음향 우선순위 및 중재 / 6.1.3 음량 제어 및 오디오 효과 / 6.1.4 상태 관리·오류 대응 및 HMI 연계) 관련 TBD: TBD-004(VSS 차량 상태 정보 유효성 및 복구 기준), TBD-005(VSS 음향별 주파수·길이·dB(A) 최종 Calibration), TBD-006(장애물 경고 거리·미디어 음량 기준), TBD-027(차량 전원 상태 생성 주체 및 입력 방식)
0. 이 절을 읽는 틀
VSS는 스피커에서 소리를 내는 기능이다. 그런데 SR은 "소리를 낸다"를 네 개의 층으로 분해했다.
이 순서가 곧 오디오 파이프라인의 실제 처리 순서다. 이벤트가 들어오면 → 우선순위로 걸러지고 → 음량 정책이 적용되고 → 출력 가능 상태인지 확인된다. 이 노트도 그 순서로 간다.
1. §6.1.1 — 기능별 이벤트 음향 출력
SR은 음향을 발생 원인에 따라 세 그룹으로 나눈다. 이 그룹 나눔이 §6.1.2 우선순위의 근거가 되므로, 어떤 음향이 어느 그룹인지 아는 게 중요하다.
1-1. 차량 전원, 도어 및 원격 제어 연동 음향
- 시스템은 실내 탑승자가 감지된 상태에서 차량 전원이 켜지는 경우 웰컴 차임을 출력해야 한다.
- 시스템은 차량 전원이 꺼지는 경우 굿바이 차임을 출력해야 한다.
- 시스템은 도어 잠금이 정상적으로 완료된 경우 잠금 완료 피드백 차임을 1 회 출력해야 한다.
- 시스템은 도어 잠금 해제가 정상적으로 완료된 경우 잠금 해제 피드백 차임을 2 회 연속 출력해야 한다.
- 시스템은 도어 잠금 상태에서 도어가 열려 있거나 정상 잠금에 실패한 경우 경적(Horn) 경고음을 출력해야 한다.
- 시스템은 사용자의 원격 차량 찾기(Find My Car) 요청이 확인된 경우 위치 확인용 경적 음향을 출력해야 한다.
여기서 놓치기 쉬운 것들:
| 요구사항 | 숨은 조건 |
|---|---|
| 웰컴 차임 | **"실내 탑승자가 감지된 상태에서"**가 조건이다. 빈 차에 전원이 들어오면(원격 시동 등) 웰컴 차임을 울리면 안 된다. → §6.3의 Vision 탑승자 판정에 의존한다 |
| 굿바이 차임 | 탑승자 조건이 없다. 전원이 꺼지면 무조건 운다. 비대칭이다 |
| 잠금 1회 / 해제 2회 | 횟수가 요구사항에 박혀 있다. 이건 시각 확인 없이 소리만으로 잠금/해제를 구분하게 하는 UX 설계다. 구현 시 "차임 재생" 함수가 반복 횟수를 인자로 받아야 한다 |
| 잠금 실패 → 경적 | 차임(chime)이 아니라 **경적(Horn)**이다. 음원 자체가 다르고 훨씬 크다. "정상 완료 = 차임, 이상 = 경적"이라는 청각 언어가 설계돼 있다 |
| Find My Car | 경적을 쓰지만 이건 경고가 아니라 위치 확인이다. §6.1.2의 우선순위에서 "경고음"과 같은 등급으로 취급하면 안 된다 |
함정 — "정상적으로 완료된 경우" "도어 잠금 명령을 보낸 경우"가 아니다. §6.4.1의 "시스템은 도어 잠금 해제 동작 후 실제 목표 상태가 확인되지 않는 경우 해당 요청을 정상 완료로 처리하지 않아야 한다"와 짝을 이룬다. 즉 명령 송신 → 즉시 차임은 요구사항 위반이다. 액추에이터 동작 후 실제 도어 상태를 확인하고 나서 울려야 한다. 이건 차임 재생 시점이 수십~수백 ms 늦어진다는 뜻이기도 하다.
1-2. 위험 및 상황 경고 음향
- 시스템은 파워윈도우의 끼임 위험이 감지된 경우 안티핀치 비상 경고음을 출력해야 한다.
- 시스템은 차량 전원 상태와 관계없이 실내 고온 상태에서 잔류 탑승자가 확인된 경우 비상 사이렌을 출력해야 한다.
- 시스템은 카메라(비전) 감지 영역 내에서 고양이 존재가 유효하게 확인된 경우 알림 및 주의 음향을 출력해야 한다.
- 시스템은 차량 시동이 걸려 있는 상태에서 초음파 센서 감지 범위 내 장애물이 접근한 경우 장애물 접근 경고음을 출력해야 한다.
- 시스템은 차량 시동이 꺼져 있는 상태인 경우 초음파 센서 기반 장애물 접근 경고음을 출력하지 않아야 한다.
- 시스템은 위험 상태가 해제되거나 정의된 최대 경고 시간이 초과된 경우 경고음 출력을 중단해야 한다.
"차량 전원 상태와 관계없이"가 딱 한 번 나온다 — ROA 사이렌.
이건 대단히 무거운 요구사항이다. 전원 OFF 상태에서도 VSS가 소리를 낼 수 있어야 한다는 뜻이고, 곧 S32K344-WB가 전원 OFF에서도 최소한 저전력으로 살아 있어야 한다는 하드웨어 요구로 번역된다. 잔류 탑승자(아동·반려동물) 사망 사고를 막는 기능이므로 다른 모든 것보다 우선한다.
반대로 초음파 장애물 경고는 시동 조건에 묶여 있다. 그것도 "출력해야 한다"와 "출력하지 않아야 한다" 두 문장으로 명시적으로 갈라 썼다. 왜 한 문장으로 안 썼을까?
✗ 시스템은 차량 시동이 걸려 있는 경우에만 장애물 접근 경고음을 출력해야 한다.
"~인 경우에만"은 시험 항목으로 만들면 애매하다. 긍정 조건 시험과 부정 조건 시험이 한 요구사항에 묶여, 하나만 실패해도 판정이 흐려진다. §9의 분리 원칙대로 두 문장으로 쪼갠 것이다.
왜 시동 꺼짐에서 초음파 경고를 막는가? 주차된 차 옆을 사람이 지나갈 때마다 경고음이 울리면 소음 민원이다. 그리고 시동이 꺼진 차는 움직이지 않으므로 후방 장애물이 위험이 아니다. 위험의 정의가 차량 운동 상태에 의존한다는 걸 요구사항이 인정한 것.
"정의된 최대 경고 시간" — 경고음은 무한히 울리면 안 된다. 배터리 소모와 소음 민원 때문이다. 이 값은 TBD로 남아 있지 않은 대신 §6.1.1에 "정의된"이라는 수식어로만 존재한다. 구현 시 상수로 빼두고 시험에서 확정해야 한다.
1-3. 조작 및 모드 전환 피드백 음향
- 시스템은 차량 디스플레이 또는 모바일 인터페이스에서 조작 입력 또는 모드 전환 요청이 확인된 경우 피드백 음향을 출력해야 한다.
한 문장뿐이지만, 이 그룹이 §6.1.2와 §6.1.3에서 계속 언급되는 "피드백 음향"의 정의다.
세 그룹 정리
2. §6.1.2 — 음향 우선순위 및 중재
여기가 VSS의 심장이다. 요구사항 5개가 전부 "동시에 여러 소리가 필요할 때 무슨 일이 일어나는가"를 다룬다.
- 시스템은 안티핀치 비상 경고음을 다른 음향 및 피드백 음향보다 최우선으로 출력해야 한다.
- 시스템은 일반 음향 또는 피드백 음향 출력 중 비상 경고가 발생하는 경우 진행 중인 일반 음향 출력을 즉시 중단해야 한다.
- 시스템은 비상 경고 발생 시 진행 중인 음향을 중단하고 비상 경고음을 우선하여 출력해야 한다.
- 시스템은 안티핀치 위험 감지 시 재생 중인 일반 미디어 음향을 중단하거나 음소거해야 한다.
- 시스템은 연속적인 조작 입력 발생 시 조작 피드백 음향이 서로 중첩되어 출력되지 않도록 중재해야 한다.
2-1. 우선순위 계층
요구사항에서 직접 읽히는 순위:
1위 안티핀치 비상 경고음 ← "다른 음향 및 피드백 음향보다 최우선"
2위 기타 비상 경고음 ← "비상 경고 발생 시 진행 중인 음향을 중단"
3위 일반 음향 (차임 등)
4위 피드백 음향 (조작·모드 전환)
— 미디어 음향 ← 별도 축: 중단 또는 음소거 대상
미디어를 순위 밖에 둔 게 포인트다. 미디어는 "경쟁해서 지는" 게 아니라 "감쇄되거나 음소거되는" 대상이다. §6.1.3의 Ducking이 그래서 미디어에만 적용된다.
2-2. 선점(Preemption)과 중재(Arbitration)는 다른 문제다
- 선점: 더 급한 소리가 나면 진행 중인 소리를 끊는다. (우선순위 다른 소리끼리)
- 중재: 같은 종류의 소리가 몰릴 때 겹치지 않게 정리한다. (우선순위 같은 소리끼리)
마지막 요구사항 "연속적인 조작 입력 발생 시 조작 피드백 음향이 서로 중첩되어 출력되지 않도록 중재해야 한다"가 후자다. 사용자가 버튼을 빠르게 5번 누르면 "삑삑삑삑삑"이 겹쳐서 뭉개진다. 이걸 막는 전형적인 방법 세 가지:
| 방식 | 동작 | 장단점 |
|---|---|---|
| Drop (버리기) | 재생 중이면 새 요청 무시 | 가장 단순. 사용자가 "눌렸나?" 의심할 수 있음 |
| Restart (재시작) | 새 요청이 오면 처음부터 다시 | 반응성 좋음. 빠른 연타 시 앞부분만 반복돼 이상하게 들림 |
| Queue + 최소간격 | 큐에 넣되 최소 간격을 보장 | 자연스러움. 큐가 길어지면 입력과 소리의 시차가 커짐 |
피드백 음향은 보통 Drop + 짧은 쿨다운이 무난하다. 어차피 확인용 소리라 매 입력마다 울릴 필요가 없다.
2-3. 구현 — 우선순위 채널 모델
/* VSS 음향 카테고리 — 숫자가 작을수록 우선 */
typedef enum {
SND_PRIO_ANTIPINCH = 0, /* §6.1.2 "최우선" */
SND_PRIO_EMERGENCY = 1, /* ROA 사이렌, 장애물 경고, 잠금 실패 경적 */
SND_PRIO_NOTICE = 2, /* 웰컴/굿바이/잠금 차임, 고양이 알림, Find My Car */
SND_PRIO_FEEDBACK = 3, /* 조작·모드 전환 */
SND_PRIO_COUNT
} snd_prio_t;
typedef struct {
uint16_t sound_id;
uint8_t repeat; /* 잠금 1 / 해제 2 — §6.1.1 */
uint32_t max_ms; /* "정의된 최대 경고 시간" — §6.1.1 */
snd_prio_t prio;
} snd_req_t;
typedef struct {
bool active;
snd_req_t req;
uint32_t started_ms;
uint8_t played; /* 반복 재생 진행 횟수 */
} snd_slot_t;
static snd_slot_t g_slot[SND_PRIO_COUNT];
static snd_prio_t g_current = SND_PRIO_COUNT; /* COUNT = 무음 */
/* 최소 재생 간격 — 피드백 음향 중첩 방지 (§6.1.2) */
#define FEEDBACK_MIN_GAP_MS 120u
static uint32_t g_last_feedback_ms;
bool vss_request(const snd_req_t *r)
{
uint32_t now = hal_now_ms();
/* 중재: 같은 등급 피드백음이 연달아 오면 최소 간격을 보장 (§6.1.2) */
if (r->prio == SND_PRIO_FEEDBACK) {
if (now - g_last_feedback_ms < FEEDBACK_MIN_GAP_MS) return false; /* drop */
g_last_feedback_ms = now;
}
g_slot[r->prio].active = true;
g_slot[r->prio].req = *r;
g_slot[r->prio].started_ms = now;
g_slot[r->prio].played = 0;
/* 선점: 더 급하면 즉시 뺏는다 (§6.1.2 "즉시 중단") */
if (r->prio < g_current) {
audio_stop(); /* 진행 중인 출력 중단 */
audio_start(r->sound_id);
g_current = r->prio;
}
return true;
}
r->prio < g_current 이 한 줄이 §6.1.2의 세 문장을 전부 구현한다. 안티핀치(0)는 어떤 것보다 작으므로 항상 이긴다.
함정 — 선점당한 소리를 되살리지 마라
audio_stop()후 원래 소리를 큐에 보관해뒀다가 경고가 끝나면 재개하고 싶어질 수 있다. 하지 마라. 00편 패턴 C에서 봤듯 이 SR은 자동 재개를 일관되게 금지한다. §6.1.3은 예외적으로 Fade-in 복구를 명시한 경우만 허용하는데, 그건 미디어 음량 복구이지 중단된 차임의 재생이 아니다. 잠금 차임이 경고음에 잘려 나갔다면, 그냥 잘린 것이다. 나중에 뒤늦게 울리면 사용자는 무슨 일이 일어난 건지 알 수 없다.
2-4. 타임아웃 처리 — "정의된 최대 경고 시간"
void vss_tick_1ms(void)
{
if (g_current == SND_PRIO_COUNT) return;
snd_slot_t *s = &g_slot[g_current];
uint32_t elapsed = hal_now_ms() - s->started_ms;
/* §6.1.1 "정의된 최대 경고 시간이 초과된 경우 경고음 출력을 중단해야 한다" */
if (s->req.max_ms != 0u && elapsed >= s->req.max_ms) {
vss_release(g_current);
return;
}
if (audio_finished()) {
s->played++;
/* §6.1.1 잠금 1회 / 해제 2회 연속 */
if (s->played < s->req.repeat) {
audio_start(s->req.sound_id);
} else {
vss_release(g_current);
}
}
}
static void vss_release(snd_prio_t p)
{
g_slot[p].active = false;
audio_stop();
/* 다음으로 급한 대기 음향을 찾는다 — 없으면 무음 */
g_current = SND_PRIO_COUNT;
for (snd_prio_t i = 0; i < SND_PRIO_COUNT; i++) {
if (g_slot[i].active) { audio_start(g_slot[i].req.sound_id); g_current = i; break; }
}
}
여기서 vss_release가 다음 대기 음향을 찾아 재생하는 건 자동 재개가 아니다. 아직 유효한 요청으로 남아 있는(active) 음향을 이어서 처리하는 것이고, 선점당해 중단된 음향의 active를 그대로 두느냐 지우느냐가 설계 결정 지점이다. 위 SR의 정신에 맞추려면 선점 시 하위 슬롯을 active = false로 지우는 쪽이 안전하다.
3. §6.1.3 — 음량 제어 및 오디오 효과
3-1. 음량 감쇄 및 음소거 (Ducking & Mute)
- 시스템은 장애물이 주의 거리 범위에 접근한 경우 재생 중인 미디어 음량을 정의된 수준으로 감쇄(Ducking)해야 한다.
- 시스템은 장애물이 주의 거리 범위에 접근한 경우 단속 경고음을 출력해야 한다.
- 시스템은 장애물이 긴급 거리 범위에 접근한 경우 재생 중인 미디어 음량을 음소거(Mute)해야 한다.
- 시스템은 장애물이 긴급 거리 범위에 접근한 경우 연속 긴급 경고음을 출력해야 한다.
- 시스템은 디스플레이 또는 모바일 인터페이스의 무음(Mute) 설정이 활성화된 경우 피드백 및 모드 전환 음향 출력을 억제해야 한다.
거리 2단계 × 효과 2종의 대칭 구조다.
| 거리 단계 | 미디어 | 경고음 |
|---|---|---|
| 주의 거리 | Ducking (정의된 수준으로 감쇄) | 단속(intermittent) 경고음 |
| 긴급 거리 | Mute (음소거) | 연속(continuous) 긴급 경고음 |
단속 → 연속의 전환은 인간 청각 심리를 이용한 설계다. 삑…삑…삑 (간격이 좁아짐) → 삐———— (연속). 사람은 간격 변화를 거리 변화로 직관적으로 매핑한다. 후방 주차 센서의 표준 UX다.
TBD-006이 여기 걸려 있다: "장애물 경고 거리, 미디어 음량 기준 — 초음파 시험과 베치 시험 기준 통합 후 확정". TBD-013도 "근접 위험 단계 수(예: 5 단계) 포함"이라고 하는데, §6.1.3은 2단계(주의/긴급)만 쓴다. VSS는 2단계로 소리를 내고, HMI는 5단계로 표시할 수 있다 — 같은 초음파 데이터의 두 해석이다. §6.3.3의 "시스템은 근접 위험 단계를 HMI 및 VSS 경고에 사용할 수 있도록 제공해야 한다"가 이걸 뒷받침한다.
함정 — 무음 설정이 무엇까지 끄는가 "무음(Mute) 설정이 활성화된 경우 피드백 및 모드 전환 음향 출력을 억제해야 한다." 경고음은 대상이 아니다. 사용자가 무음을 켰다고 Anti-pinch 경고나 ROA 사이렌까지 꺼지면 안 된다. 안전 기능은 사용자 설정으로 무력화할 수 없다는 게 자동차 소프트웨어의 기본 원칙이다. 구현할 때
if (mute_enabled) return;을 오디오 출력 함수 최상단에 두면 이 요구사항을 위반한다. 카테고리별 게이트여야 한다.
static bool vss_muted_by_user(snd_prio_t p)
{
/* §6.1.3 — 무음 설정은 피드백/모드전환에만 적용. 경고는 예외. */
if (!g_user_mute) return false;
return (p == SND_PRIO_FEEDBACK);
}
3-2. 음량 복구 및 페이드 (Fade-in / Fade-out)
- 시스템은 굿바이 차임 출력을 종료할 때 음량을 서서히 감쇄(Fade-out)시켜야 한다.
- 시스템은 안티핀치 위험이 해제된 경우 이전에 재생 중이던 일반 음향을 서서히 정상 수준으로 복구(Fade-in)해야 한다.
- 시스템은 장애물이 경고 범위를 벗어난 경우 미디어 음량을 서서히 정상 수준으로 복구(Fade-in)해야 한다.
Fade가 필요한 이유는 클릭 노이즈(pop) 때문이다. 오디오 샘플이 0이 아닌 값에서 갑자기 0으로 끊기면 파형에 계단이 생기고, 그게 스피커에서 "틱" 소리로 들린다. 진폭이 클수록 심하다.
갑작스러운 중단: 페이드 아웃:
/\ /\ /\ /\
/ \/ \|______ / \/ \___
↑ 계단 → pop ↑ 부드러움
구현은 샘플마다 게인을 곱한다. 선형 페이드보다 지수(exponential) 페이드가 사람 귀에 자연스럽다. 인간의 음량 지각이 로그 스케일이기 때문이다.
/* 지수 페이드 — 매 오디오 프레임마다 호출 */
typedef struct {
q15_t gain; /* 현재 게인, Q1.15 (0x7FFF = 1.0) */
q15_t target; /* 목표 게인 */
q15_t step; /* 1프레임당 이동량 */
} fade_t;
static void fade_apply(fade_t *f, int16_t *buf, size_t n)
{
for (size_t i = 0; i < n; i++) {
/* 목표를 향해 한 스텝씩 — 도달하면 고정 */
if (f->gain < f->target) {
f->gain = (q15_t)MIN((int32_t)f->gain + f->step, (int32_t)f->target);
} else if (f->gain > f->target) {
f->gain = (q15_t)MAX((int32_t)f->gain - f->step, (int32_t)f->target);
}
buf[i] = (int16_t)(((int32_t)buf[i] * f->gain) >> 15);
}
}
함정 — Q15 곱셈에서
>> 15를 빼먹으면int16_t × q15_t는 32비트 범위가 필요하다.(int32_t)캐스팅 없이 곱하면int16오버플로로 파형이 뒤집혀 지지직거린다. 그리고>> 15는 Q1.15 스케일을 되돌리는 것이지 단순 나눗셈 최적화가 아니다. 이건 03편에서 다루는 고정소수점 연산의 전형적인 함정과 같은 뿌리다.
"이전에 재생 중이던 일반 음향을 Fade-in 복구" — 앞서 "선점당한 소리는 되살리지 마라"고 했는데, 이 문장은 그와 충돌하는 것처럼 보인다. 실제로는 두 가지 해석이 가능하고, 이건 SR의 모호한 지점이다.
- 음량 복구 해석: 안티핀치 동안 감쇄돼 있던 일반 음향(아직 재생 중)의 볼륨을 되돌린다.
- 재생 재개 해석: 중단됐던 음향을 다시 튼다.
§6.1.2가 "일반 음향 출력을 즉시 중단"이라고 했으므로, 중단된 것을 다시 트는 2번 해석은 §6.1.2와 모순된다. 1번(볼륨 복구)이 정합적인 해석이다. 즉 Anti-pinch 경고 중에도 일반 음향이 완전히 죽는 게 아니라 감쇄 상태로 살아 있고, 위험 해제 후 볼륨이 돌아온다.
이건 SR을 실제로 구현할 때 설계 문의(clarification request)를 올려야 하는 항목이다. "중단"과 "복구"가 한 절 안에서 서로 다른 상태 모델을 가정하고 있기 때문이다. 이런 걸 발견해서 질문하는 게 SR 리뷰의 목적이다.
3-3. 주야간 감쇄 및 음량 유지
- 시스템은 저소음 설정 또는 야간 감쇄 상태에서도 안티핀치 비상 경고음을 식별 가능한 음량 수준으로 유지해야 한다.
- 시스템은 유효한 시간 정보를 기반으로 주간 및 야간 상태를 구분해야 한다.
- 시스템은 야간 시간대이고 차량이 주차 또는 정차 상태인 경우 일반 피드백 및 조작 음향을 감쇄된 음량으로 출력해야 한다.
- 시스템은 차량 시동이 걸려 있는 상태인 경우 시간 정보와 관계없이 일반 피드백 음향의 야간 감쇄를 적용하지 않아야 한다.
**안전음의 하한선(floor)**이 첫 문장이다. 어떤 감쇄 정책도 안티핀치 경고를 들리지 않게 만들 수 없다.
/* §6.1.3 — 안전 경고음의 음량 하한 */
#define VOL_SAFETY_FLOOR Q15(0.60f)
static q15_t vss_final_gain(snd_prio_t p, q15_t requested)
{
q15_t g = requested;
if (g_night_mode && g_vehicle_parked) g = q15_mul(g, NIGHT_ATTEN); /* 야간 감쇄 */
if (p <= SND_PRIO_EMERGENCY && g < VOL_SAFETY_FLOOR) g = VOL_SAFETY_FLOOR;
return g;
}
야간 감쇄의 조건이 두 개(AND)라는 게 중요하다: 야간 시간대 AND 주차/정차 상태. 그리고 마지막 문장이 이걸 뒤집어서 한 번 더 못 박는다 — 시동이 걸려 있으면 시간과 무관하게 감쇄를 적용하지 않는다.
왜? 야간 감쇄의 목적은 주차장에서 남에게 폐 끼치지 않기다. 주행 중에는 로드 노이즈가 있어서 감쇄하면 피드백음이 아예 안 들린다. 목적이 사라진 곳에서는 정책도 사라져야 한다.
"유효한 시간 정보를 기반으로" — 시간을 신뢰할 수 없으면? SR은 여기서 답을 안 준다. 하지만 00편의 패턴 A를 적용하면 답이 나온다: 새로운 야간 감쇄 판단을 시작하지 않는다 = 감쇄 없이(정상 음량) 출력한다. 안전한 기본값(fail-safe default)은 "더 잘 들리는 쪽"이다. ESP32에 RTC가 없거나 시간 동기가 안 된 상황이 실제로 자주 발생하므로, 이건 구현 시 반드시 정해야 하는 지점이다.
4. §6.1.4 — VSS 상태 관리, 오류 대응 및 HMI 연계
- 시스템은 VSS 동작에 필요한 차량 상태 정보를 신뢰할 수 없는 경우 정상적인 미디어 재생을 제한해야 한다.
- 시스템은 VSS 동작에 필요한 차량 상태 정보를 신뢰할 수 없는 경우 이상 알림 경고음을 출력해야 한다.
- 시스템은 VSS 자체 오류(오디오 경로 또는 제어 이상)가 발생한 경우 차량 내 디스플레이(HMI)에 VSS 오류 상태를 전달하여 표시해야 한다.
- 시스템은 VSS 동작에 필요한 차량 상태 정보 및 VSS 오디오 경로가 정상 복구된 경우 이상 알림 경고를 종료하고 정상 동작 상태로 복귀해야 한다.
- 차량 내 HMI 는 VSS 미디어 제어 입력을 제공해야 한다.
- 차량 내 HMI 는 VSS 미디어 재생 상태를 표시해야 한다.
4-1. 두 종류의 오류가 다르게 처리된다
| 오류 종류 | 감지 대상 | 대응 |
|---|---|---|
| 입력 정보 불신 | 차량 상태 정보(전원/도어/윈도우 등) | 미디어 재생 제한 + 이상 알림 경고음 출력 |
| VSS 자체 오류 | 오디오 경로, 제어 이상 | HMI에 오류 상태 전달·표시 |
논리가 우아하다. 소리를 낼 수 있는 상태면 소리로 알리고, 소리를 낼 수 없는 상태면 화면으로 알린다.
오디오 경로가 죽었는데 "이상 알림 경고음"을 내려고 하면 아무 일도 일어나지 않는다. 그래서 자체 오류는 HMI 경로를 쓴다. 이건 알림 채널의 이중화(redundancy) 설계이고, 00편에서 본 "센서 오류 / 통신 오류 / 기능 자체 오류 구분" 원칙의 구체적 적용이다.
4-2. 복구가 대칭이 아니다
복구 조건은 "차량 상태 정보 및 VSS 오디오 경로가 정상 복구된 경우" — AND다. 둘 중 하나만 복구돼도 정상 복귀하지 않는다.
그리고 복구 시 두 가지를 한다: (1) 이상 알림 경고 종료, (2) 정상 동작 상태 복귀.
여기서 정상 동작 상태 복귀 ≠ 중단됐던 미디어 재생 재개임을 주의해야 한다. 00편 패턴 C에 따르면, 미디어는 사용자가 다시 재생을 요청해야 한다. "정상 동작 상태"란 "이제 요청이 오면 정상 처리할 수 있는 상태"라는 뜻이다.
TBD-004가 이 절을 가리킨다: "VSS 차량 상태 정보 유효성 및 복구 기준 — 차량 상태 정보 유효성 판단 기준 및 이상 알림 진입·복구 조건 확정".
4-3. VSS 상태 기계
그림 1의 Central Controller 블록에 INIT / READY / FAULT가 적혀 있다. §6.1.4와 합치면 이런 모델이 나온다.
DEGRADED와 FAULT를 나눈 게 핵심이다. 둘을 하나로 합치면 "차량 상태 정보가 이상한데 오디오는 멀쩡한" 상황에서 경고음까지 못 내게 된다. 그건 §6.1.1의 안전 요구사항(ROA 사이렌 등)을 깨뜨린다.
5. 실제로 소리가 나기까지 — 전체 경로 추적
Anti-pinch 감지부터 스피커까지의 실제 데이터 흐름을 따라가 보자. 이게 이 절 전체의 통합 시나리오다.
이 시퀀스에서 반드시 봐야 할 것
Power Window가 CAN 송신보다 먼저 모터를 멈춘다. 이게 안전 설계의 기본이다. "Central에 알리고 → Central이 판단하고 → 멈추라고 지시" 경로였다면 CAN 지연(수 ms~수십 ms)만큼 손가락이 더 눌린다.
§6.2.5가 이걸 요구사항으로 못 박고 있다.
"시스템은 윈도우 제어 관련 통신 오류가 발생하더라도 로컬 윈도우 제어기에서 수행하는 Anti-pinch 보호 기능을 유지해야 한다."
통신이 완전히 죽어도 Anti-pinch는 살아 있어야 한다. 그러려면 감지-정지-보호동작이 전부 S32K144 로컬에서 닫혀 있어야 한다. CAN으로 나가는 건 "알림"일 뿐 "제어 경로"가 아니다.
경고음은 그 반대다. VSS는 Central에 있으므로 CAN을 타야 한다. 그래서 소리는 조금 늦게 난다. 이건 결함이 아니라 설계상 불가피한 것이고, 대신 실제 보호 동작은 이미 끝나 있다. **"보호는 로컬, 알림은 중앙"**이 이 시스템의 안전 아키텍처 요약이다.
6. 한 줄 요약
| 절 | 한 줄 |
|---|---|
| §6.1.1 | 전원·도어(차임/경적), 위험(경고음), 조작(피드백) 세 그룹. 잠금 1회·해제 2회는 요구사항이다 |
| §6.1.2 | 안티핀치 최우선 → 비상경고 → 일반 → 피드백. 미디어는 순위 밖(Ducking/Mute 대상). 같은 등급끼리는 중재 |
| §6.1.3 | 주의=Ducking+단속음 / 긴급=Mute+연속음. 무음 설정은 피드백만, 경고는 예외. 안전음에는 음량 하한 |
| §6.1.4 | 입력 불신 → 소리로 알림 / 자체 오류 → 화면으로 알림. 복구는 둘 다 정상일 때만 |
설계 판단 체크포인트
구현에 들어가기 전에 팀이 답을 갖고 있어야 하는 것들이다. 답이 안 나오면 그 자리가 곧 설계 문의 또는 TBD 후보다.
-
사용자가 HMI에서 무음(Mute)을 켰다. ROA 비상 사이렌은 울려야 하는가? 울려야 한다. §6.1.3의 무음 설정은 "피드백 및 모드 전환 음향"만 억제한다. 안전 기능은 사용자 설정으로 무력화되지 않는다. 구현 시 mute 체크를 오디오 출력 공통 경로에 넣으면 이 요구사항이 깨진다.
-
도어 잠금 명령을 보낸 직후 차임을 울렸다. 무엇이 잘못됐나? §6.1.1은 "정상적으로 완료된 경우"를 요구한다. §6.4.1은 "실제 목표 상태가 확인되지 않는 경우 정상 완료로 처리하지 않아야 한다"고 한다. 액추에이터 구동 후 도어 상태 피드백을 확인하고 울려야 한다. 명령 즉시 울리면 잠금 실패 시에도 성공 차임이 울리는 결함이 된다.
-
안티핀치 경고음이 나가는 동안 ROA 사이렌 조건이 성립하면? 안티핀치가 최우선(§6.1.2)이므로 계속 나간다. 다만 ROA는 "차량 전원 상태와 관계없이" 울려야 하는 인명 관련 기능이므로, 실제 설계에서는 두 소리의 우선순위를 재검토할 여지가 있다. SR 문장만으로는 안티핀치가 이긴다가 답이지만, 이런 조합이 실제로 발생 가능한지(창문 조작 중 실내 고온 잔류 탑승자)와 함께 설계 문의로 올릴 만한 지점이다.
-
미디어를 Ducking하는 것과 Mute하는 것의 구현 차이는? Ducking은 게인만 낮추므로 디코더·DMA가 계속 돈다 → 복구가 즉각적이고 재생 위치가 유지된다. Mute는 게인 0으로 하거나 디코더를 멈추는데, 후자를 택하면 복구 시 재생 위치를 별도 관리해야 하고 버퍼 재충전 지연이 생긴다. §6.1.3이 "장애물이 경고 범위를 벗어난 경우 서서히 정상 수준으로 복구(Fade-in)"를 요구하므로, Mute도 게인 0 방식으로 구현하는 게 정합적이다.
-
야간 감쇄가 "야간 AND 주차/정차"인데, 주행 중 신호 대기로 정차했다. 감쇄해야 하나? 마지막 요구사항이 답을 준다 — "차량 시동이 걸려 있는 상태인 경우 시간 정보와 관계없이 야간 감쇄를 적용하지 않아야 한다." 시동이 걸려 있으므로 감쇄하지 않는다. 즉 "주차 또는 정차"는 시동 꺼진 상태의 정차를 뜻한다고 읽어야 두 문장이 정합적이다. 이런 용어 충돌도 리뷰에서 잡아야 할 항목이다.
-
CAN이 완전히 끊긴 상태에서 창문에 손이 끼었다. 무슨 일이 일어나는가? §6.2.5에 따라 Power Window Controller 로컬에서 감지·정지·보호동작이 모두 수행된다. 그러나 VSS 경고음은 나지 않는다 — Central이 이벤트를 못 받기 때문이다. 그리고 §6.2.6에 따라 HMI는 마지막 정상 윈도우 상태를 현재 상태로 표시하지 않아야 하므로, 사용자는 "윈도우 상태 확인 불가"를 보게 된다. 물리적 보호는 되지만 사용자 인지는 열화된다 — 이게 이 아키텍처가 감수한 트레이드오프다.