Skip to content
This is the development version of the documentation. It may change before the next release. See 0.6.x for the latest release.

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 multiple focal points fit in a single frame, so the number of frames is small and the latency is low.

FociStm::new(freq, &points, option);
Parameter Type Description
freq impl Into<StmConfig> Playback rate (Freq / Duration / SamplingConfig)
points &[ControlPoints<N>] Sequence of focal point samples (at least 2 samples)
option FociStmOption Options such as sound speed, loop, and transition

Passing a Freq / Duration to freq represents “the frequency/period for one full cycle over all samples”. A sampling frequency can also be specified. A Duration that is not divisible by the number of samples is an error (use Nearest to round it).

A single sample is represented by ControlPoints<N>. N is the number of focal points emitted simultaneously (up to 8).

  • ControlPoint { point, phase_offset } — focal point coordinate [mm] and phase offset.
  • ControlPoints<N> { points: [ControlPoint; N], intensity }N focal points and an amplitude.
FociStmOption {
bank,
sound_speed,
loop_behavior,
transition_mode,
}
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.

Helper functions are provided to generate typical trajectories.

circle(center, radius, num_points, normal, intensity, &mut dst);
Parameter Type Description
center Point3<f32> Center of the circle [mm]
radius Length Radius of the circle
num_points usize Number of points to generate
normal UnitVector3<f32> Normal of the circle plane (unit vector)
intensity Intensity Amplitude of each point
dst &mut Vec<ControlPoints<1>> Output buffer

Places num_points points at equal intervals on a circle whose normal is normal.

line(start, end, num_points, intensity, &mut dst);
Parameter Type Description
start Point3<f32> Start point [mm]
end Point3<f32> End point [mm]
num_points usize Number of points to generate
intensity Intensity Amplitude of each point
dst &mut Vec<ControlPoints<1>> Output buffer

Places num_points points at equal intervals along a line including the start and end points.

FociStm is equivalent to the three commands WriteFociBuffer + ConfigFociStm + ChangePatternBank. When the data fits in a single frame it is fused and sent as one frame; otherwise it expands into the three commands above. The following is equivalent to FociStm::new(freq, &points, option).

WriteFociBuffer {
bank: option.bank,
index_offset: 0,
points: &points,
};
ConfigFociStm {
bank: option.bank,
config: StmConfig::new(freq).into_sampling_config(points.len()),
size: points.len(),
num_foci: N, // N is the number of foci in the points
sound_speed: option.sound_speed,
loop_behavior: option.loop_behavior,
};
ChangePatternBank {
bank: option.bank,
transition_mode: option.transition_mode,
};
use autd3_rs::commands::{FociStm, FociStmOption, circle};
use autd3_rs::geometry::{Autd3, Geometry, Vector3, offset};
use autd3_rs::units::{Hz, m, mm, s};
use autd3_rs::value::{Intensity, LoopBehavior, PatternBank, TransitionMode};
use autd3_rs::{Client, ClientConfig};
use autd3_rs_link_nop::Nop;
let geometry = Geometry::new(vec![Autd3::default()]);
let client = Client::open(&geometry, Nop, ClientConfig::default()).await?;
let center = geometry.center() + offset(0.0 * mm, 0.0 * mm, 150.0 * mm);
let mut points = Vec::new();
circle(
center,
30.0 * mm,
200,
Vector3::z_axis(),
Intensity::MAX,
&mut points,
);
let mut builder = client.datagram_builder();
builder.push(FociStm::new(
1.0 * Hz,
&points,
FociStmOption {
bank: PatternBank::B0,
sound_speed: 340.0 * m / s,
loop_behavior: LoopBehavior::Infinite,
transition_mode: TransitionMode::Immediate,
},
));
let frames = builder.build()?;
for frame in &frames {
client.send_checked(frame).await?;
}
client.close().await?;