先月から一連の更新を行っているが、LPF12 に変更はなかった。
2025年12月05日
LaVoixski@出力波形の記録
posted by Yasuski at 17:44| LaVoixski
2025年12月02日
LaVoixski@-1nnのオフセットが発覚したChromaticModeの判定を修正する
外部 midi 機器との間で整合性を取ったつもりだった ChromaticMode と、基音設定チューナーの間に 1nn のズレが生じている不具合が発覚した。
原因は nn 判定のオフセット値がマイナス側に作用した結果生じた不整合なので、判定の条件分岐と

midi 出力に付加していたオフセット値を修正することで

不具合に対応した。
表示系にも不具合が生じていたが、何故か直接扱っていなかった USB_MIDI への出力値を基音判定の条件分岐に割り当てて、正常な表示が行えるようになった。

外部の USB 音源に接続して、正常な運用を確認した。

その他、マニュアルを改定する過程で発覚した機能操作の不整合(タスクを配分したスイッチのミスマッチ)を解決している。
原因は nn 判定のオフセット値がマイナス側に作用した結果生じた不整合なので、判定の条件分岐と
midi 出力に付加していたオフセット値を修正することで
不具合に対応した。
表示系にも不具合が生じていたが、何故か直接扱っていなかった USB_MIDI への出力値を基音判定の条件分岐に割り当てて、正常な表示が行えるようになった。
外部の USB 音源に接続して、正常な運用を確認した。
その他、マニュアルを改定する過程で発覚した機能操作の不整合(タスクを配分したスイッチのミスマッチ)を解決している。
posted by Yasuski at 21:35| LaVoixski
2025年12月01日
LaVoixski@バグの修正とフィルターの音質を調整
リモコンのマニュアルを執筆する過程で、

機能の実装を怠っていた物理スイッチ群とバグに対する手当を行った。
先ず、マニュアルを執筆する過程でこの場所にコードの重複を発見した。

物理スイッチには機能のアサイン漏れが多かったが、これは使用時に困惑する原因となるので、ライヴでの使用頻度を考慮して機能を割り当てていく。


長押し系のアサインにも怪し気な箇所があったので、修正を行っている。

本体側は、まず Voice2 の #15 に設定している ChordSequence のアドレス送りスイッチが i2c に未登録だったのでこれを追加、、、

次に、効きが極端に悪化していた WaveShaper の係数を修正している。

ついでに、紛らわしい命名を行っていたレジスタ群の名称を変更しつつ、遊んでいた Env1 の出力を VCF 専用に割振った他、CombFilter 系のモジュレータに直結していた Env2 にフィルターを挿入した。

モジュレータの調整は理屈で行うことが出来ず、出音の反応を聞きながら試行錯誤を繰り返すことになった。
WaveShaper は、しきい値を超えると波形が反転するという乱暴な機能だが、

フィルターを通すことで破綻が無くなる。
機能の実装を怠っていた物理スイッチ群とバグに対する手当を行った。
先ず、マニュアルを執筆する過程でこの場所にコードの重複を発見した。
物理スイッチには機能のアサイン漏れが多かったが、これは使用時に困惑する原因となるので、ライヴでの使用頻度を考慮して機能を割り当てていく。
長押し系のアサインにも怪し気な箇所があったので、修正を行っている。
本体側は、まず Voice2 の #15 に設定している ChordSequence のアドレス送りスイッチが i2c に未登録だったのでこれを追加、、、
次に、効きが極端に悪化していた WaveShaper の係数を修正している。
ついでに、紛らわしい命名を行っていたレジスタ群の名称を変更しつつ、遊んでいた Env1 の出力を VCF 専用に割振った他、CombFilter 系のモジュレータに直結していた Env2 にフィルターを挿入した。
モジュレータの調整は理屈で行うことが出来ず、出音の反応を聞きながら試行錯誤を繰り返すことになった。
WaveShaper は、しきい値を超えると波形が反転するという乱暴な機能だが、
フィルターを通すことで破綻が無くなる。
posted by Yasuski at 21:18| LaVoixski
2025年11月26日
LaVoixski@Ritardandoの開始点をVolumeLevelから設定する
Ritardandoを開始するポイントをレジスタに登録する機能は既に実装済みではあったが、

より容易に直感的な操作でそれが行えるようにVolumeLevelを直接キャプチャするスイッチ&リモコンの設定を追加した。
従来は、起動最低値 3300 を境目に、ロータリーエンコーダ(他のレジスタとデータを共用)の操作によって Ritardando の開始点を設定していたのが、今回行った改訂によりリモコン

及びトップスイッチ左のダブルクリックで起点を登録した時点で

Ritardando の起動準備ができる = 任意に設定した音量から、Ritardando の操作が可能になった。
Ritardando の設定値は、トップスイッチ左の長押しで 3300 の初期値にリセットされる。
追記:
Seq08のTempoレジスタのメモリ回路に記述をミスったバグを発見したので、これに対処した。
同様に、ロータリーエンコーダの操作時にSequencerのTempo設定レジスタ周りに認められたデータの極性反転に追従できない不具合を解消した。
より容易に直感的な操作でそれが行えるようにVolumeLevelを直接キャプチャするスイッチ&リモコンの設定を追加した。
従来は、起動最低値 3300 を境目に、ロータリーエンコーダ(他のレジスタとデータを共用)の操作によって Ritardando の開始点を設定していたのが、今回行った改訂によりリモコン
及びトップスイッチ左のダブルクリックで起点を登録した時点で
Ritardando の起動準備ができる = 任意に設定した音量から、Ritardando の操作が可能になった。
Ritardando の設定値は、トップスイッチ左の長押しで 3300 の初期値にリセットされる。
追記:
Seq08のTempoレジスタのメモリ回路に記述をミスったバグを発見したので、これに対処した。
同様に、ロータリーエンコーダの操作時にSequencerのTempo設定レジスタ周りに認められたデータの極性反転に追従できない不具合を解消した。
posted by Yasuski at 16:43| LaVoixski
LaVoixski@TopSwitchにmode4準拠の機能切換機構を組み込む
TopSwitch 周りに設定した機能の切換を mode4 に配したパラメータに準拠する形に整理した。
この手当を行った結果、mode4 = 5 を選択した時に、Ritardando が開始するポイントを Volume Level のキャプチャで設定することが可能になった。

リモコン受け側では、受信したフラグの状態変化に反応してキャプチャを行う仕様とした。

こちらは送信側のコード。

スイッチに配分する機能を切り分けた結果、Single / Double Click の選択肢が広がって、アクションに無理がある Triple Click の使用を制限することが出来た。
この手当を行った結果、mode4 = 5 を選択した時に、Ritardando が開始するポイントを Volume Level のキャプチャで設定することが可能になった。
リモコン受け側では、受信したフラグの状態変化に反応してキャプチャを行う仕様とした。
こちらは送信側のコード。
スイッチに配分する機能を切り分けた結果、Single / Double Click の選択肢が広がって、アクションに無理がある Triple Click の使用を制限することが出来た。
posted by Yasuski at 01:28| LaVoixski
2025年11月23日
LaVoixski@EnvelopeFollowerの信号ラインにスイッチを追加する
忘却の彼方にあった EnvelopeFollower の存在を思い出し、改めて モジュレータにエントリイを行うスイッチを組み込むことにした。
Env のエントリイ=アクティベーションは、トップスイッチ中央で行うが、

スイッチのアサインに悩んでいる際に、トップスイッチの機能を mode4 によって切換えることを思いついたので、スイッチ類の配置を今一度考え直すことになった。

Envelope 出力は uint16_t なので、EG (float) との乗り換えを行う場合にデータ型を一致させなければならない。 現状はフィルター周りの制御を uint16_t で行っているので、実験段階では EG 出力の float 型を uint 型に近い形に整形していたが、

度重なるデータ型の変換は無駄な作業の繰り返しなので、最終的にはフィルター周りの計算を float 型に置換するところに落ち着いた。


接続を確認する表示機構は、シンプルに UpperEncoder の LED を選んだ。

まだ操作がこなれていないが、EF を EG と絡めて運用する様子を記録した。
EF を切換えるのではなく「エントリイ」させるところがミソで、モジュレーターの位階として「より上位の存在」に設定された EG は、LFO を含めた制御信号全体のレベル管理を統括している。

LFO は用法上常時繋ぎっぱなしの設定となっているが、EG と機能の性格が近い EnvelopeFollwer は、その扱いが難しい。
エンヴェロープを操作するモジュレータが "EG Only" となった場合、SustainLevel の設定値は直接的に LFO の Depth に影響する。 加算の結果 base value を底上げする EF のエントリーによって SustainLevel の影響がマイルドになるが、トレードオフとしてモジュレータの効きが悪くなる。
追記:
EG と ENV の接続状態を microSD に記憶する機能を実装した。
まず、EG のパラメータは VoiceMode の CH 別に設定せず、グローバルコントローラとした。

ただし、EnvelopeFollwer の接続は VoiceMode 毎にレジスタをリザーヴしている。

SceneMemory 用のバッファを確保。

checkParameter への登録を忘れると、レジスタが反応しなくなる。

トップスイッチ側に条件分岐を設定して、VoiceMode 毎にスイッチをアサインした。

リモコンからの信号を受ける i2c の受信 CH の設定を忘れてはいけない。
ADSR は個別のアドレスで通信を行う。

リモコン側で操作する EnvelopeFollwer の接続スイッチは、グローバルコントローラとした。

追記2:
接続スイッチのメモリ読み出しが行えなかったバグが発覚したが、原因は単純な変数の記述漏れだった、、、。

あと、コード#35 の不調の原因として voiceMap( ) 上に add_val+d と記述された謎のタイプミスを発見、こちらもすぐに解決することができた。 不運にも、+ された "d" が変数として認識されてしまったが故の珍事だった。
追記3:
画面がロックして一切の操作を受け付けない重篤なバグが発覚した。
TopSwitch を操作した時に描画にジャンプする命令がカチ合って、何故か無限ループが発生していたらしく、メイン側からの無駄な描画の命令を減らして対策を講じた。
本来、描画ルーチンは Loop 内で発動させる設計なのだが、今回のようにやってはいけない筈のメインからの指定を見落としているケースがないか、音声処理系のサブルーチンを含めて「不穏な描画系サブルーチン」の介入を調査したところ、該当する箇所は無かった。
リモコンの方は漸く形になってきた感触だが、年内/年始共にライヴに参加する機会は無く、実質的な運用試験は来年春まで行えないことが確定している。
Env のエントリイ=アクティベーションは、トップスイッチ中央で行うが、
スイッチのアサインに悩んでいる際に、トップスイッチの機能を mode4 によって切換えることを思いついたので、スイッチ類の配置を今一度考え直すことになった。
Envelope 出力は uint16_t なので、EG (float) との乗り換えを行う場合にデータ型を一致させなければならない。 現状はフィルター周りの制御を uint16_t で行っているので、実験段階では EG 出力の float 型を uint 型に近い形に整形していたが、
度重なるデータ型の変換は無駄な作業の繰り返しなので、最終的にはフィルター周りの計算を float 型に置換するところに落ち着いた。
接続を確認する表示機構は、シンプルに UpperEncoder の LED を選んだ。
まだ操作がこなれていないが、EF を EG と絡めて運用する様子を記録した。
EF を切換えるのではなく「エントリイ」させるところがミソで、モジュレーターの位階として「より上位の存在」に設定された EG は、LFO を含めた制御信号全体のレベル管理を統括している。
LFO は用法上常時繋ぎっぱなしの設定となっているが、EG と機能の性格が近い EnvelopeFollwer は、その扱いが難しい。
エンヴェロープを操作するモジュレータが "EG Only" となった場合、SustainLevel の設定値は直接的に LFO の Depth に影響する。 加算の結果 base value を底上げする EF のエントリーによって SustainLevel の影響がマイルドになるが、トレードオフとしてモジュレータの効きが悪くなる。
追記:
EG と ENV の接続状態を microSD に記憶する機能を実装した。
まず、EG のパラメータは VoiceMode の CH 別に設定せず、グローバルコントローラとした。
ただし、EnvelopeFollwer の接続は VoiceMode 毎にレジスタをリザーヴしている。
SceneMemory 用のバッファを確保。
checkParameter への登録を忘れると、レジスタが反応しなくなる。
トップスイッチ側に条件分岐を設定して、VoiceMode 毎にスイッチをアサインした。
リモコンからの信号を受ける i2c の受信 CH の設定を忘れてはいけない。
ADSR は個別のアドレスで通信を行う。
リモコン側で操作する EnvelopeFollwer の接続スイッチは、グローバルコントローラとした。
追記2:
接続スイッチのメモリ読み出しが行えなかったバグが発覚したが、原因は単純な変数の記述漏れだった、、、。
あと、コード#35 の不調の原因として voiceMap( ) 上に add_val+d と記述された謎のタイプミスを発見、こちらもすぐに解決することができた。 不運にも、+ された "d" が変数として認識されてしまったが故の珍事だった。
追記3:
画面がロックして一切の操作を受け付けない重篤なバグが発覚した。
TopSwitch を操作した時に描画にジャンプする命令がカチ合って、何故か無限ループが発生していたらしく、メイン側からの無駄な描画の命令を減らして対策を講じた。
本来、描画ルーチンは Loop 内で発動させる設計なのだが、今回のようにやってはいけない筈のメインからの指定を見落としているケースがないか、音声処理系のサブルーチンを含めて「不穏な描画系サブルーチン」の介入を調査したところ、該当する箇所は無かった。
リモコンの方は漸く形になってきた感触だが、年内/年始共にライヴに参加する機会は無く、実質的な運用試験は来年春まで行えないことが確定している。
posted by Yasuski at 16:59| LaVoixski
2025年11月22日
LaVoixski@ADSRの導入にトライする
今回行う作業は、Deepseek に以前組み込んだ LFO に準じた構造の EnvelopeGenerator の生成を依頼することから始めた。 制御系信号のハンドリングに関しては LFO の製作でハードルを超えた感があり、EG はその応用編となる。
パラメータの構成はシンプルな ADSR とした。 後々、GateDelay を組み込んでもよいが、取り敢えずはまともに動く EG の導入を目指す。
Deepseek とのやり取りはほんの数分で終わり、あとは自力でシステムに EG を導入するだけとなったが、その作業は想像していたよりも厳しいものだった。
パラメータの増設それ自体は、既存のシステムを参考にすれば良いのだが、最大の問題はロータリーエンコーダで構成された巨大な制御系への組み込みだ。 頁の配分は CombFilter の直後、ArpSpd との間に行った。 導入を行う前に、Sequencer の Tempo 設定頁を ArpSpd と統合し、

