コンテンツにスキップ

Listening Point の座標制限と送信方式

本書では、BATCAM FX の Listening Point(LPoint)を API で設定したり画面に表示したりする際に必要となるインデックス座標系最小距離制限、および API 送信用の 40×15 インデックス圧縮・復元ルールについて説明します。LPoint インデックスを扱うコードはすべて、本書の座標系ルール(右下原点)を前提として作成する必要があります。

BATCAM FX から送信される Beamforming イベントの BF Map は 40x30 の構造で構成されており、送信時には 1x1200 構造の Array として渡されます。

BATCAM FX の RTSP 映像に BF Map を可視化した例の画面。緑色の部分が例として設定された Listening Point

BATCAM FX の RTSP 映像に BF Map を可視化する場合を想定した写真。緑色の部分は例として設定されたと想定した Listening Point。

BATCAM FX の LPoint 機能は 3 個まで指定でき、指定した位置でビームフォーミングされたオーディオ信号が LPointAudio メッセージ(ROS トピック /fx_{hardware_id}/lpoint_audio、チャンネル lpoint0~lpoint2)を通じて送信されます。メッセージ構造は ROS 連携ドキュメントを参照してください。

インデックス座標系

LPoint は 40×30 サイズの 2D グリッドを 1 次元インデックス(0~1199)で表現します。

⚠️ 座標系に関する注意: BATCAM FX の BF Map インデックスは右下が 0、左上が 1199 です。一般的な左上原点(0)の座標系とは逆であるため、圧縮/復元の際には必ず 1199 - n の変換が必要です。この変換を行わずに直接 n % 40n / 40 で計算すると、誤った結果になります。

インデックスは右下(0)から始まって左方向に増加し、1 行(40 マス)が終わると 1 行上に上がります。つまり、グリッド座標を x = n mod 40y = ⌊n / 40⌋ で計算すると、x は右から左へ、y は下から上へ増加します。四隅のインデックスは次のとおりです。

位置インデックス
右下0
左下39
右上1160
左上1199

制限事項

Listening Point を設定する際、2 つの地点間の距離が近すぎてはいけません

現在 BATCAM FX の LPoint 設定では、次のような最小距離制限が設定されています:

  • 横方向: 最小 ±2 マス以上

  • 縦方向: 最小 ±2 マス以上

つまり、1 つの Listening Point が指定されると、そこから横・縦に 2 マス以内のすべての領域は、他の Listening Point として使用できません。

例えば、次のような Listening Point を指定したと仮定する場合(以下の x・y は x = n mod 40y = ⌊n / 40⌋ で計算したグリッド座標 — 右下原点基準):

  • Listening Point A: インデックス 20(x=20, y=0)

  • Listening Point B: インデックス 580(x=20, y=14)

この 2 つの Listening Point の周辺には、次のような制限領域が設定されます:

  • A を基準として: 18 ≤ x ≤ 22、0 ≤ y ≤ 2(y の負の方向はグリッド外のため 0 で切り取られます)

  • B を基準として: 18 ≤ x ≤ 22、12 ≤ y ≤ 16

この範囲内に追加の Listening Point を設定してはいけません。

API で使用するための LPoint インデックスの圧縮および復元

API リクエスト時には、縦方向の解像度を半分に縮小した 40×15 の形式(インデックス 0599)に変換してインデックスを送信する必要があります。ファームウェア v1.0.2d から、ビームフォーミング設定 API の lpoint インデックスの許容範囲が 01199 から 0~599 に変更されました(ファームウェアリリースノートを参照)。

そのために、次の式を使用して圧縮(Downsize)および復元(Upsize)を行います。

💡 参考: 圧縮は縦方向の解像度を半分に縮小するため、情報が失われる場合があります。座標の精度が必要な場合は、圧縮前の元のインデックスを別途保存してください。損失・復元ルールの詳細については、下記の限界および境界値セクションを参照してください。

インデックス圧縮 (Downsize)

1 次元インデックス n(0~1199)を 40×15 グリッド基準に変換します。

座標系を反転(1199 - n)した後、縦方向の解像度を半分に縮小して y 座標を圧縮します。

数式:

f(n)=401199n402+((1199n)mod40)f(n) = 40 \cdot \left\lfloor \frac{\left\lfloor \frac{1199 - n}{40} \right\rfloor}{2} \right\rfloor + ((1199 - n) \bmod 40)

例:

  • f(120) → 559

  • f(600) → 319

  • f(1160) → 39

インデックス復元 (Upsize)

圧縮されたインデックスを元の 40×30 基準に復元します。

圧縮時に失われた 1 行のうち上側の行(y * 2) を基準に復元した後、座標系を再び反転します。

数式:

