バンクの切り替え
焦点の移動で説明したように, AUTD3 において Pattern 等は送信するたびに上書きされ, この書き込みはバッファリングされない.
そのため, 再生中のデータを上書きすると, 書き込みの途中で意図しない中間データが出力されてしまうことがある.
これを防ぐために, AUTD3 の Pattern は複数のメモリ領域 (バンクと呼ぶ) を持っている.
再生中でない別のバンクへ書き込み, 書き込み完了後に再生対象をそのバンクへ切り替えれば, 出力を乱さずにデータを差し替えられる.
バンクを指定して書き込む
Section titled “バンクを指定して書き込む”書き込み先・再生対象のバンクは Pattern::with_bank で指定する.
Pattern::new ( バンク省略時) は PatternBank::B0 を使う.
下記の例では, まず B0 へ焦点 A を書き込んで再生し, 次の焦点 B は再生中でない B1 へ書き込む.
B1 への書き込み中も B0 の出力は乱れず, 書き込み完了後に B1 へ切り替わる.
// Write focus A to bank B0 and play it.let target_a = geometry.center() + offset(0.0 * mm, 0.0 * mm, 150.0 * mm);let mut pat_a = geometry.pattern_buffer();autd3_rs_pattern::focus( &geometry, target_a, wavelength, &autd3_rs_pattern::FocusOption::default(), &mut pat_a,);let mut builder = client.datagram_builder();builder.push(Pattern::with_bank(PatternBank::B0, &pat_a));for frame in &builder.build()? { client.send_checked(frame).await?;}
// Write focus B to bank B1, which is not currently playing, then switch to B1.// B0 keeps playing cleanly while B1 is being written (double buffering).let target_b = geometry.center() + offset(0.0 * mm, 30.0 * mm, 150.0 * mm);let mut pat_b = geometry.pattern_buffer();autd3_rs_pattern::focus( &geometry, target_b, wavelength, &autd3_rs_pattern::FocusOption::default(), &mut pat_b,);let mut builder = client.datagram_builder();builder.push(Pattern::with_bank(PatternBank::B1, &pat_b));for frame in &builder.build()? { client.send_checked(frame).await?;}# Write focus A to bank B0 and play it.target_a = geometry.center() + np.array([0.0, 0.0, 150.0])pat_a = geometry.pattern_buffer()pattern.focus( geometry, target_a, wavelength, pattern.FocusOption(), pat_a,)builder = client.datagram_builder()builder.push(Pattern(pat_a, bank=PatternBank.B0))for frame in builder.build(): await client.send_checked(frame)
# Write focus B to bank B1, which is not currently playing, then switch to B1.# B0 keeps playing cleanly while B1 is being written (double buffering).target_b = geometry.center() + np.array([0.0, 30.0, 150.0])pat_b = geometry.pattern_buffer()pattern.focus( geometry, target_b, wavelength, pattern.FocusOption(), pat_b,)builder = client.datagram_builder()builder.push(Pattern(pat_b, bank=PatternBank.B1))for frame in builder.build(): await client.send_checked(frame)// Write focus A to bank B0 and play it.var targetA = geometry.Center + new Vector3(0.0f, 0.0f, 150.0f);var patA = geometry.PatternBuffer();Pattern.Focus( geometry, targetA, wavelength, new FocusOption(), patA);var builder = client.DatagramBuilder();builder.Push(new Pattern(PatternBank.B0, patA));foreach (var frame in builder.Build()){ await client.SendCheckedAsync(frame);}
// Write focus B to bank B1, which is not currently playing, then switch to B1.// B0 keeps playing cleanly while B1 is being written (double buffering).var targetB = geometry.Center + new Vector3(0.0f, 30.0f, 150.0f);var patB = geometry.PatternBuffer();Pattern.Focus( geometry, targetB, wavelength, new FocusOption(), patB);var builder2 = client.DatagramBuilder();builder2.Push(new Pattern(PatternBank.B1, patB));foreach (var frame in builder2.Build()){ await client.SendCheckedAsync(frame);}このように再生中でないバンクへ交互に書き込むことで, 出力を乱さずにパターンを差し替えられる.
Modulation も同様にバンクを持っており, Modulation::with_bank で書き込み先のバンク (ModulationBank) を指定できる.
バンクの書き込み・設定・切り替えをより細かく制御したい場合は, API リファレンスの 低レベルコマンド を参照.