一段回深い階層に Sequencer で取り扱う Arpeggiator の Spd 設定パラメータを移設した。

階層の切り換えは、TopSwitch 右のシングルクリックに配分した。 同じスイッチに配分している事故が起きやすい LoopRec は、mode4 == 4 / PlaybackMode のみで発動するように制限を掛けた。

これで空き番地 #10 番を確保出来たので、この場所に ADSR を設定する EG 用の頁を組んでいく。
EG の構造は、LFO のそれを踏襲しているので、、、

LFO を導入した際の経験を活かすことが出来る。
EG は主にフィルターの制御に使用する前提で、回路を組んでいく。

問題となったのはロータリーエンコーダの構成で、こちらは CombFilter のそれを踏襲しているのだが、この時点で「掛かりの深さ」等のチューニングを行う余裕は無く、「まずはとにかく動けばよい」ということで、動作の確認を行う GUI の設定を詰めることにした。GUI の構造と制御信号を処理する回路を近似させれば、GUI の動きが表層的には動作の確認となる筈だ。

EG は2系統で構成されているので、これを切換えるパラメータが必要だ。 今回は、これをトップスイッチ右に配分した。 先の Sequencer 用の ArpSpd パラメータの呼び出しも、同じスイッチに配分している。
VoiceMode 7 個分の(ADSR2 系統 = 8 × 7 個と結構な数になる)パラメータを追加するのは諦めて、システム全体を統合する8個分のレジスタを先ず実装する。
レジスタの切り替えを行うのは UpperEncoder で、コードに内包される mode2 切り換え機構の上位に ADSR のレジスタを選択する条件分岐を設定している。

EG は実用性の検証が未了なので、ひとまずはグローバルコントローラに設定している。 今後用法が確立して EG の機能を使いこなせることが判った時点で、再度全 VoiceMode 分の導入を検討する。
EG の起動は、Volume に設けた閾値を判定するフラグによって行われる。
EG1 のトリガは固定された閾値で、

EG2 のトリガはレジスタによって設定された閾値で起動される。

EG の設定は、Main プログラム側の Loop 内からブリッジ関数を呼び出して行う。

受け渡されたレジスタの値は、EG のサブルーチンで処理される。

この辺りの処理の流れは LFO と同じなので、新たなモジュレータとして組み込むのに最適な場所を考慮するだけでよかった。
LED と LCD の色味の調整を行って、、、


動作を確認したが、ADSR の選択には int を使っていた所為で発生した「周期的に発現するロータリーエンコーダの無反応」というバグに困惑することになった。 基本、スイッチ系の素子は uint で組むべきということか。
VCF 的な用法は可能だが、フィルターの効き自体がまろやかなので、鮮烈な効果は薄い。
残る作業は、現時点では暫定的に readBuffer(); 内で数値を書き込んでいる新規に登録した ADSR のレジスタ群を microSD に登録する機能の実装となる。
追記:
実験の結果、Decay のリリース時にノイズが発生していたので、EG の出力値をメイン側でさらに平滑化することにした。

ノイズを除去しつつ、動作に違和感を感じない設定値はこのあたりになるだろうか。
これからリモコン側に ADSR のパラメータを組み込んでいくが、ADSR 分のパラメータをリザーヴするには階層を深くせざるを得ず、予想していたよりもコーディングに手間が掛かるかもしれない。 特に、LFO のDepth との相関性が深い Sustain の扱いを検討することになるだろう。
パラメータの構成はシンプルな ADSR とした。 後々、GateDelay を組み込んでもよいが、取り敢えずはまともに動く EG の導入を目指す。
Deepseek とのやり取りはほんの数分で終わり、あとは自力でシステムに EG を導入するだけとなったが、その作業は想像していたよりも厳しいものだった。
パラメータの増設それ自体は、既存のシステムを参考にすれば良いのだが、最大の問題はロータリーエンコーダで構成された巨大な制御系への組み込みだ。 頁の配分は CombFilter の直後、ArpSpd との間に行った。 導入を行う前に、Sequencer の Tempo 設定頁を ArpSpd と統合し、
一段回深い階層に Sequencer で取り扱う Arpeggiator の Spd 設定パラメータを移設した。
階層の切り換えは、TopSwitch 右のシングルクリックに配分した。 同じスイッチに配分している事故が起きやすい LoopRec は、mode4 == 4 / PlaybackMode のみで発動するように制限を掛けた。
これで空き番地 #10 番を確保出来たので、この場所に ADSR を設定する EG 用の頁を組んでいく。
EG の構造は、LFO のそれを踏襲しているので、、、
LFO を導入した際の経験を活かすことが出来る。
EG は主にフィルターの制御に使用する前提で、回路を組んでいく。
問題となったのはロータリーエンコーダの構成で、こちらは CombFilter のそれを踏襲しているのだが、この時点で「掛かりの深さ」等のチューニングを行う余裕は無く、「まずはとにかく動けばよい」ということで、動作の確認を行う GUI の設定を詰めることにした。GUI の構造と制御信号を処理する回路を近似させれば、GUI の動きが表層的には動作の確認となる筈だ。
EG は2系統で構成されているので、これを切換えるパラメータが必要だ。 今回は、これをトップスイッチ右に配分した。 先の Sequencer 用の ArpSpd パラメータの呼び出しも、同じスイッチに配分している。
VoiceMode 7 個分の(ADSR2 系統 = 8 × 7 個と結構な数になる)パラメータを追加するのは諦めて、システム全体を統合する8個分のレジスタを先ず実装する。
レジスタの切り替えを行うのは UpperEncoder で、コードに内包される mode2 切り換え機構の上位に ADSR のレジスタを選択する条件分岐を設定している。
EG は実用性の検証が未了なので、ひとまずはグローバルコントローラに設定している。 今後用法が確立して EG の機能を使いこなせることが判った時点で、再度全 VoiceMode 分の導入を検討する。
EG の起動は、Volume に設けた閾値を判定するフラグによって行われる。
EG1 のトリガは固定された閾値で、
EG2 のトリガはレジスタによって設定された閾値で起動される。
EG の設定は、Main プログラム側の Loop 内からブリッジ関数を呼び出して行う。
受け渡されたレジスタの値は、EG のサブルーチンで処理される。
この辺りの処理の流れは LFO と同じなので、新たなモジュレータとして組み込むのに最適な場所を考慮するだけでよかった。
LED と LCD の色味の調整を行って、、、
動作を確認したが、ADSR の選択には int を使っていた所為で発生した「周期的に発現するロータリーエンコーダの無反応」というバグに困惑することになった。 基本、スイッチ系の素子は uint で組むべきということか。
VCF 的な用法は可能だが、フィルターの効き自体がまろやかなので、鮮烈な効果は薄い。
残る作業は、現時点では暫定的に readBuffer(); 内で数値を書き込んでいる新規に登録した ADSR のレジスタ群を microSD に登録する機能の実装となる。
追記:
実験の結果、Decay のリリース時にノイズが発生していたので、EG の出力値をメイン側でさらに平滑化することにした。
ノイズを除去しつつ、動作に違和感を感じない設定値はこのあたりになるだろうか。
これからリモコン側に ADSR のパラメータを組み込んでいくが、ADSR 分のパラメータをリザーヴするには階層を深くせざるを得ず、予想していたよりもコーディングに手間が掛かるかもしれない。 特に、LFO のDepth との相関性が深い Sustain の扱いを検討することになるだろう。
posted by Yasuski at 04:43| LaVoixski
2025年11月20日
LaVoixski@フィルタ周りにバグを発見する
リモコンと楽器の整合性を突き詰めていったら、結果として本体側の設定ミスが見つかるケースが相次いでいる。
今日は、フィルターを切換えるスイッチの不整合を発見、そりゃいくらレベルを調整しても結果が出ないのは当前なのだった、、、。

この失敗が発生した原因は「九龍城的に建増しを繰り返したバラック状の回路構成」にあって、その都度行われるべき制御ロジックの統合に失敗した結果、スイッチによる選択対象が場所によって反転している状態に気付けなかった。 リモコンによる統合制御を導入する過程で、本体側の制御ロジックの不整合が表面化するケースは今後も続く公算が高い。
さて、そのリモコンの開発の状況だが、気になっていた「空き地」が埋まってひとまずは完成といったところか。

EMA の値の切り換えや、スレッショルド値の調整や、出力をアクティヴェイトするスイッチなど、IMU の出力調整を行う機能を暫定的に設定しているが、

楽器側の対応は未了。 というか、使い途を思い付けない。

VoiceMode の切替時に望まないコードの音が出る「仕様」は運用を重ねるにつれて使い辛く感じてきたので、目的のコードを指定したあとに「タッチパネルを長押し」した段階で結果が反映されるように、リモコンの構造を変更した。

タッチパネルの長押しに関しては反応がイマイチなので、この機能を機械スイッチに割り振る事も考えている。
楽器本体の側では、対応可能なパラメータを増やした。


これで表に出ているパラメータはほぼ網羅出来た筈。
追記:
Voicingの決定を機械スイッチに振り替えた。

なんやかんやで、物理は安心出来る。
追記2:
リモコンの長押し設定を整理した。
基本は、パラメータのリセットを行う機能を持たせているが、

VoiceModeの選択時のみChromaticModeの起動を行う。


機械スイッチも同様にパラメータの切り替えを行ってもよいが、操作の混乱の原因ともなるので、程々にしなければならない。
追記3:
リモコンがレジスタの上書きを行った後に、SceneMemoryで状態が復帰できないバグを発見した。
原因は、新規に増設すべきだったレジスタをケチったという間抜けな理由だったので、