f1(n)=1199(40(2n40)+(nmod40))f^{-1}(n) = 1199 - \left(40 \cdot (2 \cdot \left\lfloor \frac{n}{40} \right\rfloor) + (n \bmod 40)\right)

例:

  • f⁻¹(559) → 120

  • f⁻¹(319) → 600

  • f⁻¹(39) → 1160

使用箇所の要約

状況使用する関数説明
API リクエスト時の座標送信Downsize40×30 → 40×15 圧縮
ユーザー画面への座標出力Upsize40×15 → 40×30 復元

これを各言語に対応するコードで表現すると、次のとおりです。

Swift

extension Int {
func lPointDownSized() -> Int {
let value = 1199 - self
let x = value % 40
let y = value / 40
let downY = y / 2
return downY * 40 + x
}
func lPointUpSized() -> Int {
let x = self % 40
let y = self / 40
let upY = y * 2
return 1199 - (upY * 40 + x)
}
}

Python

def l_point_down_sized(n: int) -> int:
value = 1199 - n
x = value % 40
y = value // 40
down_y = y // 2
return down_y * 40 + x
def l_point_up_sized(n: int) -> int:
x = n % 40
y = n // 40
up_y = y * 2
return 1199 - (up_y * 40 + x)

C#

public static class LPointExtensions
{
public static int LPointDownSized(this int n)
{
int value = 1199 - n;
int x = value % 40;
int y = value / 40;
int downY = y / 2;
return downY * 40 + x;
}
public static int LPointUpSized(this int n)
{
int x = n % 40;
int y = n / 40;
int upY = y * 2;
return 1199 - (upY * 40 + x);
}
}

C++

int lPointDownSized(int n) {
int value = 1199 - n;
int x = value % 40;
int y = value / 40;
int downY = y / 2;
return downY * 40 + x;
}
int lPointUpSized(int n) {
int x = n % 40;
int y = n / 40;
int upY = y * 2;
return 1199 - (upY * 40 + x);
}

API 送信方式

変換した LPoint インデックスは、ビームフォーミング設定 API の index_l パラメータとして送信します。BATCAM FX 機器が API を直接提供しており(基本 URL http://{device_ip})、認証には Basic 認証を使用します。

項目内容
設定の照会GET /beamforming/setting — 現在のビームフォーミング設定値を返し、レスポンスの index_l は整数 3 個の配列です。
設定の変更PATCH /beamforming/settingmultipart/form-data 形式で送信します。
index_l のリクエスト形式カンマで区切られた 3 個の L point 文字列(例: 20,510,579)
注意部分的な設定は反映されないため、全体の値を送信する必要があります。まず GET で現在の設定を取得した後、index_l のみを修正して全体を再度送信してください。
エラーレスポンス誤った lpoint パラメータを渡した場合、400 レスポンス(error: 1message: lpoint parameter error)が返されます。

成功時のレスポンスはエンベロープ構造で返されます:

{
"error": 0,
"result": {
"autogain": true,
"gain": 100,
"x_cal": -0.06,
"y_cal": 0,
"distance": 1,
"high_cut": 45000,
"low_cut": 2000,
"index_l": [20, 510, 579]
}
}

リクエスト/レスポンスの全体スキーマと実際の呼び出しテストは、FX API プレイグラウンドの beamforming グループで確認できます。index_l を含む各ビームフォーミング設定値の属性については、ビームフォーミングパラメータドキュメントを参照してください。

限界および境界値

縦方向の解像度の圧縮は情報の損失を伴います。 提供される各圧縮・復元関数は縦方向のみを半分に圧縮するため、元々は互いに異なる 2 つのインデックスが同じ値にマッピングされる場合があります。例えば 040 は圧縮時にどちらも 599 になり、11591199 はどちらも 0 になります。

復元関数は常に上側のラインを基準に復元されます。 復元関数は圧縮されたインデックスを復元する際、元々存在し得た 2 行のうち上側(y * 2)の行を基準に復元した後、座標系を再び反転(1199 - result)します。

したがって、API レスポンスや結果を表示する際、ユーザーが認識する位置よりわずかにずれる場合があるため、正確な復元が必要な場合は、圧縮前に元の座標情報を別途保存しておく必要がある場合があります。

境界値処理の要約

下の表の完全復元の可否は、圧縮(Downsize)後に復元(Upsize)したときに、元の入力インデックスがそのまま戻ってくるかどうかを意味します。例えば 0599 に圧縮された後 40 に復元されるため ❌ であり、40 は同じ 599 に圧縮されますが復元結果が再び 40 になるため ✅ です。

入力値圧縮結果復元結果完全復元の可否
059940❌ (衝突の可能性あり)
4059940
115901199❌ (衝突の可能性あり)
1160391160
119901199

一般化すると、反転された座標系(1199 - n)を基準に偶数の y 行にあるインデックスは完全に復元されます。