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

PatternStm

PatternStm provides an STM feature that switches arbitrary sound fields (the phase and intensity of each transducer) by a hardware timer. Unlike FociStm, it can handle arbitrary Patterns, but the amount of data to transfer is large (i.e. the latency is high).

PatternStm::new(config, &patterns, intensities, option);
Parameter Type Description
config SamplingConfig Sampling configuration per sample
phases &[Vec<Vec<Phase>>] Phases of each sample (at least 2 samples)
intensities impl Into<StmIntensity> Intensities for every sample (a uniform value, one buffer shared by all indices, or one buffer per index)
option PatternStmOption Options such as phase depth, loop, and transition

config is the sampling configuration per sample.

intensities accepts the following three types.

  • Intensity: to use the same value for every device, every transducer and every index
  • &[Vec<Intensity>]: to use values that differ per transducer but are shared by all indices
  • &[Vec<Vec<Intensity>>]: to use a different value for every index
PatternStmOption {
bank,
phase_depth,
loop_behavior,
transition_mode,
..Default::default()
}
Field Type Default Description
bank PatternBank PatternBank::B0 Bank to write to / play back
phase_depth PhaseDepth PhaseDepth::Bits8 Bit depth of the phase
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.

intensities PhaseDepth::Bits8 PhaseDepth::Bits4
Intensity WritePatternPhase (5 indices/frame) WritePatternPhase (11 indices/frame)
&[Vec<Intensity>] / &[Vec<Vec<Intensity>>] WritePatternBuffer (2 indices/frame) Error

Bits4 quantizes the phase to its upper 4 bits.

PatternStm internally expands into the three commands WritePatternPhase or WritePatternBuffer + ConfigPattern + ActivatePatternBank. The following is equivalent to PatternStm::new(config, &phases, intensities, option) when intensities is a uniform value. When intensities holds per-transducer values, WritePatternBuffer is used for 2 indices at a time instead of WritePatternPhase.

let max_count = option.phase_depth.max_count();
for (k, chunk) in patterns.chunks(max_count).enumerate() {
WritePatternPhase {
bank: option.bank,
start_index: k * max_count,
depth: option.phase_depth,
intensity: intensities,
patterns: chunk,
};
}
ConfigPattern {
bank: option.bank,
config,
size: patterns.len(),
loop_behavior: option.loop_behavior,
};
ActivatePatternBank {
bank: option.bank,
transition_mode: option.transition_mode,
};
use autd3_rs::commands::{Clear, PatternStm, PatternStmOption, PhaseDepth, Synchronize};
use autd3_rs::geometry::{Autd3, Geometry, offset};
use autd3_rs::units::{Hz, m, mm, s};
use autd3_rs::value::{Intensity, LoopBehavior, PatternBank, SamplingConfig, TransitionMode};
use autd3_rs::Client;
use autd3_rs::udp::TransportOption;
use autd3_rs_pattern::{focus, wavelength};
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 wavelength = wavelength(340.0 * m / s);
let patterns = (0..200)
.map(|i| {
let theta = 2.0 * std::f32::consts::PI * i as f32 / 200.0;
let target =
center + offset(30.0 * theta.cos() * mm, 30.0 * theta.sin() * mm, 0.0 * mm);
let mut buffer = geometry.phase_buffer();
focus(
&geometry,
target,
wavelength,
&mut buffer,
);
buffer
})
.collect::<Vec<_>>();
client.send(PatternStm::new(
SamplingConfig::from_freq(1.0 * Hz * patterns.len() as f32)?,
&patterns,
Intensity::MAX,
PatternStmOption {
bank: PatternBank::B0,
phase_depth: PhaseDepth::Bits8,
loop_behavior: LoopBehavior::Infinite,
transition_mode: TransitionMode::Immediate,
..Default::default()
},
)).await?;