状態保存が行えるようにレジスタを追加した結果、バグは解消された。
今日は、フィルターを切換えるスイッチの不整合を発見、そりゃいくらレベルを調整しても結果が出ないのは当前なのだった、、、。
この失敗が発生した原因は「九龍城的に建増しを繰り返したバラック状の回路構成」にあって、その都度行われるべき制御ロジックの統合に失敗した結果、スイッチによる選択対象が場所によって反転している状態に気付けなかった。 リモコンによる統合制御を導入する過程で、本体側の制御ロジックの不整合が表面化するケースは今後も続く公算が高い。
さて、そのリモコンの開発の状況だが、気になっていた「空き地」が埋まってひとまずは完成といったところか。
EMA の値の切り換えや、スレッショルド値の調整や、出力をアクティヴェイトするスイッチなど、IMU の出力調整を行う機能を暫定的に設定しているが、
楽器側の対応は未了。 というか、使い途を思い付けない。
VoiceMode の切替時に望まないコードの音が出る「仕様」は運用を重ねるにつれて使い辛く感じてきたので、目的のコードを指定したあとに「タッチパネルを長押し」した段階で結果が反映されるように、リモコンの構造を変更した。
タッチパネルの長押しに関しては反応がイマイチなので、この機能を機械スイッチに割り振る事も考えている。
楽器本体の側では、対応可能なパラメータを増やした。
これで表に出ているパラメータはほぼ網羅出来た筈。
追記:
Voicingの決定を機械スイッチに振り替えた。
なんやかんやで、物理は安心出来る。
追記2:
リモコンの長押し設定を整理した。
基本は、パラメータのリセットを行う機能を持たせているが、
VoiceModeの選択時のみChromaticModeの起動を行う。
機械スイッチも同様にパラメータの切り替えを行ってもよいが、操作の混乱の原因ともなるので、程々にしなければならない。
追記3:
リモコンがレジスタの上書きを行った後に、SceneMemoryで状態が復帰できないバグを発見した。
原因は、新規に増設すべきだったレジスタをケチったという間抜けな理由だったので、
状態保存が行えるようにレジスタを追加した結果、バグは解消された。
posted by Yasuski at 02:44| LaVoixski
2025年11月17日
LaVoixski@新設したスイッチ類をSceneMemoryに登録する
新設した LPFmod = combFilter の前段に配置した LPF のアクティベーション と LPFの切り換えを行うスイッチのレジスタを SceneMemory に登録した。
何れも、音色に対する影響が大きなパラメータが故に、楽器の立ち上げ時に設定が記憶されていない状態に不便を感じていた。
今回、操作系やファイル記録システムに大きな改変を行う手間を掛けずに増設したパラメータを記録する手法として、bitSet/Clear/Read を使って関連するパラメータの MSB に状態を反映する方法を考えついた。
セレクタ・スイッチの値で、フラグとなる MSB を操作している。

読み出し側は、逆の手順で MSB の状態を拾えばよいのだが、、、

既存のパラメータの数値には MSB の状態が影響しないように、上位ビットにマスクを掛ける必要がある。

レジスタの仕様によって、マスクを掛ける場所が変わってくる。

既存のパラメータとレジスタを共有した影響で「ファイルの可読性」が犠牲になってしまうが、この項目に直接記述を行う可能性は低く、実用上の問題は殆どないだろう。
追記:
i2cのアドレスに増設したレジスタを追加で登録した。

本体側の仕様変更に伴って、リモコン側のデザインにも修正を行っている。
何れも、音色に対する影響が大きなパラメータが故に、楽器の立ち上げ時に設定が記憶されていない状態に不便を感じていた。
今回、操作系やファイル記録システムに大きな改変を行う手間を掛けずに増設したパラメータを記録する手法として、bitSet/Clear/Read を使って関連するパラメータの MSB に状態を反映する方法を考えついた。
セレクタ・スイッチの値で、フラグとなる MSB を操作している。
読み出し側は、逆の手順で MSB の状態を拾えばよいのだが、、、
既存のパラメータの数値には MSB の状態が影響しないように、上位ビットにマスクを掛ける必要がある。
レジスタの仕様によって、マスクを掛ける場所が変わってくる。
既存のパラメータとレジスタを共有した影響で「ファイルの可読性」が犠牲になってしまうが、この項目に直接記述を行う可能性は低く、実用上の問題は殆どないだろう。
追記:
i2cのアドレスに増設したレジスタを追加で登録した。
本体側の仕様変更に伴って、リモコン側のデザインにも修正を行っている。
posted by Yasuski at 21:42| LaVoixski
LaVoixski@Looper使用時に発生するノイズへの対処について
今日は、ChromaticMode と Looper を併用した場合に、処理能力の限界から出力にノイズが混入する事案に対する手当を行っていた。
例の如く、コードを精査する過程で別のバグ( combFilter 周辺の信号ラインの混乱)を発見したので、まずはこれに対処することになった。

これは、バグというよりも構造(関数のネーミング)の問題で、ノイズに対処する過程で行っていた試行錯誤の後遺症と思われる。 最初はネーミングの混乱に端を発していたのが、何時の間にかそれが忘れ去られて、砂上の楼閣を組んでいった結果の大混乱で、前提を間違えた上で現物合わせを繰り返したことが、更なる混乱を招いていたという間抜けなケースであった。
このような凡ミスへの対処は愚直に行うのが正解で、信号ラインを素直な形に組み直し接続を整理して、取敢えずこの問題は解決できた。


さて、Looper 由来と思われるノイズの発生は以前から認識されていた現象で、combFilter の配線が混乱した件は「Looper のノイズ対策への一環」としての試行錯誤の産物なのだった。 現物合わせで対策を行う時に発生する問題は、経験上記述ミスや配置のミスが多く、今回行った改修ではミスを事前に防ぐ目論見として「処理過程のサブルーチン化」を進めていった。

これは、Deepseek 的価値観からすると「唾棄すべき外法」と思われるが、プログラムの構造を視覚的に把握出来るこの方法は侮り難く、特に配置換えパズルを行う際に混乱が生じない点が大きな長所である。



各処理過程をサブルーチン化する過程で、可能な限り「処理の単純化」を行っているが、Looper の重い処理の対価としては焼け石に水で、例えば描画を停止する手法は思った程に効果はなかった。

効果があったのは処理ルーチンの洗い直しで、処理を行う時系列を整理した結果、Looper の配置はL/Rの処理を切換えるオーディオクロックのアップ/ダウン・エッジの近辺、「2番目のタスク」に行うのが正解だったようだ。


改修後にノイズの発生は極力抑えられ、ChromaticMode を稼働させながら Looper の録音/再生を行うことが出来るようになった。
流石に 5voiceMode で複雑なヴォイシングの切り替えを行うタスクと ChromaticMode の並立は無理だったようだが、以前は 5voiceMode 単体の使用で発生していたノイズが抑えられているので、ここら辺りを取敢えずの妥協点とする。
ちなみに、MCU のクロックアップが簡単&最良の選択肢であったが、

MCU の個体差によって LCD の描画が行えなくなってしまうようで、この対処法には「MCU の選別」といった別のハードルの存在が明らかになった。 クロックアップには諸々の弊害が発現してしまう傾向があるので、これは最後の手段と認識すべきだろう。
追記:
ディレイラインの構成が変った影響で、レベルの設定やモジュレータの配置が怪しくなっていた箇所の修正を行った。

Looperの稼働状態。
MCUの処理能力を保全するために、録音が開始されると同時に描画を停止している。
メモリの管理状態が怪しかったときは再生時に稼働するはずのサンプルのフェードが上手く行っていなかったが、メモリの残量に余裕が出来てからは正常に動作しているようだ。
追記2:
Looper の起動に反応して波形表示がいきなり停止する仕様に戸惑うことが多かった(入力のレベル管理が出来なくなる)ので、表示する内容をダウングレードしてMCUの負荷を軽くする仕様に設計を変更した。

モジュレータの「効き」は入力信号のレベルに左右されるが、これは歪の発生と表裏一体で、演奏中に微妙なレベルの推移を監視する必要がある。 Looperを起動した場合には、さらにLooperと演奏のレベルのバランスに注視しなければならず、波形の表示は可能な限り行うべきだろう。
追記3:
ノイズサプレッションの目的で DAC の Mute 端子と楽器側の VoiceMode 切り換えスイッチを連携していたのだが、どうやらこれが逆効果だったようなので、関係を解消した。

それと、Looper の停止スイッチに、ソフトミュート機能を追加している。

こちらの効果も「それなりな感」が強いので、LFO の導入に準ずる形になるが本格的な EG を組み込むべきかもしれない。
追記4:
RAM1の free for local variables に余裕があると、不調だったLooper に仕込んだ自動 Fade In/Out 機能は、、、

設計通りに働いているようだ、、、。

x1/2 再生の場合はフェードを掛けておらず、録音された状態がそのまま再生される。

Loop 再生の記録。 何れの再生モードでも継ぎ目のノイズは認められない。
Loop の先頭は、録音の立ち上がり時にフェードを掛けている。

録音の終了を予測して、ソフトミュートを行っている(つもり)。
例の如く、コードを精査する過程で別のバグ( combFilter 周辺の信号ラインの混乱)を発見したので、まずはこれに対処することになった。
これは、バグというよりも構造(関数のネーミング)の問題で、ノイズに対処する過程で行っていた試行錯誤の後遺症と思われる。 最初はネーミングの混乱に端を発していたのが、何時の間にかそれが忘れ去られて、砂上の楼閣を組んでいった結果の大混乱で、前提を間違えた上で現物合わせを繰り返したことが、更なる混乱を招いていたという間抜けなケースであった。
このような凡ミスへの対処は愚直に行うのが正解で、信号ラインを素直な形に組み直し接続を整理して、取敢えずこの問題は解決できた。
さて、Looper 由来と思われるノイズの発生は以前から認識されていた現象で、combFilter の配線が混乱した件は「Looper のノイズ対策への一環」としての試行錯誤の産物なのだった。 現物合わせで対策を行う時に発生する問題は、経験上記述ミスや配置のミスが多く、今回行った改修ではミスを事前に防ぐ目論見として「処理過程のサブルーチン化」を進めていった。
これは、Deepseek 的価値観からすると「唾棄すべき外法」と思われるが、プログラムの構造を視覚的に把握出来るこの方法は侮り難く、特に配置換えパズルを行う際に混乱が生じない点が大きな長所である。
各処理過程をサブルーチン化する過程で、可能な限り「処理の単純化」を行っているが、Looper の重い処理の対価としては焼け石に水で、例えば描画を停止する手法は思った程に効果はなかった。
効果があったのは処理ルーチンの洗い直しで、処理を行う時系列を整理した結果、Looper の配置はL/Rの処理を切換えるオーディオクロックのアップ/ダウン・エッジの近辺、「2番目のタスク」に行うのが正解だったようだ。
改修後にノイズの発生は極力抑えられ、ChromaticMode を稼働させながら Looper の録音/再生を行うことが出来るようになった。
流石に 5voiceMode で複雑なヴォイシングの切り替えを行うタスクと ChromaticMode の並立は無理だったようだが、以前は 5voiceMode 単体の使用で発生していたノイズが抑えられているので、ここら辺りを取敢えずの妥協点とする。
ちなみに、MCU のクロックアップが簡単&最良の選択肢であったが、
MCU の個体差によって LCD の描画が行えなくなってしまうようで、この対処法には「MCU の選別」といった別のハードルの存在が明らかになった。 クロックアップには諸々の弊害が発現してしまう傾向があるので、これは最後の手段と認識すべきだろう。
追記:
ディレイラインの構成が変った影響で、レベルの設定やモジュレータの配置が怪しくなっていた箇所の修正を行った。
Looperの稼働状態。
MCUの処理能力を保全するために、録音が開始されると同時に描画を停止している。
メモリの管理状態が怪しかったときは再生時に稼働するはずのサンプルのフェードが上手く行っていなかったが、メモリの残量に余裕が出来てからは正常に動作しているようだ。
追記2:
Looper の起動に反応して波形表示がいきなり停止する仕様に戸惑うことが多かった(入力のレベル管理が出来なくなる)ので、表示する内容をダウングレードしてMCUの負荷を軽くする仕様に設計を変更した。
モジュレータの「効き」は入力信号のレベルに左右されるが、これは歪の発生と表裏一体で、演奏中に微妙なレベルの推移を監視する必要がある。 Looperを起動した場合には、さらにLooperと演奏のレベルのバランスに注視しなければならず、波形の表示は可能な限り行うべきだろう。
追記3:
ノイズサプレッションの目的で DAC の Mute 端子と楽器側の VoiceMode 切り換えスイッチを連携していたのだが、どうやらこれが逆効果だったようなので、関係を解消した。
それと、Looper の停止スイッチに、ソフトミュート機能を追加している。
こちらの効果も「それなりな感」が強いので、LFO の導入に準ずる形になるが本格的な EG を組み込むべきかもしれない。
追記4:
RAM1の free for local variables に余裕があると、不調だったLooper に仕込んだ自動 Fade In/Out 機能は、、、
設計通りに働いているようだ、、、。
x1/2 再生の場合はフェードを掛けておらず、録音された状態がそのまま再生される。
Loop 再生の記録。 何れの再生モードでも継ぎ目のノイズは認められない。
Loop の先頭は、録音の立ち上がり時にフェードを掛けている。
録音の終了を予測して、ソフトミュートを行っている(つもり)。
posted by Yasuski at 01:19| LaVoixski
2025年11月15日
LaVoixski@Filterのリプレイスに苦労する
昨日は Deepseek と8時間程スケッチの生成を頑張っていたが、今回は結果を出せなかった。
導入しようと試みたのは BiQuad タイプのデジタルフィルタで、これはとても便利な仕掛けなのだが、どうやっても量子化ノイズ?が出てしまう。

