FociStm
FociStm provides an STM feature that switches single- and multi-focus sound fields by a hardware timer.
Unlike PatternStm, it can only handle focal points, but the amount of data to transfer is small and the latency is low.
FociStm::new(config, &points, option);FociStm(config, points, option)new FociStm(config, points, option);| Parameter | Type | Description |
|---|---|---|
config |
SamplingConfig |
Sampling configuration per sample |
points |
&[ControlPoints] |
Sequence of focal point samples (at least 2 samples) |
option |
FociStmOption |
Options such as sound speed, loop, and transition |
config is the sampling configuration per sample. To derive it from “the frequency of one full cycle over all samples”, multiply that frequency by the number of samples (e.g. 200 samples at 1 Hz is 200 Hz).
ControlPoint / ControlPoints
Section titled “ControlPoint / ControlPoints”A single sample is represented by ControlPoints. The length of points is the number of focal points emitted simultaneously (1 to 8), and it must be the same for every sample (otherwise sending fails with an error).
ControlPoint { point, phase_offset }— focal point coordinate [mm] and phase offset.ControlPoints { points: Vec<ControlPoint>, intensity }— a sequence of focal points and an amplitude.
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,}| Field | Type | Default | Description |
|---|---|---|---|
bank |
PatternBank |
PatternBank::B0 |
Bank to write to / play back |
sound_speed |
Velocity |
340 m/s |
Sound speed used for focus computation |
loop_behavior |
LoopBehavior |
LoopBehavior::Infinite |
Loop count |
transition_mode |
TransitionMode |
TransitionMode::Immediate |
Transition timing on bank switching |
For the behavior of loop_behavior and transition_mode, see playback control.
Equivalent Low-Level Commands
Section titled “Equivalent Low-Level Commands”FociStm is equivalent to the three commands WriteFociBuffer + ConfigFociStm + ActivatePatternBank.
The following is equivalent to 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, }));