feat: add realistic portable localization core
This commit is contained in:
+11
-3
@@ -4,9 +4,17 @@
|
||||
|
||||
JSON Schema Draft 2020-12 형식입니다.
|
||||
|
||||
- `array.schema.json`: 배열 크기, 좌표계, 마이크 위치와 선택적 보정값
|
||||
- `scene.schema.json`: 재현 가능한 음원 recipe, asset 참조, 정적 위치와 선택적 trajectory
|
||||
- `array.schema.json`: 배열 크기, 좌표계, 마이크 위치와 선택적 scalar/주파수 응답 보정값
|
||||
- `scene.schema.json`: 음원 recipe, asset·trajectory와 선택적 sparse shoebox 음향 환경
|
||||
- `experiment.schema.json`: scan plane/grid, 주파수 대역, STFT/DAS와 peak 검출 임계값
|
||||
- `result.schema.json`: raw/display/후처리 map, 복수 peak, 비확률 beam spread, timing과 평가 지표
|
||||
|
||||
중복 id, Nyquist, 시간 구간과 참조 무결성은 `packages/contracts/validation.js`에서 추가로 검증합니다.
|
||||
마이크 주파수 응답점은 배열 계약 자체이므로 특정 Scene의 Nyquist와 결합하지 않고 0~1 MHz의
|
||||
안전 범위에서 엄격한 오름차순을 요구합니다. 실제 분석에서는 선택한 Scene/STFT의 bin 주파수만
|
||||
보간합니다. 중복 id, Nyquist, 시간 구간과 참조 무결성은
|
||||
`packages/contracts/validation.js`에서 추가로 검증합니다.
|
||||
|
||||
Scene `acoustics`는 기본 `free-field` 또는 `shoebox`입니다. shoebox는 room bounds, 0/1차
|
||||
반사와 scattering 비율, bounded diffuse tail, 최대 8개의 AABB occluder를 저장합니다.
|
||||
room·occluder의 각 축은 `min < max`여야 하고 source/trajectory와 occluder는 room 안에
|
||||
있어야 합니다. 이 계약은 전체 파동 해석이 아니라 sparse path 근사의 입력입니다.
|
||||
|
||||
@@ -42,7 +42,20 @@
|
||||
"id": { "type": "string", "minLength": 1, "maxLength": 64 },
|
||||
"position": { "$ref": "#/$defs/position" },
|
||||
"sensitivityDb": { "type": "number", "minimum": -120, "maximum": 120 },
|
||||
"phaseOffsetDeg": { "type": "number", "minimum": -180, "maximum": 180 }
|
||||
"phaseOffsetDeg": { "type": "number", "minimum": -180, "maximum": 180 },
|
||||
"frequencyResponse": {
|
||||
"type": "array", "minItems": 2, "maxItems": 64,
|
||||
"items": { "$ref": "#/$defs/frequencyResponsePoint" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"frequencyResponsePoint": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["frequencyHz", "gainDb"],
|
||||
"properties": {
|
||||
"frequencyHz": { "type": "number", "minimum": 0, "maximum": 1000000 },
|
||||
"gainDb": { "type": "number", "minimum": -120, "maximum": 120 },
|
||||
"phaseDeg": { "type": "number", "minimum": -180, "maximum": 180 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@
|
||||
"algorithm": { "const": "das" }, "backend": { "enum": ["auto", "cpu", "webgpu"] },
|
||||
"minimumDistance": { "type": "number", "exclusiveMinimum": 0, "maximum": 10 },
|
||||
"normalization": { "enum": ["peak", "none"] },
|
||||
"dynamicRangeDb": { "type": "number", "minimum": 6, "maximum": 120 }
|
||||
"dynamicRangeDb": { "type": "number", "minimum": 6, "maximum": 120 },
|
||||
"compensateFrequencyResponse": { "type": "boolean" }
|
||||
}
|
||||
},
|
||||
"evaluation": {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"targetPeak": { "type": "number", "exclusiveMinimum": 0, "maximum": 1 }
|
||||
}
|
||||
},
|
||||
"acoustics": { "$ref": "#/$defs/acoustics" },
|
||||
"image": { "$ref": "#/$defs/image" },
|
||||
"assets": { "type": "array", "maxItems": 128, "items": { "$ref": "#/$defs/asset" } },
|
||||
"sources": { "type": "array", "minItems": 1, "maxItems": 32, "items": { "$ref": "#/$defs/source" } },
|
||||
@@ -38,6 +39,67 @@
|
||||
"position": { "$ref": "#/$defs/position" }
|
||||
}
|
||||
},
|
||||
"wallLevels": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"properties": {
|
||||
"xMin": { "type": "number", "minimum": -60, "maximum": 0 },
|
||||
"xMax": { "type": "number", "minimum": -60, "maximum": 0 },
|
||||
"yMin": { "type": "number", "minimum": -60, "maximum": 0 },
|
||||
"yMax": { "type": "number", "minimum": -60, "maximum": 0 },
|
||||
"zMin": { "type": "number", "minimum": -60, "maximum": 0 },
|
||||
"zMax": { "type": "number", "minimum": -60, "maximum": 0 }
|
||||
}
|
||||
},
|
||||
"room": {
|
||||
"type": "object", "additionalProperties": false, "required": ["min", "max"],
|
||||
"properties": {
|
||||
"min": { "$ref": "#/$defs/position" },
|
||||
"max": { "$ref": "#/$defs/position" }
|
||||
}
|
||||
},
|
||||
"reflections": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["order", "wallGainDb", "scattering"],
|
||||
"properties": {
|
||||
"order": { "enum": [0, 1] },
|
||||
"wallGainDb": { "type": "number", "minimum": -60, "maximum": 0 },
|
||||
"perWallDb": { "$ref": "#/$defs/wallLevels" },
|
||||
"scattering": { "type": "number", "minimum": 0, "maximum": 1 }
|
||||
}
|
||||
},
|
||||
"diffuseReverb": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["enabled", "rt60Seconds", "gainDb", "tapCount"],
|
||||
"properties": {
|
||||
"enabled": { "type": "boolean" },
|
||||
"rt60Seconds": { "type": "number", "minimum": 0.05, "maximum": 5 },
|
||||
"gainDb": { "type": "number", "minimum": -60, "maximum": 0 },
|
||||
"tapCount": { "type": "integer", "minimum": 1, "maximum": 32 }
|
||||
}
|
||||
},
|
||||
"occluder": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["id", "min", "max", "transmissionDb", "diffractionGainDb"],
|
||||
"properties": {
|
||||
"id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
|
||||
"min": { "$ref": "#/$defs/position" },
|
||||
"max": { "$ref": "#/$defs/position" },
|
||||
"transmissionDb": { "type": "number", "minimum": -120, "maximum": 0 },
|
||||
"diffractionGainDb": { "type": "number", "minimum": -120, "maximum": 0 }
|
||||
}
|
||||
},
|
||||
"acoustics": {
|
||||
"type": "object", "additionalProperties": false, "required": ["model"],
|
||||
"properties": {
|
||||
"model": { "enum": ["free-field", "shoebox"] },
|
||||
"room": { "$ref": "#/$defs/room" },
|
||||
"reflections": { "$ref": "#/$defs/reflections" },
|
||||
"diffuseReverb": { "$ref": "#/$defs/diffuseReverb" },
|
||||
"occluders": {
|
||||
"type": "array", "maxItems": 8, "items": { "$ref": "#/$defs/occluder" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"image": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["assetId", "widthPixels", "heightPixels", "plane"],
|
||||
|
||||
Reference in New Issue
Block a user