生成してもらったファイルは当初からレンジ外のデータを吐きまくっていて、適正値が得られるようになるまでに数時間が費やされた。

最終的に、なんとか各種フィルタの機能を再現できたものの、チリチリといった風の細かいノイズが音声に乗ってくる。

デバッグ用に動かしていたシリアル通信を切ってもノイズが発生する状況は変わらない。
特にモジュレーターとの相性は最悪で、リアルタイム系の操作をすると途端に“パリパリ“と細かなノイズが発生する。 操作情報のリアルタイム更新はご法度っぽくて、考えていた EMA 系フィルタとのリプレイスは断念することになった。
EMA フィルタは効きが今ひとつで HPF を構成するパートは特に弱かったのだが、LFO の改装を受けて出音の性格があまり好みではない方向に変化してしまった。 今回目論んでいたのは効きの良いフィルタの導入と、EMA 系 HPF のリプレイスだった。 BiQuad フィルタの導入計画が潰えてしまったので、EMA フィルタ周りの構成を今一度考え直さなければならない。
とりあえず、LFP の方に不満はなく、改装の必要を感じているのは HPF を構成するパートだ。 この箇所には以前大きな改装を行っていてその成果が Waveshaper だったのだが、EMA の 段数を増やしたことと、LFO の出力仕様が変わった影響で、出音のニュアンスが悪い方向に変化してしまった。 HPF の方も同様に影響を受けていたので、今回追加した部分を外して従来のシンプルな処理を行う構成に戻すことにした。
処理を戻すついでに HPF の改善を目論んで定数をいじったのものの、最適値がなかなか決まらない。 レベル管理の問題も絡んできた結果、調整に数時間が費やされることになった。
最終的に探しだしたのがこの定数で、、、

HPF の改良を諦めて、効きの良い LPF に実装を変更することになった。
偶然の産物ではあるが、この新しい LPF と S&H 出力の LPF の相性がすこぶる良かったので、設定を保存している。
追記:
S/H のスピードに合わせて LFO/RATEを 設定した場合に他のモードとの齟齬が発生することが判った。

S/H の Rate 設定は、どちらかというと DelayTime や Arpeggiator の Speed との連携が優先されそうなので、S/H の Rate を LFO のパラメータから切り離すことにした。






ついでに、放置していた自動ディレイタイム設定のオーバーフロー対策を行っておいた。

導入しようと試みたのは BiQuad タイプのデジタルフィルタで、これはとても便利な仕掛けなのだが、どうやっても量子化ノイズ?が出てしまう。
生成してもらったファイルは当初からレンジ外のデータを吐きまくっていて、適正値が得られるようになるまでに数時間が費やされた。
最終的に、なんとか各種フィルタの機能を再現できたものの、チリチリといった風の細かいノイズが音声に乗ってくる。
デバッグ用に動かしていたシリアル通信を切ってもノイズが発生する状況は変わらない。
特にモジュレーターとの相性は最悪で、リアルタイム系の操作をすると途端に“パリパリ“と細かなノイズが発生する。 操作情報のリアルタイム更新はご法度っぽくて、考えていた EMA 系フィルタとのリプレイスは断念することになった。
EMA フィルタは効きが今ひとつで HPF を構成するパートは特に弱かったのだが、LFO の改装を受けて出音の性格があまり好みではない方向に変化してしまった。 今回目論んでいたのは効きの良いフィルタの導入と、EMA 系 HPF のリプレイスだった。 BiQuad フィルタの導入計画が潰えてしまったので、EMA フィルタ周りの構成を今一度考え直さなければならない。
とりあえず、LFP の方に不満はなく、改装の必要を感じているのは HPF を構成するパートだ。 この箇所には以前大きな改装を行っていてその成果が Waveshaper だったのだが、EMA の 段数を増やしたことと、LFO の出力仕様が変わった影響で、出音のニュアンスが悪い方向に変化してしまった。 HPF の方も同様に影響を受けていたので、今回追加した部分を外して従来のシンプルな処理を行う構成に戻すことにした。
処理を戻すついでに HPF の改善を目論んで定数をいじったのものの、最適値がなかなか決まらない。 レベル管理の問題も絡んできた結果、調整に数時間が費やされることになった。
最終的に探しだしたのがこの定数で、、、
HPF の改良を諦めて、効きの良い LPF に実装を変更することになった。
偶然の産物ではあるが、この新しい LPF と S&H 出力の LPF の相性がすこぶる良かったので、設定を保存している。
追記:
S/H のスピードに合わせて LFO/RATEを 設定した場合に他のモードとの齟齬が発生することが判った。
S/H の Rate 設定は、どちらかというと DelayTime や Arpeggiator の Speed との連携が優先されそうなので、S/H の Rate を LFO のパラメータから切り離すことにした。
ついでに、放置していた自動ディレイタイム設定のオーバーフロー対策を行っておいた。
posted by Yasuski at 12:23| LaVoixski
2025年11月13日
LaVoixski@LFOの実装を完了する・他
今回こなした一連の作業で結構な量のタスクを消化出来たので、記憶が揮発しないうちに備忘録を記す。
作業の前日に、Deepseek との間で計算によって波形を生成する LFO の製作についての検討を行っていた。
当初、Deepseek の提案で LFO は CombFilter に内装されていたのだが、

「外部に LFO の信号を引き出せないか」と依頼したのが話の発端で、「だったら LFO だけ機能を分離すればよいのでは?」と、こちら側から提案を行い、新たなソフトウェア開発の方針が決まった。
自作した LFO は、Wavetable を参照する一般的な常識からは外れた構造のシステムではあったが、波形を生成するために必要とされる計算の負荷が軽いのが利点だった。

とはいえ、ステップ数 4096 のそれは分解能が低く、不連続なラインを補間しても性能に限界が見られた。特にサイン波状の入力波形との相性が悪く、出力に妙な高調波が発生していた。
これは、以前 CombFilter の出力波形を撮影した画像だが、「点線状の不連続な波形」を確認できる。

LFO の出力波形に補間を掛ける処理工程を考えた場合、MCU の計算による波形の生成と負荷の差はほぼ無くなりそうなので、LFO をリプレイスした方が良いのではないか?と、システム構成の変更を考えたのは半年程前で、当時も Deepseek に相談を持ちかけたのだが、こちらの設問が悪かった所為もあって有意義な回答は得られなかった。
従って、今回の依頼では前回の反省から事前のリサーチを徹底し、予めオリジナルの回路構成を例示するのと同時に、扱っている変数の詳細をリストアップした。 作業を開始した当初、Deepseek はオリジナルの回路構成を尊重しようと試みたが、そこは早めに見切りを付けるように提案して、常識的なソフトウエア生成の作法で回路を構成してもらうように開発の方向性を誘導した。
列挙されたパラメータは、外部からの入力とリンクされる。

Deepseek が行うコーディングの特徴は、可能な限り短い記述で、しかもファイルを一纏めにしようと頑張るところにあるが、其処にメインテナンス性の確保や可読性を重視する観点はあまり持ち合わせていないように思える。 今回行った作業でもパラメータの一括に拘る傾向が見られ、その都度修正を提案することになった。
画像は波形を生成するパートで、6波の生成に対応している。

あと、スレッド内に於けるコーディングの継承性に欠ける傾向は治っておらず、それを阻止する方策としてコードの部分生成を避けるようにお願いをしていた。

こちら側のミスとしては、変数のデータ型の申し渡しを失念していたことで、一般的な概念から外れたプログラムの一部分を見せただけで、AI に細部を判断させたのは流石に酷であった。

変数のデータ型をすり合わせた後に問題となったのは波形のエッジを丸める Waveshaper の実装で、これが何故か目論見通りに処理を行った信号が出力されない状態が続いた。EMA とされる出力がそれで、固定値から一切の変動が認められない。

コードのデバッグを行うには USB シリアルに出力された情報を読む必要があるのだが、PC 側の接続状態(物理)が安定しない。 そのうえ JAVA の(ヴァージョンの)影響もあるのか、IDE の状態もかなり怪しくなっている。 なので、出来るだけ GFX を使って LCD に出力を試みるも、LFO はデータの送信量が多いためにそれにも限界がある。 仕方なく、調子の悪いシリアルポートを騙し騙し使って観察を続けたが、どうやっても出力が得られない Waveshape を諦めて、最終的に RAW データを読むことに方針を転換することになった。
後日、Waveshaper によるフィルタリングに関しては、なんと Deepseek が勘違いで効果のないコードを生成していたことが判明した。 この例は正しく書かれた EMA フィルタの記述だが、

該当する箇所に実績のあるコードを実装することで問題は解決した。
当初は外部操作が可能なパラメータとして扱っていた Waveshaper の設定値だが、とりあえずは実験を行って最適と判断した数値に固定することになった。 後々の使い勝手を考えた場合、CPP 側に記述を行うのは不便そうなので、Main 側にも追加でフィルタを増設して細かな調整はそちらで行うことにしているが、ModSpeed と関連付けて自動で値を変動させるのが理想ではある。
コードを組み込む過程で新たに問題となったのは、LFO の出力値の仕様がオリジナルとは異なっている点で、これには実際に運用を重ねながら最適値を探っていくことになった。
また、オリジナル回路の LFO1 と LFO2 では Speed の領域設定が2倍程違うので、それに合わせて生成されたコードの LFO2 側に修正を行っている。

この映像を参照すると判るが、元来装備していた LFO に生じていた階段状の段差=不連続面が解消された結果、劇的に音質が向上している。 視覚的には、描かれる波形もスムーズになったことが判る。
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
CombFilter を実装する過程で、諸々の問題が発覚したので、個別に対処を行うことになった。
まず、リモコン使用時にどうやっても特定のパラメータにアクセスできない問題があり、その症状から判断するに、どうやら同じデータを定常的に吐いている箇所が存在するようだ。 具体的には 2VoicMode で Arpeggiator の Note を選択するパラメータに異常が認められたのだが、

描画のトリガーとなるレジスタを虱潰しに探しても原因は見つからず、怪しい箇所を見落としていないか幾度も確認を繰り返したところ、意外なところにバグが潜んでいた。

これは、かなり初歩的な書き漏らしで、この状態ではロータリーエンコーダの出力データが確定せずに、終始同じ値を繰り返し吐き続けることになる。 ヒントは描画の異様なチラツキにあったのだが、もしかするとプログラムの開発を始めた極初期に発生していた書き漏らしだった可能性が高く、リモコンを導入することがなければ本件も認識出来ずに放置されていた不具合であった。
Arpeggiator には他にも LCD の導入を行う前から認識していた不具合があるのだが、こちらは用法上あまり不便を感じなかったため、そのまま放置していた案件である。
今回この問題に手を入れたのは、sdFat の読み込みルーティンを改装した影響で、Step 数が正確に読めなくなったバグの解消に端を発する。 バグの解消自体はとりたてて難しい問題ではなく、、、

予め与えていたオフセット値を解消することで容易に対応することが出来た。
その過程で気になったのが Arpeggiator の読み出しパターンの Up/Down に関する不具合で、不連続な状態でフレーズが再生されてしまう。 要はフレーズを構成する音符の上下に休符が入ってしまう症状で、これは反転時に与えるオフセット値を間違えていたために発生した現象であった。

