FociStm
FociStm は, ハードウェアタイマにより単一, 及び, 多焦点音場を切り替える STM 機能を提供する.
PatternStm と異なり, 焦点しか扱えないが, 転送データ量が少なく, レイテンシが小さい.
FociStm::new(config, &points, option);FociStm(config, points, option)new FociStm(config, points, option);| 引数 | 型 | 説明 |
|---|---|---|
config |
SamplingConfig |
サンプル毎のサンプリング設定 |
points |
&[ControlPoints] |
焦点サンプルの列 (2 サンプル以上) |
option |
FociStmOption |
音速・ループ・遷移などのオプション |
config は 1 サンプルあたりのサンプリング設定である. 「全サンプルを 1 周する周波数」から決めたいときは, 周波数にサンプル数を掛けて SamplingConfig を作る (例: 200 サンプルを 1 Hz で回すなら 200 Hz).
ControlPoint / ControlPoints
Section titled “ControlPoint / ControlPoints”1 サンプルは ControlPoints で表される. points の長さが同時に出す焦点の数 (1 以上 8 以下) で, 全サンプルで揃っていなければならない (揃っていないと送信時にエラーになる).
ControlPoint { point, phase_offset }— 焦点座標 [mm] と位相オフセット.ControlPoints { points: Vec<ControlPoint>, intensity }— 焦点の列と振幅.
FociStmOption
Section titled “FociStmOption”FociStmOption { bank, sound_speed, loop_behavior, transition_mode, ..Default::default()}FociStmOption( bank, sound_speed, loop_behavior, transition_mode,)new FociStmOption{ Bank = bank, SoundSpeed = soundSpeed, LoopBehavior = loopBehavior, TransitionMode = transitionMode,}| フィールド | 型 | デフォルト | 説明 |
|---|---|---|---|
bank |
PatternBank |
PatternBank::B0 |
書き込み先・再生対象のバンク |
sound_speed |
Velocity |
340 m/s |
焦点計算に使う音速 |
loop_behavior |
LoopBehavior |
LoopBehavior::Infinite |
ループ回数 |
transition_mode |
TransitionMode |
TransitionMode::Immediate |
バンク切替時の遷移タイミング |
loop_behavior と transition_mode の挙動は再生制御 を参照.
等価な低レベルコマンド
Section titled “等価な低レベルコマンド”FociStm は WriteFociBuffer + ConfigFociStm + ActivatePatternBank の 3 つと等価である.
以下は FociStm::new(config, &points, option) と等価な組み合わせである.
let max_len = WriteFociBuffer::max_len(num_foci);for (i, chunk) in points.chunks(max_len).enumerate() { WriteFociBuffer { bank: option.bank, start_index: i * max_len, points: chunk, };}ConfigFociStm { bank: option.bank, config, size: points.len(), num_foci, sound_speed: option.sound_speed, loop_behavior: option.loop_behavior,};ActivatePatternBank { bank: option.bank, transition_mode: option.transition_mode,};max_len = WriteFociBuffer.max_len(num_foci)for start_index in range(0, len(points), max_len): WriteFociBuffer( bank=option.bank, start_index=start_index, points=points[start_index : start_index + max_len], )ConfigFociStm( bank=option.bank, config=config, size=len(points), num_foci=num_foci, sound_speed=option.sound_speed, loop_behavior=option.loop_behavior,)ActivatePatternBank( bank=option.bank, transition_mode=option.transition_mode,)var maxLen = WriteFociBuffer.MaxLen(numFoci);for (var startIndex = 0; startIndex < points.Length; startIndex += maxLen){ new WriteFociBuffer( bank: option.Bank, startIndex: (uint)startIndex, points: points[startIndex..Math.Min(startIndex + maxLen, points.Length)] );}new ConfigFociStm( bank: option.Bank, config: config, size: (uint)points.Length, numFoci: numFoci, soundSpeed: option.SoundSpeed, loopBehavior: option.LoopBehavior);new ActivatePatternBank( bank: option.Bank, transitionMode: option.TransitionMode);Example
Section titled “Example”use std::f32::consts::PI;
use autd3_rs::commands::{Clear, FociStm, FociStmOption, Synchronize};use autd3_rs::geometry::{Autd3, Geometry, offset};use autd3_rs::units::{Hz, m, mm, s};use autd3_rs::value::{ControlPoints, LoopBehavior, PatternBank, SamplingConfig, TransitionMode};use autd3_rs::Client;use autd3_rs::udp::TransportOption;
let geometry = Geometry::new(vec![Autd3::default()]);let option = TransportOption::default();let mut client = Client::open(&geometry, &option).await?;client.send(Clear).await?;client.send(Synchronize).await?;
let center = geometry.center() + offset(0.0 * mm, 0.0 * mm, 150.0 * mm);let points: Vec<ControlPoints> = (0..200) .map(|i| { let theta = 2.0 * PI * i as f32 / 200.0; ControlPoints::from(center + offset(30.0 * mm * theta.cos(), 30.0 * mm * theta.sin(), 0.0 * mm)) }) .collect();
client.send(FociStm::new( SamplingConfig::from_freq(1.0 * Hz * points.len() as f32)?, &points, FociStmOption { bank: PatternBank::B0, sound_speed: 340.0 * m / s, loop_behavior: LoopBehavior::Infinite, transition_mode: TransitionMode::Immediate, ..Default::default() },)).await?;import asyncioimport math
from autd3 import Client, TransportOptionfrom autd3.commands import Clear, FociStm, FociStmOption, Synchronizefrom autd3.geometry import Autd3, Geometry, offsetfrom autd3.units import Hz, m, mm, sfrom autd3.value import ControlPoints, LoopBehavior, PatternBank, SamplingConfig, TransitionMode
async def main() -> None: geometry = Geometry([Autd3()]) with await Client.open(geometry, TransportOption()) as client: await client.send(Clear()) await client.send(Synchronize())
center = geometry.center() + offset(0.0 * mm, 0.0 * mm, 150.0 * mm) points = [] for i in range(200): theta = 2.0 * math.pi * i / 200 p = center + offset(30.0 * mm * math.cos(theta), 30.0 * mm * math.sin(theta), 0.0 * mm) points.append(ControlPoints(p))
await client.send( FociStm( SamplingConfig(1.0 * Hz * len(points)), points, FociStmOption( bank=PatternBank.B0, sound_speed=340 * m / s, loop_behavior=LoopBehavior.Infinite, transition_mode=TransitionMode.Immediate, ), ) )
asyncio.run(main())using System;using System.Linq;using System.Threading.Tasks;using AUTD3;using static AUTD3.Units;
var geometry = new Geometry(new[] { new Autd3() });using var client = await Client.OpenAsync(geometry, new TransportOption());await client.SendAsync(new Clear());await client.SendAsync(new Synchronize());
var center = geometry.Center + Offset(0.0f * mm, 0.0f * mm, 150.0f * mm);var points = Enumerable.Range(0, 200) .Select(i => 2.0f * MathF.PI * i / 200) .Select(theta => (ControlPoints)(center + Offset(MathF.Cos(theta) * 30.0f * mm, MathF.Sin(theta) * 30.0f * mm, 0.0f * mm))) .ToArray();
await client.SendAsync(new FociStm( new SamplingConfig(1.0f * Hz * points.Length), points, new FociStmOption { Bank = PatternBank.B0, SoundSpeed = 340.0f * m / s, LoopBehavior = LoopBehavior.Infinite, TransitionMode = TransitionMode.Immediate, }));