こちらも、正確なオフセット値を与えることで問題は解決できたのだが、ランダム音階再生時に生じてしまう無音の処理は、それによって生成されるグルーヴ感が好みに合っていたので、敢えて残すことにした。
10月初頭から立て続けに行ってきた改装作業だが、残るはリモコンへのパラメータの実装で、これを完了すればしばらく落ち着くことになりそうだ。
作業の前日に、Deepseek との間で計算によって波形を生成する LFO の製作についての検討を行っていた。
当初、Deepseek の提案で LFO は CombFilter に内装されていたのだが、
「外部に LFO の信号を引き出せないか」と依頼したのが話の発端で、「だったら LFO だけ機能を分離すればよいのでは?」と、こちら側から提案を行い、新たなソフトウェア開発の方針が決まった。
自作した LFO は、Wavetable を参照する一般的な常識からは外れた構造のシステムではあったが、波形を生成するために必要とされる計算の負荷が軽いのが利点だった。
とはいえ、ステップ数 4096 のそれは分解能が低く、不連続なラインを補間しても性能に限界が見られた。特にサイン波状の入力波形との相性が悪く、出力に妙な高調波が発生していた。
これは、以前 CombFilter の出力波形を撮影した画像だが、「点線状の不連続な波形」を確認できる。
LFO の出力波形に補間を掛ける処理工程を考えた場合、MCU の計算による波形の生成と負荷の差はほぼ無くなりそうなので、LFO をリプレイスした方が良いのではないか?と、システム構成の変更を考えたのは半年程前で、当時も Deepseek に相談を持ちかけたのだが、こちらの設問が悪かった所為もあって有意義な回答は得られなかった。
従って、今回の依頼では前回の反省から事前のリサーチを徹底し、予めオリジナルの回路構成を例示するのと同時に、扱っている変数の詳細をリストアップした。 作業を開始した当初、Deepseek はオリジナルの回路構成を尊重しようと試みたが、そこは早めに見切りを付けるように提案して、常識的なソフトウエア生成の作法で回路を構成してもらうように開発の方向性を誘導した。
列挙されたパラメータは、外部からの入力とリンクされる。
Deepseek が行うコーディングの特徴は、可能な限り短い記述で、しかもファイルを一纏めにしようと頑張るところにあるが、其処にメインテナンス性の確保や可読性を重視する観点はあまり持ち合わせていないように思える。 今回行った作業でもパラメータの一括に拘る傾向が見られ、その都度修正を提案することになった。
画像は波形を生成するパートで、6波の生成に対応している。
あと、スレッド内に於けるコーディングの継承性に欠ける傾向は治っておらず、それを阻止する方策としてコードの部分生成を避けるようにお願いをしていた。
こちら側のミスとしては、変数のデータ型の申し渡しを失念していたことで、一般的な概念から外れたプログラムの一部分を見せただけで、AI に細部を判断させたのは流石に酷であった。
変数のデータ型をすり合わせた後に問題となったのは波形のエッジを丸める Waveshaper の実装で、これが何故か目論見通りに処理を行った信号が出力されない状態が続いた。EMA とされる出力がそれで、固定値から一切の変動が認められない。
コードのデバッグを行うには USB シリアルに出力された情報を読む必要があるのだが、PC 側の接続状態(物理)が安定しない。 そのうえ JAVA の(ヴァージョンの)影響もあるのか、IDE の状態もかなり怪しくなっている。 なので、出来るだけ GFX を使って LCD に出力を試みるも、LFO はデータの送信量が多いためにそれにも限界がある。 仕方なく、調子の悪いシリアルポートを騙し騙し使って観察を続けたが、どうやっても出力が得られない Waveshape を諦めて、最終的に RAW データを読むことに方針を転換することになった。
後日、Waveshaper によるフィルタリングに関しては、なんと Deepseek が勘違いで効果のないコードを生成していたことが判明した。 この例は正しく書かれた EMA フィルタの記述だが、
該当する箇所に実績のあるコードを実装することで問題は解決した。
当初は外部操作が可能なパラメータとして扱っていた Waveshaper の設定値だが、とりあえずは実験を行って最適と判断した数値に固定することになった。 後々の使い勝手を考えた場合、CPP 側に記述を行うのは不便そうなので、Main 側にも追加でフィルタを増設して細かな調整はそちらで行うことにしているが、ModSpeed と関連付けて自動で値を変動させるのが理想ではある。
コードを組み込む過程で新たに問題となったのは、LFO の出力値の仕様がオリジナルとは異なっている点で、これには実際に運用を重ねながら最適値を探っていくことになった。
また、オリジナル回路の LFO1 と LFO2 では Speed の領域設定が2倍程違うので、それに合わせて生成されたコードの LFO2 側に修正を行っている。
この映像を参照すると判るが、元来装備していた LFO に生じていた階段状の段差=不連続面が解消された結果、劇的に音質が向上している。 視覚的には、描かれる波形もスムーズになったことが判る。
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
CombFilter を実装する過程で、諸々の問題が発覚したので、個別に対処を行うことになった。
まず、リモコン使用時にどうやっても特定のパラメータにアクセスできない問題があり、その症状から判断するに、どうやら同じデータを定常的に吐いている箇所が存在するようだ。 具体的には 2VoicMode で Arpeggiator の Note を選択するパラメータに異常が認められたのだが、
描画のトリガーとなるレジスタを虱潰しに探しても原因は見つからず、怪しい箇所を見落としていないか幾度も確認を繰り返したところ、意外なところにバグが潜んでいた。
これは、かなり初歩的な書き漏らしで、この状態ではロータリーエンコーダの出力データが確定せずに、終始同じ値を繰り返し吐き続けることになる。 ヒントは描画の異様なチラツキにあったのだが、もしかするとプログラムの開発を始めた極初期に発生していた書き漏らしだった可能性が高く、リモコンを導入することがなければ本件も認識出来ずに放置されていた不具合であった。
Arpeggiator には他にも LCD の導入を行う前から認識していた不具合があるのだが、こちらは用法上あまり不便を感じなかったため、そのまま放置していた案件である。
今回この問題に手を入れたのは、sdFat の読み込みルーティンを改装した影響で、Step 数が正確に読めなくなったバグの解消に端を発する。 バグの解消自体はとりたてて難しい問題ではなく、、、
予め与えていたオフセット値を解消することで容易に対応することが出来た。
その過程で気になったのが Arpeggiator の読み出しパターンの Up/Down に関する不具合で、不連続な状態でフレーズが再生されてしまう。 要はフレーズを構成する音符の上下に休符が入ってしまう症状で、これは反転時に与えるオフセット値を間違えていたために発生した現象であった。
こちらも、正確なオフセット値を与えることで問題は解決できたのだが、ランダム音階再生時に生じてしまう無音の処理は、それによって生成されるグルーヴ感が好みに合っていたので、敢えて残すことにした。
10月初頭から立て続けに行ってきた改装作業だが、残るはリモコンへのパラメータの実装で、これを完了すればしばらく落ち着くことになりそうだ。
posted by Yasuski at 13:56| LaVoixski
2025年11月10日
LaVoixski@SequenceFileの読み出しに苦労する
今日は一日 Deepseek と Sequencer のデータ読み出し機構の再構成を行っていた。
microSD に記録した1bite のキャラクタをシーケンスで用いるピッチテーブルに変換する仕様は、読み出すキャラクタが 2bite に跨った場合に発生する処理の煩雑さを嫌って創作した仕掛けだ。
極初期に設計したデータ読み出し機構はこのような構成で、

当初はダブルクオートで文字列を区切っていたのを、C#SV という独自規格を捏ち上げることで表記の簡易化を目指したコードはこのような構成となった

C#SV 規格の真髄は、"," に加えて "#" に区切り機能を持たせつつ、同時に音程の半音階上を判定する機能を設定したところにある。 SD file を扱う上で必要となる技術の不足が招いた結果が反映された謎規格ではあるが、区切りを読み出すと同時にフラグが立てられ、指定された音階を呼び出したあとにフラグがクリアされるといった即時処理は確実に行われる。 データの容量が半分に抑えられるために、RAM の残量が厳しかった Teensy3.6 の仕様にもマッチしていた。
問題となるのは記述の煩雑さで、これは RAM1 の消費に直結する。 今回行っているコードの改訂は SD file を読み書きする際のコードをスマートな記述に置き換えるのが目的で、特に記述が長くデータ量が多い音程を扱うパートがその主な対象となる。
だが、前述したピッチを表現する独自規格が影響した結果、乗り換え作業は困難を極めることになった。
対象となった readSeq は特殊な構造で、パートによって読み出すキャラクタを変換する作法が異なる。
Seq01 がドライヴを担当するのは Arpeggiator で、ここでは音階の記述は行われず、キャラクタはHEXにマッピングされる。

Seq02a / Seq03a を除く Seq06a 等の末尾に "a" のつくシーケンスには数列がマッピングされる。 こちらの機能は、演奏される主音階に対する伴奏音のコーディングを微妙に変化させる機能を持つ。 また、これらのシーケンスのステップ数にメインとなるシーケンスとの相対関係を考慮した設定を行うことで、(5:4の場合は、20ステップで一旦収束する)周回ごとに生じたズレがまた収束するといった不規則感を持たせることを目指している。

以上のパートは素直な変換を行う形式故に、改定作業はスムーズに進んだ。
問題となったのはキャラクタをピッチテーブルに変換するパートで、ここで影響したのが "#" の判定とそれを取り扱うタイミングだった。 最初に Deepseek が提案してきた手法は、#判定によって近隣するアドレスのテーブルを振り分ける手法で、簡素な記述が特徴だったものの、この方法ではどうやっても#判定のタイミングとそれをクリアするタイミングがズレてしまう。
そこで、最終的に落ち着いたのが以下の手法で、判定を行う記述はオリジナルに沿った少々煩雑なものとなっている。

が、こちらは確実に動作する。

キャラクタを読み出すパートは sdFat が用いるメソッドに書き換えられた。

最後まで問題となったのは、#判定とクリアのタイミングのズレで、こちらはオリジナルのメソッドに準ずる形の処理を加えることで解決している。 (この部分だけはオリジナルよりも処理が煩雑になっている)

改定後の記述の容易さは素晴らしく、その差は歴然だ。

高級なコーディングではなく「現物合わせ」で書いた独自仕様な音程記録フォーマットに対応したスケッチを、それなりの技術でリファインするのは思っていたよりも手間が掛かる作業で、特にタイミングの辻褄合わせに特化したコーディングの手法を相手に伝えるのはなかなかに難しかった。
追記:
その後、rec_SceneMemory 等の改訂を行った。
特に扱うパラメータ数が多い rec_SceneMemory の改定は大変に手間の掛かる作業で、タイプミスによるバグの内包が疑われる。

一度に扱うパラメータが多く、後半の Seqencer を扱うパートではうっかりと失念していたが独特の不規則性を持たせている。 レジスタの設定やナンバリングを失敗していそうなので、ライヴではほぼ使わない機能ではあるが経過観察が必要だ。

ノート判定機構に、chopping モードを扱う " * " の実装を忘れていたのでこれを追加した。

指定文字のリストにも " * " を登録。

他のピッチテーブルに対応するパートにも改定を行った。

書き込み時のタイミングが怪しいので、こちらも経過の観察が必要だ。

明らかに動作が怪しいのはMSBで極性を判定させているパートで、どうやら + 側にドリフトが発生した結果、"0" のハンドリングが出来ていないようだ。

このパートには早急に対処を行う必要がある。
追記2:
データ受信後のハンドリングを忘れていたので、その式を追加して問題は解決した。
microSD に記録した1bite のキャラクタをシーケンスで用いるピッチテーブルに変換する仕様は、読み出すキャラクタが 2bite に跨った場合に発生する処理の煩雑さを嫌って創作した仕掛けだ。
極初期に設計したデータ読み出し機構はこのような構成で、
当初はダブルクオートで文字列を区切っていたのを、C#SV という独自規格を捏ち上げることで表記の簡易化を目指したコードはこのような構成となった
C#SV 規格の真髄は、"," に加えて "#" に区切り機能を持たせつつ、同時に音程の半音階上を判定する機能を設定したところにある。 SD file を扱う上で必要となる技術の不足が招いた結果が反映された謎規格ではあるが、区切りを読み出すと同時にフラグが立てられ、指定された音階を呼び出したあとにフラグがクリアされるといった即時処理は確実に行われる。 データの容量が半分に抑えられるために、RAM の残量が厳しかった Teensy3.6 の仕様にもマッチしていた。
問題となるのは記述の煩雑さで、これは RAM1 の消費に直結する。 今回行っているコードの改訂は SD file を読み書きする際のコードをスマートな記述に置き換えるのが目的で、特に記述が長くデータ量が多い音程を扱うパートがその主な対象となる。
だが、前述したピッチを表現する独自規格が影響した結果、乗り換え作業は困難を極めることになった。
対象となった readSeq は特殊な構造で、パートによって読み出すキャラクタを変換する作法が異なる。
Seq01 がドライヴを担当するのは Arpeggiator で、ここでは音階の記述は行われず、キャラクタはHEXにマッピングされる。
Seq02a / Seq03a を除く Seq06a 等の末尾に "a" のつくシーケンスには数列がマッピングされる。 こちらの機能は、演奏される主音階に対する伴奏音のコーディングを微妙に変化させる機能を持つ。 また、これらのシーケンスのステップ数にメインとなるシーケンスとの相対関係を考慮した設定を行うことで、(5:4の場合は、20ステップで一旦収束する)周回ごとに生じたズレがまた収束するといった不規則感を持たせることを目指している。
以上のパートは素直な変換を行う形式故に、改定作業はスムーズに進んだ。
問題となったのはキャラクタをピッチテーブルに変換するパートで、ここで影響したのが "#" の判定とそれを取り扱うタイミングだった。 最初に Deepseek が提案してきた手法は、#判定によって近隣するアドレスのテーブルを振り分ける手法で、簡素な記述が特徴だったものの、この方法ではどうやっても#判定のタイミングとそれをクリアするタイミングがズレてしまう。
そこで、最終的に落ち着いたのが以下の手法で、判定を行う記述はオリジナルに沿った少々煩雑なものとなっている。
が、こちらは確実に動作する。
キャラクタを読み出すパートは sdFat が用いるメソッドに書き換えられた。
最後まで問題となったのは、#判定とクリアのタイミングのズレで、こちらはオリジナルのメソッドに準ずる形の処理を加えることで解決している。 (この部分だけはオリジナルよりも処理が煩雑になっている)
改定後の記述の容易さは素晴らしく、その差は歴然だ。
高級なコーディングではなく「現物合わせ」で書いた独自仕様な音程記録フォーマットに対応したスケッチを、それなりの技術でリファインするのは思っていたよりも手間が掛かる作業で、特にタイミングの辻褄合わせに特化したコーディングの手法を相手に伝えるのはなかなかに難しかった。
追記:
その後、rec_SceneMemory 等の改訂を行った。
特に扱うパラメータ数が多い rec_SceneMemory の改定は大変に手間の掛かる作業で、タイプミスによるバグの内包が疑われる。
一度に扱うパラメータが多く、後半の Seqencer を扱うパートではうっかりと失念していたが独特の不規則性を持たせている。 レジスタの設定やナンバリングを失敗していそうなので、ライヴではほぼ使わない機能ではあるが経過観察が必要だ。
ノート判定機構に、chopping モードを扱う " * " の実装を忘れていたのでこれを追加した。
指定文字のリストにも " * " を登録。
他のピッチテーブルに対応するパートにも改定を行った。
書き込み時のタイミングが怪しいので、こちらも経過の観察が必要だ。
明らかに動作が怪しいのはMSBで極性を判定させているパートで、どうやら + 側にドリフトが発生した結果、"0" のハンドリングが出来ていないようだ。
このパートには早急に対処を行う必要がある。
追記2:
データ受信後のハンドリングを忘れていたので、その式を追加して問題は解決した。
posted by Yasuski at 01:03| LaVoixski
2025年11月08日
LaVoixski@sdFatでファイルを書き込むとエラーが出る問題について
導入後にライヴを数件熟しただけでファイルを記録する機会がなかったとはいえ、今更ながら sdFat の不具合が発覚した。
発見が遅れたのは、メモリを呼び出すのみで楽器上でファイルの編集を行う機会がなかったのが原因だが、今回はメモリ管理の破綻に端を発した不具合の連鎖を調査する過程で FileWrite のトラブルが発覚した。
最初の切欠はコンパイル時にこのようなアラート(抜粋)が表示されてことで、

読み出しに不具合はなかったものの、これは余り良い雰囲気がしない警告だ。
当初は Deepseek 的にも「問題はないだろう」風の扱いだったが、最終的にはこのアラートにトラブルが発生するヒントがあった。
実際に不具合を体験したのは、ChebyshevTransfer を行ったときで、何故か設定したカーヴが再起動時に再現されない。 電源を落とすまではローカルのメモリに設定が残っているので気付かなかったのが、どのような設定を行っても、同じカーヴを描く設定が再現されてしまう。 試しに micorSD からアップロードされたデータを読んでみると、フルスケール4Kに対してほぼゼロな”4”が返ってくるこの状況は異常だ。
次に、波形編集の頁で波形を編集してみると、再起動時にパラメータが全て”0”になっていて、これは明らかなトラブルである。
原因の切り出しに数時間を要したが、結局はライブラリに設定されたマクロ間に発生したコンフリクトの影響で、ファイルの読み込み書き出しに不具合が生じていたようだ。 これは、何故か原因究明用に組んだ簡易なスケッチではトラブルが再現されない厄介な問題で、複雑な構造のメイン関数ならではの食い合わせによる疾病とも思われる。
件のマクロを使用することで問題は解決できたのだが、、、

本来このように冗長な記述が必要だったファイルの読み書きが、、、

シンプルな構文で行えるようになったのは行幸であった。

これから、巨大なファイル読み出しシステムの更新を行っていくが、シンプルな記述で対処できる恩恵は大きい。
発見が遅れたのは、メモリを呼び出すのみで楽器上でファイルの編集を行う機会がなかったのが原因だが、今回はメモリ管理の破綻に端を発した不具合の連鎖を調査する過程で FileWrite のトラブルが発覚した。
最初の切欠はコンパイル時にこのようなアラート(抜粋)が表示されてことで、
読み出しに不具合はなかったものの、これは余り良い雰囲気がしない警告だ。
当初は Deepseek 的にも「問題はないだろう」風の扱いだったが、最終的にはこのアラートにトラブルが発生するヒントがあった。
実際に不具合を体験したのは、ChebyshevTransfer を行ったときで、何故か設定したカーヴが再起動時に再現されない。 電源を落とすまではローカルのメモリに設定が残っているので気付かなかったのが、どのような設定を行っても、同じカーヴを描く設定が再現されてしまう。 試しに micorSD からアップロードされたデータを読んでみると、フルスケール4Kに対してほぼゼロな”4”が返ってくるこの状況は異常だ。
次に、波形編集の頁で波形を編集してみると、再起動時にパラメータが全て”0”になっていて、これは明らかなトラブルである。
原因の切り出しに数時間を要したが、結局はライブラリに設定されたマクロ間に発生したコンフリクトの影響で、ファイルの読み込み書き出しに不具合が生じていたようだ。 これは、何故か原因究明用に組んだ簡易なスケッチではトラブルが再現されない厄介な問題で、複雑な構造のメイン関数ならではの食い合わせによる疾病とも思われる。
件のマクロを使用することで問題は解決できたのだが、、、
本来このように冗長な記述が必要だったファイルの読み書きが、、、
シンプルな構文で行えるようになったのは行幸であった。
これから、巨大なファイル読み出しシステムの更新を行っていくが、シンプルな記述で対処できる恩恵は大きい。
posted by Yasuski at 22:40| LaVoixski
2025年11月05日
LaVoixski@i2c受信設定のリファインを行う
今日は朝から、楽器側に設定するESP_NOWの受信パラメータを追加している。

現状リモコン側で拡張する予定なのは16項目+1の17項目だが、取り敢えず 0x07x 分の15項目は既に埋まっている。
が、そのうち Bool が3件あり、

それらを HOLD に割り振ることを考えると、残りの空きは5項目となる。
楽器のシーンメモリをリモコン側から操作することを考えたが、運用を失敗した場合を考えて実装を諦めた。 一方、リモコンのローカルの状態を記録するのは問題ないが、それには SD カードの導入を行うのが前提となる。
受信アドレス、0x07x は全てが globalController 扱いとなるが、リモコン側に現状復帰の機能 = シーンメモリの呼び出しが問題なく行われているので、

使用法を間違えなければ混乱が生じることはないだろう。
楽器とリモコンとの摺合せが想像以上に大変で、特にリモコン側ではパラメータの使用頻度とアクセスの容易さを考えて頁の構成を考えなければならない。

リモコンを完成形に近づけるにはライヴ演奏からのフィードバッグが必要なのに、今はそのライヴの予定がない。
「スケールの使用」は、正当なテルミンの奏法からすると邪道なのだが、趣味で実装を行う分にはそれはそれでよいと思っている。 ただし、趣味に拘泥するあまり、本来必要とされる扱い易さが犠牲になるのは本末転倒なので、其処ら辺のバランスをよく考えなければならない。
追記:
リモコンに搭載されたタッチセンサーの Hold の設定時間は「単位」が判り辛く情報が錯綜しているが、このボードに搭載されているのは CST816T のようで、想定していた CST816S とは制御レジスタのアドレスが異なっていることが判った。
センサが ”816T” の場合、Hold の時間設定を行う制御レジスタのアドレスは "EB" で、値の設定も 1sec 単位ではないようだ。 取り敢えず 50 に設定してみたがこれが良い感じなので、最小単位は 10ms 辺りが正解と思われるも確証はない。

アドレス "EC" はゼスチャーのマスクで、0bxxx のxを1に設定すると対応するゼスチャーにマスクが行われる。 本来はダブルクリックを受け入れるはずが感知しないのはボードをいじりだした初期の頃からの揺るぎない「仕様」と思われるが、狭い領域で発生する誤作動を回避する思惑から、左右のスワイプのみを活かす 0b011と設定した。

設定後は HOLD の時間が短くなり、リモコン操作時に違和感を感じることは少なくなった。
500ms で HOLD を判断しているとしたら「それ以上時間が掛かっている」感触があるのだが、これは物理スイッチとは異なるタッチセンサー固有の錯覚なのかもしれない。
追記2:
ライブラリでは初期設定の記述が以下のようになっていて、、、
#define REG_IRQ_CTL 0xFA
#define IRQ_EN_MOTION 0x10
#define IRQ_EN_LONGPRESS 0x01
irq_en = IRQ_EN_MOTION | IRQ_EN_LONGPRESS; = 0x11
i2c_write(CST816T_ADDRESS, REG_IRQ_CTL, &irq_en, 1);
これをライブラリを使用せずに実行する場合は、、、⇓
Wire.beginTransmission(0x15);
Wire.write(0xFA);
Wire.write(0x11);
Wire.write(1);
Wire.endTransmission();
となる。
現状は 0xFA の制御レジスタをいじっていないので、デバイス設定のデフォルト値がこうなっている可能性が高い。
追記3:
同じことを悩んでいた人たちが解決策を模索した過程を発見している。 やはり、日本語を含めた非中国語圏で混乱が生じているようだ。
現状リモコン側で拡張する予定なのは16項目+1の17項目だが、取り敢えず 0x07x 分の15項目は既に埋まっている。
が、そのうち Bool が3件あり、
それらを HOLD に割り振ることを考えると、残りの空きは5項目となる。
楽器のシーンメモリをリモコン側から操作することを考えたが、運用を失敗した場合を考えて実装を諦めた。 一方、リモコンのローカルの状態を記録するのは問題ないが、それには SD カードの導入を行うのが前提となる。
受信アドレス、0x07x は全てが globalController 扱いとなるが、リモコン側に現状復帰の機能 = シーンメモリの呼び出しが問題なく行われているので、
使用法を間違えなければ混乱が生じることはないだろう。
楽器とリモコンとの摺合せが想像以上に大変で、特にリモコン側ではパラメータの使用頻度とアクセスの容易さを考えて頁の構成を考えなければならない。
リモコンを完成形に近づけるにはライヴ演奏からのフィードバッグが必要なのに、今はそのライヴの予定がない。
「スケールの使用」は、正当なテルミンの奏法からすると邪道なのだが、趣味で実装を行う分にはそれはそれでよいと思っている。 ただし、趣味に拘泥するあまり、本来必要とされる扱い易さが犠牲になるのは本末転倒なので、其処ら辺のバランスをよく考えなければならない。
追記:
リモコンに搭載されたタッチセンサーの Hold の設定時間は「単位」が判り辛く情報が錯綜しているが、このボードに搭載されているのは CST816T のようで、想定していた CST816S とは制御レジスタのアドレスが異なっていることが判った。
センサが ”816T” の場合、Hold の時間設定を行う制御レジスタのアドレスは "EB" で、値の設定も 1sec 単位ではないようだ。 取り敢えず 50 に設定してみたがこれが良い感じなので、最小単位は 10ms 辺りが正解と思われるも確証はない。
アドレス "EC" はゼスチャーのマスクで、0bxxx のxを1に設定すると対応するゼスチャーにマスクが行われる。 本来はダブルクリックを受け入れるはずが感知しないのはボードをいじりだした初期の頃からの揺るぎない「仕様」と思われるが、狭い領域で発生する誤作動を回避する思惑から、左右のスワイプのみを活かす 0b011と設定した。
設定後は HOLD の時間が短くなり、リモコン操作時に違和感を感じることは少なくなった。
500ms で HOLD を判断しているとしたら「それ以上時間が掛かっている」感触があるのだが、これは物理スイッチとは異なるタッチセンサー固有の錯覚なのかもしれない。
追記2:
ライブラリでは初期設定の記述が以下のようになっていて、、、
#define REG_IRQ_CTL 0xFA
#define IRQ_EN_MOTION 0x10
#define IRQ_EN_LONGPRESS 0x01
irq_en = IRQ_EN_MOTION | IRQ_EN_LONGPRESS; = 0x11
i2c_write(CST816T_ADDRESS, REG_IRQ_CTL, &irq_en, 1);
これをライブラリを使用せずに実行する場合は、、、⇓
Wire.beginTransmission(0x15);
Wire.write(0xFA);
Wire.write(0x11);
Wire.write(1);
Wire.endTransmission();
となる。
現状は 0xFA の制御レジスタをいじっていないので、デバイス設定のデフォルト値がこうなっている可能性が高い。
追記3:
同じことを悩んでいた人たちが解決策を模索した過程を発見している。 やはり、日本語を含めた非中国語圏で混乱が生じているようだ。
posted by Yasuski at 13:50| LaVoixski
2025年11月04日
LaVoixski@楽器用コントローラの開発:その4
実験の結果、IMU の吐き出すデータが汚すぎて、音楽用途にはほぼ使えないことが判明した。
確かに、パケット通信の限界を超えてしまった結果でもあるのだが、、、それにしてもノイズにまみれたデータを吐いているようだ。
IMU には多くの設定項目があって、

これらの項目の調整で、なんとか実用になるデータを吐けるようにしたいところだが、、、。
一方、ノイズといえば楽器側にも問題があり、ESP_NOW の受信を確認する目的で駆動していた NeoPixel(LEDの制御ライブラリ)が発するノイズの影響はかなり深刻なレベルとなっていて、これを機会にデータのハンドリングそれ自体に関与していない「パイロットランプ」を無線受信系から排除することにした。
作業の過程で、旧いヴァージョンの M5Stamp が何故か認識されない問題が発生していて、これは iMac にドライバがインストールされていないのが原因と思われる。 が、不思議なことに MacMini の方では認識が可能だった。
で、案の定 esp_tools のヴァージョン違いの影響が出てコンパイルが通らなくなった。
Deepseek に相談すると、「コンパイルが通らない原因となる仕様の変更は ESP-IDF v5.x で導入されました」とのことで、、、
以前:esp_now_recv_cb_tは(mac, data, len) の3引数
現在:esp_now_recv_cb_tは(recv_info, data, len) の3引数
のように、コードを修正することで対応が可能だ。
ファームウエアを書き換えた作業の影響なのか?内部配線の取り回しが微妙に変わった結果、受信感度が激落ちしていて、コマンドの認識が結構微妙な塩梅になっているようだ。 対策として、筐体内部に適当な反射材を誂えるべきなのかもしれない。
リモコン側のコードに対象となるパラメータを書き加える過程で、楽器本体側に VoiceMode 毎に分散したパラメータを一括でコントロールするグローバルコントローラを設置出来ると考えていたが、そもそもが VoiceMode 個別にシーンメモリを実装し、それを頻繁にコールしている手前、

定期的に書き換えられている VoiceMode 個別のデータの統合は難しい。
そのような楽器側の仕様に対処すべく、現状はリモコン側で並列化されたデータの送信を7バイト分行い、

受信側でそれを処理をしていたのだが、

よく考えると、これは受信側で受け側のパラメータを並列化すればよいという単純な話であり、送信側は対応するアドレスに2パケットを送信するだけで済む。

そこで、リモコン側の VoiceMode 固有のデータを一括して送信するモード globalCotroller を廃止して、

受信側に同一のデータを各 VoiceMode のパラメータ毎に配布する構造に通信プロトコルを変更したところ、

結果、楽器側の動作が軽くなった。
やはり、パケット数が増えるとそれだけ通信エラーが発生する確率が上がるようで、以降は通信エラーを回避するためにリモコン側が送信するデータのパケット数を極力減らす方向で調整を行うことにする。

リモコンの実験を行う過程で不便を感じた楽器のトリル機構を組み直して、外部のサブルーチンに作り変えた。

ついでに、演奏時に感じた使い易くて使用頻度が高そうな音列配置のフィードバックも行っておいた。
これも、トリルの操作感が軽いタッチディスプレイを導入した恩恵と言えるだろう。
確かに、パケット通信の限界を超えてしまった結果でもあるのだが、、、それにしてもノイズにまみれたデータを吐いているようだ。
IMU には多くの設定項目があって、
これらの項目の調整で、なんとか実用になるデータを吐けるようにしたいところだが、、、。
一方、ノイズといえば楽器側にも問題があり、ESP_NOW の受信を確認する目的で駆動していた NeoPixel(LEDの制御ライブラリ)が発するノイズの影響はかなり深刻なレベルとなっていて、これを機会にデータのハンドリングそれ自体に関与していない「パイロットランプ」を無線受信系から排除することにした。
作業の過程で、旧いヴァージョンの M5Stamp が何故か認識されない問題が発生していて、これは iMac にドライバがインストールされていないのが原因と思われる。 が、不思議なことに MacMini の方では認識が可能だった。
で、案の定 esp_tools のヴァージョン違いの影響が出てコンパイルが通らなくなった。
Deepseek に相談すると、「コンパイルが通らない原因となる仕様の変更は ESP-IDF v5.x で導入されました」とのことで、、、
以前:esp_now_recv_cb_tは(mac, data, len) の3引数
現在:esp_now_recv_cb_tは(recv_info, data, len) の3引数
のように、コードを修正することで対応が可能だ。
ファームウエアを書き換えた作業の影響なのか?内部配線の取り回しが微妙に変わった結果、受信感度が激落ちしていて、コマンドの認識が結構微妙な塩梅になっているようだ。 対策として、筐体内部に適当な反射材を誂えるべきなのかもしれない。
リモコン側のコードに対象となるパラメータを書き加える過程で、楽器本体側に VoiceMode 毎に分散したパラメータを一括でコントロールするグローバルコントローラを設置出来ると考えていたが、そもそもが VoiceMode 個別にシーンメモリを実装し、それを頻繁にコールしている手前、
定期的に書き換えられている VoiceMode 個別のデータの統合は難しい。
そのような楽器側の仕様に対処すべく、現状はリモコン側で並列化されたデータの送信を7バイト分行い、
受信側でそれを処理をしていたのだが、
よく考えると、これは受信側で受け側のパラメータを並列化すればよいという単純な話であり、送信側は対応するアドレスに2パケットを送信するだけで済む。
そこで、リモコン側の VoiceMode 固有のデータを一括して送信するモード globalCotroller を廃止して、
受信側に同一のデータを各 VoiceMode のパラメータ毎に配布する構造に通信プロトコルを変更したところ、
結果、楽器側の動作が軽くなった。
やはり、パケット数が増えるとそれだけ通信エラーが発生する確率が上がるようで、以降は通信エラーを回避するためにリモコン側が送信するデータのパケット数を極力減らす方向で調整を行うことにする。
リモコンの実験を行う過程で不便を感じた楽器のトリル機構を組み直して、外部のサブルーチンに作り変えた。
ついでに、演奏時に感じた使い易くて使用頻度が高そうな音列配置のフィードバックも行っておいた。
これも、トリルの操作感が軽いタッチディスプレイを導入した恩恵と言えるだろう。
posted by Yasuski at 15:14| LaVoixski
2025年11月02日
LaVoixski@楽器用コントローラの開発:その3
IMUとオプション機能の実装が未了だが、実際に使用する事が可能なレベルで、コードを移植することが出来た。
旧式になったソフトウエア側のジェスチャー判定機能だが、一部クリック動作の判定を行うために温存している。

変更されたジェスチャーの判定項目を確認する表示機能を、ハードウエア側のジェスチャー判定ルーティンに組み込んでいる。 ジェスチャー判定が若干不安定なのは、LCDの周辺部に接触した他の指の影響で、LCDをフレームにマウントすることで対処が可能と思われる。

jxl+ という聞き慣れないベンダーの製品は、Seeed Round Displayよりも初期導入の敷居が高いデバイスだが、そのジェスチャー認識機能は素晴らしく、性能はこちらの方に軍配が上がる。
問題は、共有されている情報が極端に少ないことだが、これから化けるかもしれない逸品だと思う。
ライブラリの影響なのか、Bitmapファイルの描画が不得手なので、

描画を行う際にはファイルのフォーマットを検討することになるだろう。
旧式になったソフトウエア側のジェスチャー判定機能だが、一部クリック動作の判定を行うために温存している。
変更されたジェスチャーの判定項目を確認する表示機能を、ハードウエア側のジェスチャー判定ルーティンに組み込んでいる。 ジェスチャー判定が若干不安定なのは、LCDの周辺部に接触した他の指の影響で、LCDをフレームにマウントすることで対処が可能と思われる。
jxl+ という聞き慣れないベンダーの製品は、Seeed Round Displayよりも初期導入の敷居が高いデバイスだが、そのジェスチャー認識機能は素晴らしく、性能はこちらの方に軍配が上がる。
問題は、共有されている情報が極端に少ないことだが、これから化けるかもしれない逸品だと思う。
ライブラリの影響なのか、Bitmapファイルの描画が不得手なので、
描画を行う際にはファイルのフォーマットを検討することになるだろう。
posted by Yasuski at 10:39| LaVoixski
LaVoixski@楽器用コントローラの開発:その2
2日間の苦労の末、タッチスイッチをやっと実装することが出来た。

今回Deepseekさんの助けはなく、純粋な自己解決であった。
タッチスイッチの動作が阻害されていた原因は後述する”TICK"というボード製作者のサンプルコードに含まれていたライブラリで、これを取り除いてスイッチ素子のリセットを単純な方法に書き換えた後、ようやくセンサのデータを拾えるようになった。
問題になったのは、タッチセンサー/CST816S と、i2c接続の外部増設スイッチ/TCA6408 の組み合わせで、

特に、実装されたデバイスのIRQ出力が直接MCUのGPIOにアクセス出来ない癖のあるハードウエアの設計に困惑させられることになった。
コードの構成は既に稼働実績のあるスケッチをCST816系に合わせて加工することにしたが、

レジスタの構成が異なることをDeepseekが失念した結果、混乱が発生することになった。
ここで発想を変えて、現在手掛けているハードウエアに合わせて個別にセンサー類のコーディングを行い、各素子の稼働を確認できた経過を先の記事に書いた。
今回はこの実績を元に、昨日は動かなかったコードの構造を解析して、タッチセンサーから出力されるデータの流れを追うことから始めた。
まず、混乱していたサブルーチンの配置を、稼働実績のあるコード

に寄せて再配置を行った。
Deepseekが抱える弱点は、自らが生成したコードに対しての継承性を失ってしまうところにあり、同じスレッド内でさえも辿ってきた思考の過程を忘却する傾向が強く、それを人間側が見抜けないうちに目的から逸れたコードが生成されていく。 これは、稼働実績のあるコードにも言えることで、折角の実績が継承されずピントの外れた「新たな提案」を始める始末であった。
勿論、問題はコードの本質的な構造を理解できていない人間側にもあり、負の相乗効果によって脱線が進んでいく。 人間側が脱線に気付くのは既に後戻りが難しくなるフェイズになってからで、そこから脱線に至る前の提案を一からやり直すことになる。
今回は混乱を避けるためにDeepseekから距離を置き、既に生成して貰った複数の稼働が保証されたコードを読み合わせて、その差分から問題点を洗い直すところから作業を始めた。
最初にチェックしたのは i2c 拡張ポートの稼働状態で、各デバイスのインターラプトを受信するこの素子が正常に働いているか、スケッチを走らせて確認を行った。 このスケッチはデバイスの接続をチェックする過程で生成して貰ったものだが、大量に生成された試作品の中からのサルベージに労力が費やされることになった。

シンプルなスケッチでは動作が確認出来たとしても、それを組み込んだ別のスケッチでは何故か動かなくなってしまう。 そこで、対象となったコードの差分を確認することになるのだが、ここで問題になってくるのが、先に話題にした「コードの継承性」だ。 例えば、似たようなコードであっても変数の命名が継承されておらず、しかもそれが微妙に違うケースがそこそこあって、その都度「通らないコンパイル」のエラー解析にDeepseek共々に疲弊が進んでいく。 AIの方にも疲弊の痕跡が認められるのが興味深い点で、理由は判らないが「人間側の混乱」が伝染しているようにも感じる。
さて、最初に見つけた差分は、Tickerというライブラリの存在だ。

どうやらこのライブラリがi2c増設GPIOの稼働を阻害していたようで、これを取り除いてシンプルな初期化ルーティンを採用した結果、なんとかデバイスを認識することが出来た。

実際にデバイスを操作してみると、どうやら機能のコンフリクトが発生しているようで、ここでも継承性が維持されない問題が発覚した。 具体的にはgestureという変数が、異なるルーティンのジェスチャー判別機構で共有されているようだ。
これは、Gesture判別機構そのものにも言えることで、センサー搭載のMCUが判定してくるGestureと、メイン関数内で判定するGestureの間に期待していた並立関係が維持されずにコンフリクトが発生している。

ここで戸惑ってしまうのは、どちらか一方を排除するとシステム全体が成り立たなくなりそうなところで、折衷案として判定する対象を住み分ける手法を考えた。
タッチの判定をするreadTouchData( )の前半と後半がそれで、同一の判定をそれぞれの場所で行っている。

後半のパートでは、タッチセンサーに内装されたMCUによるGesture判定システムに対応している。

実験の結果、このGesture判定機構がかなり優秀なことが判り、急遽こちらの方をメインに処理の割り振りを行うことになった。

ここで採用したGesutureは左右のスワイプで、それらを上下のエリアに分離して、シングル・ダブルクリックに分配していたパラメータを配置した。 実験を行った結果、予想通りコンフリクトの発生を認めつつも動作の継承を確認できたので、元からあったMCU側のGesture判定ルーティンからのリンクを廃し、判定をセンサ側に引き渡すことに成功した。
同様に動作が有効になった「機械スイッチ」にもスイッチ系のパラメータを割振ることにした。

i2c接続という複雑な構成の「物理スイッチ」(これがトラブル発生の元凶でもある)も生きているので、確認はしていないが多分IMUも作動していると思われる、、、。
タッチスイッチのHOLDが効かない問題は、先のGesture判定機構のコンフリクトが原因だった。 タッチセンサ側のゼスチャー判定の確度が予想以上に素晴らしく、実用試験を重ねてその操作性を検証していく予定。
肝心要なIMUの動作をリンクさせる機能の実装(このデバイスを選んだ理由)は、未了。
気になっていた物理スイッチのチャタリングは対処済み。

描画にアラが見られるので、其処にも対処を行う必要があるが、今日はこの時点でお休みとする。
今回Deepseekさんの助けはなく、純粋な自己解決であった。
タッチスイッチの動作が阻害されていた原因は後述する”TICK"というボード製作者のサンプルコードに含まれていたライブラリで、これを取り除いてスイッチ素子のリセットを単純な方法に書き換えた後、ようやくセンサのデータを拾えるようになった。
問題になったのは、タッチセンサー/CST816S と、i2c接続の外部増設スイッチ/TCA6408 の組み合わせで、
特に、実装されたデバイスのIRQ出力が直接MCUのGPIOにアクセス出来ない癖のあるハードウエアの設計に困惑させられることになった。
コードの構成は既に稼働実績のあるスケッチをCST816系に合わせて加工することにしたが、
レジスタの構成が異なることをDeepseekが失念した結果、混乱が発生することになった。
ここで発想を変えて、現在手掛けているハードウエアに合わせて個別にセンサー類のコーディングを行い、各素子の稼働を確認できた経過を先の記事に書いた。
今回はこの実績を元に、昨日は動かなかったコードの構造を解析して、タッチセンサーから出力されるデータの流れを追うことから始めた。
まず、混乱していたサブルーチンの配置を、稼働実績のあるコード
に寄せて再配置を行った。
Deepseekが抱える弱点は、自らが生成したコードに対しての継承性を失ってしまうところにあり、同じスレッド内でさえも辿ってきた思考の過程を忘却する傾向が強く、それを人間側が見抜けないうちに目的から逸れたコードが生成されていく。 これは、稼働実績のあるコードにも言えることで、折角の実績が継承されずピントの外れた「新たな提案」を始める始末であった。
勿論、問題はコードの本質的な構造を理解できていない人間側にもあり、負の相乗効果によって脱線が進んでいく。 人間側が脱線に気付くのは既に後戻りが難しくなるフェイズになってからで、そこから脱線に至る前の提案を一からやり直すことになる。
今回は混乱を避けるためにDeepseekから距離を置き、既に生成して貰った複数の稼働が保証されたコードを読み合わせて、その差分から問題点を洗い直すところから作業を始めた。
最初にチェックしたのは i2c 拡張ポートの稼働状態で、各デバイスのインターラプトを受信するこの素子が正常に働いているか、スケッチを走らせて確認を行った。 このスケッチはデバイスの接続をチェックする過程で生成して貰ったものだが、大量に生成された試作品の中からのサルベージに労力が費やされることになった。
シンプルなスケッチでは動作が確認出来たとしても、それを組み込んだ別のスケッチでは何故か動かなくなってしまう。 そこで、対象となったコードの差分を確認することになるのだが、ここで問題になってくるのが、先に話題にした「コードの継承性」だ。 例えば、似たようなコードであっても変数の命名が継承されておらず、しかもそれが微妙に違うケースがそこそこあって、その都度「通らないコンパイル」のエラー解析にDeepseek共々に疲弊が進んでいく。 AIの方にも疲弊の痕跡が認められるのが興味深い点で、理由は判らないが「人間側の混乱」が伝染しているようにも感じる。
さて、最初に見つけた差分は、Tickerというライブラリの存在だ。
どうやらこのライブラリがi2c増設GPIOの稼働を阻害していたようで、これを取り除いてシンプルな初期化ルーティンを採用した結果、なんとかデバイスを認識することが出来た。
実際にデバイスを操作してみると、どうやら機能のコンフリクトが発生しているようで、ここでも継承性が維持されない問題が発覚した。 具体的にはgestureという変数が、異なるルーティンのジェスチャー判別機構で共有されているようだ。
これは、Gesture判別機構そのものにも言えることで、センサー搭載のMCUが判定してくるGestureと、メイン関数内で判定するGestureの間に期待していた並立関係が維持されずにコンフリクトが発生している。
ここで戸惑ってしまうのは、どちらか一方を排除するとシステム全体が成り立たなくなりそうなところで、折衷案として判定する対象を住み分ける手法を考えた。
タッチの判定をするreadTouchData( )の前半と後半がそれで、同一の判定をそれぞれの場所で行っている。
後半のパートでは、タッチセンサーに内装されたMCUによるGesture判定システムに対応している。
実験の結果、このGesture判定機構がかなり優秀なことが判り、急遽こちらの方をメインに処理の割り振りを行うことになった。
ここで採用したGesutureは左右のスワイプで、それらを上下のエリアに分離して、シングル・ダブルクリックに分配していたパラメータを配置した。 実験を行った結果、予想通りコンフリクトの発生を認めつつも動作の継承を確認できたので、元からあったMCU側のGesture判定ルーティンからのリンクを廃し、判定をセンサ側に引き渡すことに成功した。
同様に動作が有効になった「機械スイッチ」にもスイッチ系のパラメータを割振ることにした。
i2c接続という複雑な構成の「物理スイッチ」(これがトラブル発生の元凶でもある)も生きているので、確認はしていないが多分IMUも作動していると思われる、、、。
タッチスイッチのHOLDが効かない問題は、先のGesture判定機構のコンフリクトが原因だった。 タッチセンサ側のゼスチャー判定の確度が予想以上に素晴らしく、実用試験を重ねてその操作性を検証していく予定。
肝心要なIMUの動作をリンクさせる機能の実装(このデバイスを選んだ理由)は、未了。
気になっていた物理スイッチのチャタリングは対処済み。
描画にアラが見られるので、其処にも対処を行う必要があるが、今日はこの時点でお休みとする。
posted by Yasuski at 01:05| LaVoixski
2025年10月31日
LaVoixski@楽器用コントローラの開発
ここまで仕上げるのに丸一日(比喩ではない)が掛かっている。
ハードウエア的には、i2c周りの構成が複雑な癖の強い製品で、
開発の敷居が高い印象を持った。
現在は機能の実証を行っているフェイズで、センサの設定を詰めた後、楽器用のコントローラとして仕上げていく。
追記:
異様に描画が遅いパラレル接続LCDへの対策をDeepseekに相談した。
パラレルなデータのやり取りは動作が軽いはずなのにシリアル接続に速度が負けてしまう、、、という異常な状況にはライブラリの持つ欠点も絡んでいたようで、有効な対策を探し出せたものの、そもそもデータのやり取りを行う手法に問題があるようだ。
本格的に動画を扱う際には画像の扱い方を考え直す必要がある。
posted by Yasuski at 16:37| LaVoixski
2025年10月29日
LaVoixski@ESP32系列の開発環境を再構築する
ESP32の新しい製作環境をIDEが不調だったiMac上に再構築した。
案の定、Python3のリンクエラーが出たので、過去のBlog記事から記憶を掘り起こして対策を行った後、無事コンパイルからアップロードまでの動作を確認できた。

複線タイプの接続を行うLCDのハンドリングは厄介で、LCDライブラリには最新のヴァージョンを選択する必要があるだけでなく、同時に esp_tools のヴァージョンも上げなければならない。 今回の作業は、新たに扱うボードの仕様に対応するのが目的だったが、旧式なPC上でesp_toolsを扱うには、フォルダ内にある platform.txt ファイル上のリンクを書き換える作業が必要となる。

今回は、esptool.py内に記述されたリンクの書換は不要だったようだ。
今まで旧いヴァージョンの esp_tools を使用していた理由は、ESP_NOWに発生していた不具合を避けるのが目的だった。 コンパイルが通らなかった原因は「ESP専用ライブラリ内のデータ型の変更」にあったようで、こちらの問題にはプログラム上で送信を行う変数のデータ型に修正を行って対処することができた。

残るタスクは旧環境に縛られているTeensyへの対策だが、Deepseekに対策を相談することで改善が進むかもしれない。
案の定、Python3のリンクエラーが出たので、過去のBlog記事から記憶を掘り起こして対策を行った後、無事コンパイルからアップロードまでの動作を確認できた。
複線タイプの接続を行うLCDのハンドリングは厄介で、LCDライブラリには最新のヴァージョンを選択する必要があるだけでなく、同時に esp_tools のヴァージョンも上げなければならない。 今回の作業は、新たに扱うボードの仕様に対応するのが目的だったが、旧式なPC上でesp_toolsを扱うには、フォルダ内にある platform.txt ファイル上のリンクを書き換える作業が必要となる。
今回は、esptool.py内に記述されたリンクの書換は不要だったようだ。
今まで旧いヴァージョンの esp_tools を使用していた理由は、ESP_NOWに発生していた不具合を避けるのが目的だった。 コンパイルが通らなかった原因は「ESP専用ライブラリ内のデータ型の変更」にあったようで、こちらの問題にはプログラム上で送信を行う変数のデータ型に修正を行って対処することができた。
残るタスクは旧環境に縛られているTeensyへの対策だが、Deepseekに対策を相談することで改善が進むかもしれない。
posted by Yasuski at 18:59| LaVoixski
