2017年11月22日

Open.Theremin@緑基板の製作

Frequency側のオシレーターの定数を周波数が低くなる方向にLを倍量にして変更している。 撮影後、adatEncoder/DACの実装を完了済み。

IMG_7798.JPG

今回は、オシレーターのLにリードタイプのものを使用している。 VariCapを直接調整するためのVR接続端子の追加を忘れないこと。

IMG_7801.JPG

こちらは、V3基板/Teensy3.6用の基板。

IMG_7795.JPG



IMG_7789.JPG

これは、ベーシック仕様の基板。 緑基板から、Teensy3.5/3.6が共用できるようになった。 DCインレットとミニフォン端子の実装を忘れないこと。 

IMG_7790.JPG

この基盤には、基本形となる12bit出力限定のプログラムを準備している。 出力は、MCUからの2chと、V3基板側からの1chの合計3chとなる。

クロックソースをV3基板から受けた場合、オーディオクロックは8MHzを分周した31.25kHz。 それに合わせて、LPFの定数は低めに設定した。 テルミンの楽器としての性格を考えると、LPFは今よりも更に低めに周波数を設定したほうが良いかもしれない。

以上がオプション無しの素の状態。

IMG_7796.JPG

Teensy3.6にID-292版の修正済のファームウエアを書き込んだところ、機能切り替えスイッチの極性が逆に設定されていることが発覚、コレをさらに修正することになった。

IMG_7808.JPG

ID-292ではTeensyを損壊する事故(既に3基潰した)が多発しているので、実装前に保護対策を練る必要がある。

V3基板対応ボードに通電したところ、端子の設定ミスなどが発覚して修正を行った。 また、起動時のピポパ音は出力されるものの、アンテナのセンシングが全く行われない。

IMG_7809.JPG

最初に発覚した失敗は、BUT端子がプログラムのミスで別のポートに割り振られていたことで、これはソフトウエア側の改修で難なく修正することが出来た。 

次に、発振の確認と端子の電圧を測定してみたところ、DACにデータを送れずチューニングが行えない情況が判明した。 原因はSwitch機構内で条件分岐が上手く働かず、ロータリーエンコーダのデータが更新されないことにあったが、これはTeensy3.5では問題なく動いていた部分で、機種依存のバグが発生している可能性がある。

その後、この不具合をプログラムのキャリブレーションモードにロータリーエンコーダを実装することで解決しているが、ノーマルモードとの切り替えの可否は未確認。

IMG_7804.JPG

エンコーダーの稼働確認後にDACを駆動して発振周波数の調整を行ったが、再起動後にセットアップ時にデータを送っているにも係わらず、何故か起動時のセットアップルーチン内でDACにデータが伝送されない問題が発覚する。 MCUの機種依存で不具合が出ているところが怪しく、IDEのバグが疑われるが「サブルーチン化せず、関連する処理は全部ローカルに記述」することで、問題を回避できるかもしれない。

Screen Shot 2017-11-21 at 11.35.08 PM.png
posted by Yasuski at 04:32| open.Theremin

2017年11月15日

pinConfigurations/ID-292

#define LATCH01 27
#define LATCH01_ON (CORE_PIN27_PORTSET = (1<<15))
#define LATCH01_OFF (CORE_PIN27_PORTCLEAR = (1<<15))

#define LATCH02 20
#define LATCH02_ON (CORE_PIN20_PORTSET = (1<<5))
#define LATCH02_OFF (CORE_PIN20_PORTCLEAR = (1<<5))

#define LATCH03 21
#define LATCH03_ON (CORE_PIN21_PORTSET = (1<<6))
#define LATCH03_OFF (CORE_PIN21_PORTCLEAR = (1<<6))

#define LATCH04 18
#define LATCH04_ON (CORE_PIN18_PORTSET = (1<<3))
#define LATCH04_OFF (CORE_PIN18_PORTCLEAR = (1<<3))

#define LATCH05 16
#define LATCH05_ON (CORE_PIN16_PORTSET = (1<<0))
#define LATCH05_OFF (CORE_PIN16_PORTCLEAR = (1<<0))

#define LATCH06 15
#define LATCH06_ON (CORE_PIN15_PORTSET = (1<<0))
#define LATCH06_OFF (CORE_PIN15_PORTCLEAR = (1<<0))

#define LATCH07 17
#define LATCH07_ON (CORE_PIN17_PORTSET = (1<<1))
#define LATCH07_OFF (CORE_PIN17_PORTCLEAR = (1<<1))

#define CLOCK01 25
#define CLOCK01_ON (CORE_PIN25_PORTSET = (1<<5))
#define CLOCK01_OFF (CORE_PIN25_PORTCLEAR = (1<<5))

#define DATA01 26
#define DATA01_ON (CORE_PIN26_PORTSET = (1<<14))
#define DATA01_OFF (CORE_PIN26_PORTCLEAR = (1<<14))

#define LEDred 7 // LED on D7
#define LEDred_ON (CORE_PIN7_PORTSET = (1<<2))
#define LEDred_OFF (CORE_PIN7_PORTCLEAR = (1<<2))

#define LEDgrn 8 // LED on D8
#define LEDgrn_ON (CORE_PIN8_PORTSET = (1<<3))
#define LEDgrn_OFF (CORE_PIN8_PORTCLEAR = (1<<3))

#define LED 9 // LED on D9
#define LED_ON (CORE_PIN9_PORTSET = (1<<3))
#define LED_OFF (CORE_PIN9_PORTCLEAR = (1<<3))

#define LED2red 38 // LED on D38
#define LED2red_OFF (CORE_PIN38_PORTSET = (1<<11)) //inverted
#define LED2red_ON (CORE_PIN38_PORTCLEAR = (1<<11))

#define LED2grn 37 // LED on D38
#define LED2grn_OFF (CORE_PIN37_PORTSET = (1<<10))
#define LED2grn_ON (CORE_PIN37_PORTCLEAR = (1<<10))

#define LED2 39 // LED on D39
#define LED2_OFF (CORE_PIN39_PORTSET = (1<<17))
#define LED2_ON (CORE_PIN39_PORTCLEAR = (1<<17))

#define buttonPin01 11 // Button Pin on D11
#define button_State1 (CORE_PIN11_PINREG & (1<<6))

#define buttonPin02 36 // Button Pin on D36
#define button_State2 (CORE_PIN36_PINREG & (1<<9))

#define buttonPin03 3 // Button Pin on D3
#define button_State3 (CORE_PIN3_PINREG & (1<<12))

#define buttonPin04 4 // Button Pin on D4
#define button_State4 (CORE_PIN4_PINREG & (1<<13))

#define buttonPin05 5 // Button Pin on D5
#define button_State5 (CORE_PIN5_PINREG & (1<<7))

#define buttonPin06 6 // Button Pin on D6
#define button_State6 (CORE_PIN6_PINREG & (1<<4))

#define LEDvol 28 // LED on D28
#define LEDvol_ON (CORE_PIN28_PORTSET = (1<<16))
#define LEDvol_OFF (CORE_PIN28_PORTCLEAR = (1<<16))

#define LEDvol2 13
#define LEDvol2_ON (CORE_PIN13_PORTSET = (1<<5))
#define LEDvol2_OFF (CORE_PIN13_PORTCLEAR = (1<<5))

#define SAMPCLK_STATE (CORE_PIN19_PINREG & (1<<2)) //sampling clock in
#define SAMPCLK_MASK (CORE_PIN19_CONFIG = PORT_PCR_IRQC(0)) //masking sampling clock in
#define SAMPCLK_ACTV (CORE_PIN19_CONFIG = PORT_PCR_IRQC(9)) //activate sampling clock in

#define CS01 29
#define CS01_ON (CORE_PIN29_PORTSET = (1<<18))
#define CS01_OFF (CORE_PIN29_PORTCLEAR = (1<<18))

#define LDAC01 33
#define LDAC01_ON (CORE_PIN33_PORTSET = (1<<24))
#define LDAC01_OFF (CORE_PIN33_PORTCLEAR = (1<<24))

#define SCK01 30
#define SCK01_ON (CORE_PIN30_PORTSET = (1<<19))
#define SCK01_OFF (CORE_PIN30_PORTCLEAR = (1<<19))

#define DAC16 40
#define DAC16_ON (CORE_PIN40_PORTSET = (1<<28))
#define DAC16_OFF (CORE_PIN40_PORTCLEAR = (1<<28))

#define DAC16_2 31
#define DAC16_2_ON (CORE_PIN31_PORTSET = (1<<10))
#define DAC16_2_OFF (CORE_PIN31_PORTCLEAR = (1<<10))

#define SD01 32
#define SD01_ON (CORE_PIN32_PORTSET = (1<<11))
#define SD01_OFF (CORE_PIN32_PORTCLEAR = (1<<11))


#define PC_STATE1 (CORE_PIN22_PINREG & (1<<1)) // pitch osc in
#define PC_STATE2 (CORE_PIN23_PINREG & (1<<2)) // volume osc in
posted by Yasuski at 01:05| open.Theremin

2017年10月27日

Open.Theremin@生存確認作業の記録

廃棄した基盤から引き剥がし、緑基板に再実装したFPGAとPLLオーディオクロックジェネレータIC/27MHzX'talの生存を、FPGA書き込み端子に直接3.3V電源を供給した後、波形の観測を行って確認した。

IMG_7632.JPG

動作確認用に特化した電源ラインを分岐させる端子を作る必要があるが、基板側にコネクタを設置せず信号を取り出せる端末の形状を工夫しなければならない。

IMG_7731.JPG

再実装を行ったパーツのうち特にV3ボード対応基板に実装した"P601-27"は、基板から邪魔なICコネクタを引っぺがす時の事故で4番ピンが根本からモゲたために動作が心配だったが、無事稼働している模様。

IMG_7732.JPG

この実験で、使用している半導体が予想以上に頑丈なことが判った。 まあ、リフローによる実装が当たり前になった世の中なので、低出力のハンダ鏝で行う30秒程度の加熱はヘッチャラなのであろう。

WS001173.JPG

WCKの発振を確認する際に、FPGAのCLR端子をロジックレベル”H”に固定しなければならないのが手間。 ファームウエア設計の段階でプルアップしておけば良かったのだが、今更ここに手を加えると最悪の場合FPGAの端子配置が変わるので、不便でも我慢することに。

IMG_7749.JPG

WCKの出力波形は、オシロスコープの5usのスパンで観測している。 信号が丁度2マスちょいで周期しているので、96kHzのオーディオクロックが供給されていることが確認できる。 その後、周波数の設定端子S1/S2をそれぞれグランドに落とし、44.1/48kHzの発振も確認済みだ。
posted by Yasuski at 02:09| open.Theremin

2017年10月25日

Open.Theremin@出力波形の観測

Open.Thereminの出力波形を観測した。

Screen Shot 2017-10-25 at 12.13.37 AM.png

上から、ミックス・1番オシレーター・2番オシレーターの出力。 

2番オシレーターの波形には問題があって、下側/グランドよりが潰れ気味に見える。 ハードウエアに何か問題があるのだろうか。

3系統の独立した出力のテルミンなんてのはかなりレアだと思うのだけど、思ったよりも世間的な訴求力は無いような雰囲気。

Screen Shot 2017-10-25 at 12.12.12 AM.png

別のコンビネーションのオシレーターをミックスした波形。

Screen Shot 2017-10-25 at 12.11.24 AM.png

一度ミュートしてから発音する過程の波形。 よく見ると、DC成分がドリフトしていることが判る。

ピアニッシモ時の立ち上がりに小さなスパイクが見られる。

Screen Shot 2017-10-25 at 12.10.37 AM.png

こちらは、デクレッシェンド時の波形。

コンデンサの放電が終了するまで、ドリフトが継続している。

Screen Shot 2017-10-25 at 12.10.08 AM.png

これも、デクレッシェンド→クレッシェンド時の波形だが、ここでも弱音時にスパイクが見られる。

Screen Shot 2017-10-25 at 12.09.28 AM.png

スパイク波形の拡大図。

スパイクが全ての出力で同時に発生していることから、プログラム側に問題がある可能性が高い。

Screen Shot 2017-10-25 at 12.05.22 AM.png

発音の情況を俯瞰した図。

複数の波形が合成されていることが良く判る。

Screen Shot 2017-10-25 at 12.04.16 AM.png

こちらは波形の解像度を上げたもの。

位相のズレが反映されて複雑な波形を作り出している。

トランジションモードでは、このような倍音関係がシームレスに変化していく。

Screen Shot 2017-10-25 at 12.03.58 AM.png

Screen Shot 2017-10-25 at 12.03.08 AM.png
posted by Yasuski at 08:37| open.Theremin

2017年10月24日

Open.Theremin@Volumeデータの出力更新レートの変更を試みる

ヴォリュームコントロール時にノイズが出る不具合の原因が、コントロールヴァリューのリップル成分ではないか?という疑念から、データの更新サイクルを変更することを思いついた。

通常は、FTMからのフラッグをトリガーにしていたところを、サンプリングクロックが立ち上がるタイミングでカウントを行う専用タイマーを追加し、

WS001167.JPG

これの積算数によって、、、

WS001169.JPG

出力の更新を決定する機構を仮に設定、評価を行った。

WS001168.JPG

試しに、音量を更新する周期を遅らせると、それにともなってビートの周波数が下がっていく。 更新のタイミングを更に遅らせていくと、最終的には階段状のクリック音として音量変化が認識されるレベルになった。

ザラザラしたノイズは消滅したものの、結局はノイズが可聴域に下がってくることに拠る弊害のほうが大きいことが判明したため、この仕組はお蔵入りとなった。

以上の実験から、ノイズはデータの不連続面が影響して発生したスプリアスと思われるが、発生の原因を確定するにはヴォリュームの値をDACから出力し、この電圧をオシロスコープで監視するのが速道かもしれない。 電圧が推移する過程で変なスパイクが認められた場合は、これまた想定外の問題が発生していることになる。

改良の過程で、出力をマッピングして最大音量に至るラスト12bitほどの変化量を圧縮する機構を追加している。 この処置に因ってレベルオーヴァー由来の歪は皆無になった。 

WS001170.JPG

依然としてbitノイズっぽいザラザラ感は解消されていないものの、選択した出力波形がSawToothの場合は殆ど気にならないレベルになったことから、トランジションコントロールに設定していた最大数値の制限を解除した。 いきなりガッツリと歪まなくなったので、ソフトにディストーションが掛かるこちらの方が使い易い感触だ。

他の不具合としては、左手でTransitionをコントロールする際にデータがゼロになる閾値が出来、この不連続面に由来するノイズが発生するケースがあった。 これに対応するため、出力に以下の処理を加えてノイズの発生を回避している。

WS001171.JPG

以前は、閾値に至らないようにオシレーターのチューニングを続けることで調整していたが、この方法ではVolume側に過大なドリフトが生じた時は対処しきれなかった。 出力されるデータに制限を掛けることによってノイズの発生は回避されることになった。
posted by Yasuski at 19:07| open.Theremin

2017年10月21日

Open.Theremin@Interruptの整理とRAMの活用

昨日は思いついて、グローバルインターラプトを拒否る cli() に関連した処理の整理を行っていたが、

WS001162.JPG

残念ながら清書後に音質の改善は殆どみられなかった。

その後、以前MCUの容量不足で失敗していたWavetableのデータをRAMに全部載せする計画に再チャレンジしたが、IDEのリザルトを観る限りでは成功しているようだ。

WS001161.JPG

ただし、こちらも音質の向上を感じることはなかった。
 
ついでに Wavetable とそれを扱うシーケンスのデータ型を「工業用のDACを使用する限りオーディオDACの2'sコンプリフォーマットに拘る必然は殆ど無い」と判断して、int から uint に変更している。

RAMにデータを集約すると、ROMからデータを読み出す場合と比べてアクセススピードが超絶に速くなる筈だったのだが、体感的に明確な形で何かが変化した感触はない。 強いて言うならば、アンテナのセンシングの精度が上がって動作が軽くなった感がするが、動作の過程で消費される時間を実測していないのであくまでもこれは印象にすぎない。 期待した程の成果が上がら無いのは、他の処理と比較してROMへのアクセスに要していた時間の割合が大したものではなかった、、、ということなのかもしれない。

以上、コードの改良を行ってはみたものの音質に明確な改善を感じられない残念な結果となって仕舞ったが、引き続きノイズっぽい発音の発生原因を探ることにする。
posted by Yasuski at 05:51| open.Theremin

2017年10月18日

Open.Theremin@オシレーターのドリフト等

オシレーターのドリフトを記録した、見るのが辛気臭い資料映像。



10分以上通電してもこんな感じなので、楽器としての精度を考えると、かなりアカン雰囲気である。

録画の過程で、オシレーターのドリフト値がソフトウエアに拠る修正可能な限界を超えた結果、閾値辺りの挙動が大変雑になり、センシングのダイナミックレンジが狭まる現象を体験した。

こうなると再度キャリブレーションを行うしかないのだが、オシレーターを直接CVでコントロールすると二度手間が省ける。 

ソフト的に対処できる限界を超えるポイントは、水晶発振子を分周したリファレンスクロックとLC発振器の周波数の差分により発生するビートの周波数が、MCUの周波数タイマーがセンシング出来る最高周波数を上回った時で、ソフトウエア側で差分の修正を行って辻褄を合わせようとしてもダイナミックレンジが極端に狭まってしまう。 これはPitch/Volume双方に発生する現象だが、Volume側ではより深刻な影響が顕現している。

オシレーターの安定性を確保できない現状では、CVを印加する機能を導入するしか無いだろう。

ID-292版ではオシレーター間に生じる相対誤差を軽減するために、物理的に近似した回路構成の発振器をリファレンスに用いているが、一方の回路をVariCapコントロールにしてしまったところが画竜点睛だったかもしれない。 現行の回路は運用試験を行って評価していくが、誤差が大きくなる場合はアンテナ以外は完全に一致した回路を組むことにしている。 完璧を期するには外部にアンテナに該当するカウンターバランスを接続する手もあるが、そこまでやるかどうかは微妙なところ。

その後、モードを切り替えるインターフェイスを改良した。 波形選択モードを各和音モードの合間に挿入している。 映像の後半ではヴォリュームコントロールのレスポンスを試している。



操作感の印象だが、多少はまどろっこしく感じるも特に和音でトランジションのコントロールを行う際の音のバラけ方が、瞬時に判るのが良い。 以前はバランスの確認をするにはモードの間を行ったり来たりする必要があり、最大で4ステップを超える作業が必要だったが、新しいインターフェイスではこれが1ステップで済む。 

問題は、戻るにしても進めるにしても混乱の原因となるのがダブルクリックを判定する間隔で、出来る範囲でこれを最適化しなければならない。 特にFWDにシングルクリックでモードを進める場合、閾値の設定次第で機械側の判定が微妙になってくる。 一方、ダブルクリックでRWD方向に進む場合、FWDに較べて判定の確実性が高い結果が出ているので、クリックの間隔をタイトに調整する方向で修正を検討している。

10月27日 追記:

前回行った改良では「波形選択パラメーターの出現頻度」を上げるものだったが、実際に使用してみたところ、不安定なチューニング系のパラメーターを弄りたくなる場合が少なくなかった。 基本的にオシレーターの周波数ドリフト問題に関してはアナログな手法で対処することを考えているが、ファインチューニングはデータ側で行うことを想定している。 

現在設定している循環するパラメーターの選択項目は 

→黒 (空は波形選択パラメーター)

としているが、

→黒 

のように、出来るだけ短い距離で緑と青の項目にもアクセスできるように改変を行ってみよう。 
posted by Yasuski at 20:16| open.Theremin

Open.Theremin@チューニングとキャリブレーションのポットデータ

オシレーターのキャリブレーションモード専用のレジスタを組んで、チューニングとキャリブレーションのポットデータを分離した。

WS001159.JPG

同時に、モード変更の順番を、ピッチ(緑)→ヴォリューム(青)→波形選択(水色)の順番に変更している。

波形選択モードに関しては、他のモードの合間に挿入すると、便利かもしれないので、インターフェイスの変更を検討しよう。

追記:

スイッチの判定機構を間違えていたので修正。 

WS001160.JPG

Volumeは問題なく操作できるが、何故かPitchがアカンので、
今一度、処理ルーティンを精査中。
posted by Yasuski at 06:12| open.Theremin

2017年10月17日

Open.Theremin@GigaTrimをVariCapにリプレイスする

高価なGigaTrimを使用せず、多回転VRTでチューニングを行う方式に回路をリプレイスした。

WS001158.JPG

厳密には、実装スペースの限界から回路のグループ毎にオシレーターの周波数を決定するCの実装サイズが異なってしまうのが残念だが、これはあくまでも基板上の問題。 対象となるCのサイズを実装時に1206から0805に縮小してしまえば問題は解決する。

現行回路の評価次第だが、次期ロットはこの基盤を発注して実験を行うかもしれない。

adat回路が失敗した場合は、DACを複数個増設することになるだろう。

追記:

オプションのTOSLINKを装着する場合、回路に供給する電源ラインにLを入れ忘れていたのでこれを追加する必要がある。

WS001158e.jpg

まず、プリントされた電源ラインをカットし、切り離した回路にLを挿入する。 Lを経てデバイスに供給される電源ラインにコンデンサとバイアス用の抵抗を追加して作業は終了。

こちらは2ndDACを増設した場合のケース。 空きエリアだったTOSLINKの端子付近にMAX5541を追加している。

ID292withStereoOut.png

DACのデータ入力が浮かしてあるので、オプション装着時はMCUとの配線をジャンパ線で行う必要がある。
posted by Yasuski at 16:51| open.Theremin

Open.Theremin@発振器の相対誤差の問題

よくよく考えると、折角アナログ的な手法で、ピッチをセンシングしているのだから、アナログ的な手法でチューニングを行うのが筋ではある。

デジタル処理は、音源周りに限定すべきなのだろう。 

オシレーターにVariCapを使う設計の利点は、外乱に敏感なオシレーターの素子をシールド線で引き回さなくて済むところで、実際モダンな設計の短波ラジオは、これとマイコンを組み合わせて発振器の電圧制御を行っている。 

リファレンス用のオシレーターの安定度を上げるにはPLLの使用が望ましいが、片方の発振器にアンテナを繋いで不安定化しているので、相対的な安定度を考えなければならない。 リファレンス・オシレーター単体で安定度の向上を追求する意味は全く無い。

相対性の確立をつきつめていくと現行の設計には疑問があって、VariCapを積んでいる回路とそうでない回路の併用による誤差の発生が気になってくる。 将来的には双方のオシレーターをVariCapコントロールにした方が良いかもしれない
posted by Yasuski at 13:50| open.Theremin

2017年10月16日

Open.Theremin@オシレーターコントロール用のVRポットを追加する

ボディー上面に、オシレーターコントロール用のCVを調整するVRポットを追加した。

IMG_7710.JPG

VRに印加する電圧は3.3Vで、抵抗値が1/2のポイントでオシレーターのベース電圧になるようにDAC出力との調整を行う。 発振周波数の調整はVariCapとの兼ね合いがあるので、実測した結果からCの値を調整して擦り合わせていく。

CVinput.png

Volume側との混信を避けるため、Pitch側のLを2mHに増やして発振周波数を低い方に変更する予定。またVariCap搭載側をリファレンスに変更し、アンテナは固定LCのオシレーターに接続する。

IMG_7714.JPG

VRポットは左右のポジションを置換して、調整時にアンテナとポットを回す手の位置を出来るだけ離すことにした。

IMG_7715.JPG

ケース上面左側のPitch調整用ポットは3回転型なので、細かな調整を行える。 右側のVolumeを調整するポットは、1回転(未満)のVRを仮付けしている。

次のヴァージョンでは基板上に部品を追加する予定。

WS001157.JPG
posted by Yasuski at 18:50| open.Theremin

2017年10月15日

OpenTheremin@CV機能の追加を検討する

キャリブレーションを行う過程でVRに中点のオフセットを掛けることで、正負両方向のドリフトに対処できる事に気付いた。

掛けられるオフセットのレンジ設定についてはとりあえず2/300kΩを予定しているが、最終的にはドリフトの発生量から逆算することになるだろう。
posted by Yasuski at 18:42| open.Theremin

Open.Theremin@オシレーターの補正について

昨日、二時間ほど継続して行った OpenThermin V3 の実証試験に於いて、「楽器としての基本性能と限界」が明らかになってきた。 ここで整理のために、今回発覚した問題点をまとめておく。

まず、演奏を行っている2時間余の間、オシレーターのチューニングが全く安定しなかった。 電源投入後に発生する初期の変動は通電後約10分程度で収束するものの、そこからは常にピッチが上がる方向にドリフトがゆっくりとではあるが継続する。周波数カウンタでオシレーターの発振を測定していないので断定は控えるが、オシレーターの発振周波数は明らかに低下する方向にドリフトしている。 特にドリフトが顕著に大きくなるのは、限界付近までの高音程を長時間に渡りキープした時で、試しに右手の位置がアンテナ直近の高音域から、低音域に右手をスライドさせてみると、高音域にポジションを上げる前に確認していた最低音の限界域が明らかにアップしている。 高音域に限らず、演奏を長時間継続した場合も同様に最低音域が高い方にドリフトする。 ドリフトの原因はコイルの発熱の影響と予想しているが、これは発信器の機構上の問題なので、根本的な解決は難しい。 ドリフトはVolume側でも同様のパターンで発生しているので、やはり構造上の問題と推測せざるを得ない。

次に、AC駆動時に明らかに増加するポップ音の発生率と、左手の動きに連動して生じる独特な低周波ノイズの 問題を確認した。 低周波ノイズは電池駆動アンプの場合でも発生していたが、AC駆動時の場合、これが無視できないレベルまで増幅されてしまう。 対処法として考えられるのは電源部にリップル除去用の手当てを行うことだが、ひとまず電源平滑用の電解コンの容量をアップするところから対策を開始する。 ただ、電池/AC、何れの駆動形態においても程度の差こそあれリップルが確認できているので、この件は視点を変えて調査を行う必要がある。

最終的には、ソフトウエア側からの修正で誤魔化せるレベルを超えた時点でドラスティックにシステムの破綻が発生するのだが、先のトピックで述べたように、DACからVariCapを制御するルーティンはそれだけで12bit×2の通信タスクが生じるわけで、これは音声再生を行うために使用するDACとの通信帯域を限定することに繋がる。 通信帯域のボトルネックを避けるためにVariCapの駆動はキャリブレーション・モード内に限定しているのだが、二回目のキャリブレーションで修正を行う際に、ソフト上のドリフト対策として生成されたオフセット値が、そのままDACの制御値に反映されてしまうというバギーな仕様にハマって、二度目の修正は困難を極めることになる。 このような状況を避けるために、キャリブレーションを行う際は常に電源を落としてリセットを掛けているのが現状なのだが、PA接続時の事故を想定するとあまりにヤバ過ぎるバギーな仕様は改めた方が良いだろう。 が、それ以前の問題として冷静に考えてしまうと、そもそもこのような状況下でソフト側から外部のアナログシステムに介入する意義が全く認められないのだ。

オシレーター回路へのVariCapの導入はチューニングのインテリジェント化を狙ってのことと想像しているが、外気温の変化だけではなく、演奏の影響で発生する自己発熱による周波数ドリフトが疑われるシステムに於いて、自動チューニングは実効性が欠ける仕組みと判断して良いだろう。 そこで、根本的な解決策はあるのかというとV3基盤に依存する場合の選択肢は回路のリプレイス以外に思い付けないが、その実際的な手法は、DACに代わってVariCapを手動でコントロールするアナログな方法だ。 つまり、オシレーターをVRポットを使って電圧制御するしかないのだ。

WS001154.JPG

回路図を参考にすると、DACの出力に繋がる R4/R8 の端子をフローティングし、そこにVRで分圧した電圧を加える。印加する電圧レンジの調整が必要だが、これにより、非常にアナログ的な手法ではあるものの、より確実にそして直接的にオシレーターのチューニングと修正を行うことが出来る。 またC6/C13とRの結節点に新たにMix用のRを追加してDACの出力とアナログCVを合成する手法をとれば、適正な初期値を呼び出した後に電圧を印加してCの値を減少方向にコントロール出来るので、

WS001155.JPG

こちらの方法も是非検討していきたい。 その場合は、VRの中点から得られる電圧をミックスする抵抗値を調整してで周波数の可動レンジを決定すればよいだろう。
posted by Yasuski at 05:17| open.Theremin

2017年10月14日

Open.Theremin@試験運用のリザルト

今日の午後は2時間ほどぶっ通しでテルミンの運用試験を行っていたのだが、その間最後までオシレーターの周波数補正を行わざるを得なかった。 体感的に「高いピッチ」を発音する度にドリフトが拡大していく感触を得たことから、オシレーター回路内の”L”の発熱による影響が疑わしい。

オシレーターの他の構成部品を考えると、温度変化の影響を受け易い”C”に加えて更に”VariCap”の温度係数が影響してくる訳で、しかも”L”に関しては外気温以外に発振の影響による部品の自己発熱という動的なファクターが絡んでくる。 つまり、演奏の内容によってドリフト値が変動しかねないということで、これは楽器としての性能を考えると由々しき事態といえる。 

現在、周波数の修正を行う構造は、キャリブレーションモード内でオシレーターのVariCapに送るDACからの制御電圧を調整しつつ、通常モードではソフトウエア的にオフセット値を解消するという2段構えの構造なのだが、この部分の複雑さが逆に制御を難しくしている可能性もある。 通常モードからDACの制御を外すのは、DACへのアクセスタイムを削る意味合いもあり、この部分を修正するのは余り得策ではなさそうだ。 

結論は、ソフトウエアで辻褄を合わせることを諦めて、単純にバリコンで発振周波数を調整する従来のチューニング方法を選択するのが正しい在り方なのだろう。 VariCapを活かす場合は、VRによるチューニングが可能だが、この場合出来れば多回転タイプのものを選択すべきだろう。
posted by Yasuski at 21:05| open.Theremin

Open.Theremin@波形合成の実験

昨日の晩は波形の加算合成の実験を行っていたのだが、出力レベルのリミットでソフト・ディストーションが掛かる機構を追加したことが功を奏したのか、いきなりパッツンと逝く情況には陥らず過渡特性がマイルドになった。 フルヴォリュームに近くなるに連れて歪が増していく特性には慣れが必要だが、ヴォリュームアンテナ側の設定次第では、自由度の高い表現を行える可能性がある。

ノイズっぽい出力特性は、それが目立ちにくいSawtoothやHalfWaveTriangleなSine波との相性がよいようで、加算合成時のミックスバランスを間違えなければ、面白い音を作ることが出来た。 

波形の選択によっては逆相になるものがあって、これを積極的に使うことで、強烈なフィルター効果を得ることが出来るが、波形同士の相対的な関係に依存する現象なので、出来ればオシロスコープで波形を観察しながら編集を行った方が効率がアップする筈だ。

確かに、6波の相関関係を直感的に把握することは難しく、簡易タイプで良いのでオシロスコープの導入を行ったほうが良いのだろうが、問題となるのはそれを格納するケースの仕様だ。 

現在、試作品としてID-292を使用したものを製作中だが、OLEDパネルの実装スペースがギリギリで量産には向きそうにない。 最終的にはスペースに余裕を持たせられるHammond/1455シリーズ辺りを選択することになるだろう。
posted by Yasuski at 02:31| open.Theremin

2017年10月13日

Open.Theremin@Teensy3.2搭載の初期型が再起不能に陥る

今朝方、Teensy3,2を使って構築したテルミン開発用のプラットフォームが、修正プログラムをアップロードしたのをキッカケにご逝去された。 原因の詳細は不明。

最新のプログラムをオーバークロック仕様でアップロードした後に通電すると、LEDが文字通り白目を剥いたまま反応しない。 起動時のピポパ音も沈黙している。

Teensy3.2単体でチェックすると、ROMの内容を起動時に吐いているし、プログラムを書き換えてLEDチカも可能。 なにがどうなっているのか訳が解らないが、とにかく楽器が死亡したとしか言いようが無い。

このままでは故障の詳細が判らず、部品をサルベージしてオシロに化けさせるしか無いのだろうか? 幸い、Teensy3.2は試作中のオシロに必要なので、転用は可能ではある。

この機会に、旧型弾薬箱アンプと新型V3基盤対応テルミンのコンビネーションを試したが、妙なノイズがクローズアップされてしまって、イマイチ相性が良くない。これは、D-Classアンプのチョッパー周波数とテルミンのDACから漏れる高調波の相性と思われるが、LPFの部品係数を考え直した方が良い感触であった。

そういえば、以前にも白目を剥いて死亡したことがあったように記憶しているが、結局はマイコンを交換するしか無かったような。 最後にライヴで活躍できたのが幸いだったが、この楽器は退役させることになりそうだ。 

で、去年のことを思い出したのだが、故障の直接的な原因は処理能力をオーヴァーしたプログラムをオーバークロック仕様でアップロードしたことにあるようで、この行為がキッカケでMCUに搭載されているROMの領域を荒らしてしまったのかもしれない。

過去に似たようなトラブルが発生した時にプログラムを使ってROMを強制的にクリアしてなんとか復活させたことがあり、これは一度試す価値があるトラブルの対応法だろう。

追記:

ROM消去もクリアしているし、データの書込みも問題なく、シグナルトレースを行っても各ルーティンをちゃんとこなしているようにしか見えず、(ソフトウエア上の)LEDの点灯サインも出ているが、何れもMCUをハードウエアから切り離した単独の状態での反応で、ハードウエア接続後はRGBエンコーダが白眼を剥いてしまい、クリック等外部からのアクセスに対して一切の反応が無くなる。

この様子では、短絡等による原因でシステム全体の電圧が降下している可能性が大きくなってきたが、ハードの検査は億劫なので、このままパーツのサルベージを行いつつシステムをバラすことになりそう。
posted by Yasuski at 17:11| open.Theremin

2017年10月12日

Open.Theremin@半音階ドリフトの謎

昨日からテルミンの楽器としての運用試験を本格化しているが、例の半音階だけ音がズレる現象を考えると、ランダムな周波数の変動ではなく「ほぼ正確に半音分ズレる」ところに問題があり、これはバグの匂いがする。

プログラム上、音階の関係は半音単位で以下のように関数化しているのだが、

double pitch1 = 1.0600;
double pitch2 = 1.1236;
double pitch3 = 1.1910;
double pitch4 = 1.2625;
double pitch5 = 1.33823;
double pitch6 = 1.41852;
double pitch7 = 1.50363;
double pitch8 = 1.59385;
double pitch9 = 1.68948;
double pitch10 = 1.79085;
double pitch11 = 1.8983;


double pitchInc = 0.00006103515625;

これはあくまで基音に対して相対化された値であり、A=440Hzといった厳密なものではない。

音源の音程は、Wavetableを読みだすポインターにオーディオクロックの周期で追加される「データを読み飛ばす係数」によって決定される。 add_valというのがそれだが、そこにピッチの変動を掛けることで、音階を決定していく。

case 35: pointer = pointer + (add_val);
pointer2 = pointer + (add_val);
pointer3 = pointer3 + (add_val * pitch5);
pointer4 = pointer4 + (add_val * pitch7);
pointer5 = pointer5 + (add_val * pitch9);
pointer6 = pointer6 + (add_val * pitch11);
break;


一方、半音階に規定されない自由な音程関係をプリセットする機能はこのような形で実現しているのだが、、、

case 41: pointer = pointer + (tuner);
pointer2 = pointer2 + (tuner * (pot3a * pitchInc ));
pointer3 = pointer3 + (tuner * (pot3b * pitchInc ));
pointer4 = pointer4 + (tuner);
pointer5 = pointer5 + (tuner * (pot10a * pitchInc ));
pointer6 = pointer6 + (tuner * (pot10b * pitchInc ));
break;

この機能を選択し、pot_x を呼び出し、tuner が乗算された結果が”ゼロ”からそれ以上に転じた瞬間に、何故か変動が生じないはずの tuner * (potx * pitchInc) が加算されない pinter2 や pointer5 において音程が変化するのが謎なのだ。

追記:


今一度コードを解析した結果、pointerのデータを元にWavetableを読み込むルーチン

uint16_t offset = (uint16_t)(pointer>>5) & 0x3ff;
uint16_t offset2 = (uint16_t)(pointer2>>5) & 0x3ff;
uint16_t offset3 = (uint16_t)(pointer3>>5) & 0x3ff;
uint16_t offset4 = (uint16_t)(pointer4>>5) & 0x3ff;
uint16_t offset5 = (uint16_t)(pointer5>>5) & 0x3ff;
uint16_t offset6 = (uint16_t)(pointer6>>5) & 0x3ff;
                    
の ”後 ”に、ピッチの設定を行っていることが原因と判明した。 

対策は単純で、pointerの値からWavetableの読み出しを行うoffsetが確定する ”前” に switch/case を選択してしまえば良い。

追記2:

ついでに、pointerに行っていたbitshift命令で1bit分過剰にデータを削っていたことが発覚している。本来は2048ステップのところを1024ステップでデータを扱っていたわけで、大変にマヌケである。 修正後は周波数の再生レンジが広くなり、調整がやり易くなった。

追記3:

追試を行ったところ、若干のピッチドリフトが発生している模様。 つまり、処理に伴う負荷が影響しているものと推測される。
posted by Yasuski at 15:06| open.Theremin

2017年10月11日

Open.Theremin@トランジション・モード時に発生するピッチ変動の問題

今週は、テルミンの音量コントロールを改良しているが、トランジション・モードを選択した時に予期せぬ音程の変動が発生していることに気付いた。



音程の変動といえば、和音をプリセットするページで、パラメーターを呼び出す毎に全体の音程が下がる謎の現象を確認しているが、どうもそれに似た雰囲気のトラブルだ。

で、音程の変動が確認される情況は、パラメーターの初期値”ゼロ’が入力された時が怪しい。

試しに、"ゼロ"が入力される機会を調べてみたところ、トランジションを設定しているヴォリュームの変化カーヴと、、、・

Screen Shot 2017-10-11 at 1.47.08 PM.png

Wavetableのアドレスを指定するパートを見つけた。 余り無し=ゼロ なので、この部分には常に”1”以上を出力するように細工を行った。 同時に不感帯を設定して、ヴォリュームカーヴの変化が発生するポイントをズラしている。

Screen Shot 2017-10-11 at 1.46.07 PM.png

以上のように、Wavetableを含む音量コントロール関連のパラメーターから”ゼロ”を追放したところ、音程の変動は綺麗に無くなった。

ちなみに、この手当を行う前にオシレーターの発音を5音に制限してみたが、情況は殆ど変わらなかったことを記録しておく。
posted by Yasuski at 15:21| open.Theremin

2017年10月10日

open.Theremin@Volumeコントロールの改良について

Wavetableから変化量の推移を記録したカーヴを参照することで、より自然な音量のコントロールが行えるようになった。



ただし、トランジションコントロール時の段付きが復活している。 そろそろ処理能力の限界を超えているのかもしれない。 

ArduinoIDEは何をやらかしているかわからないところがあるので、より判り易い形で処理速度の向上を狙うため試験的にアセンブラコードの導入を試しているが、

WS001153.JPG

これが実際に関数を仕込んでみるとコンパイルが通らず、バグレポートを送れとのアラートが出てくる。 

が、これは過去の経験からバグではなく、用法を間違えている感じがしている。 

やはり別に簡単な検証用のプログラムを組んでみて動作の確認を行ったほうが良いのだろうが、アセンブラに関しては引き続き実験を行うとして、3.5を使用する環境に関しては音源を1つ減らす方向でも検討していくことになる。

posted by Yasuski at 20:07| open.Theremin

2017年10月09日

Open.Theremin@VolumeControler周りの問題について

8bit処理時代に感じていた不具合が段階的に軽減されたきたものの、VolumeAntの反応について常に不満を感じ続けていることもまた事実。

Open.ThereminのVolumeControlの構造について解析すると、まずハード面の違いはオシレーターの中心周波数が40kHz程下なこと位で、Pitch側と殆ど構造は同じ。 ソフト面も似たような構成だが、周波数カウンタでカウント=センシングされた値をMaxVolumeの規定値4095=12bit/FSから減算するところに違いがある。 つまり、センシングされる周波数の差分が大きくなるほど、音量設定のデータは低くなっていく。 センシングされた差分の最大値は予め4095にリミットされているので、マイナスの値は出てこない。

一方、オシレーターの周波数変化にはリニアリティーが要求されているために、当然ながらValueの変化もリニアになる。 が、これは音量をコントロールする数値変化に要求される変化のカーヴとしては頂けない。 弱音から一気に音量が増えてしまう感覚は、このようなシステムの在り方に起因している。

ここで、今一度整理することを目的に、現時点で追加した改良点を列挙しておく。

1) 処理ビットの幅を8bitから11bitに拡大。 

8bit幅ではどうしても「段差」を感じてしまうため、より細かな変化幅でドライヴすることが望ましい。 が、分解能が上がると、それだけ計算に必要な時間が増える。 ので、トレードオフとして11bit程度が妥当と判断した。

WS001152.JPG

2) フィルターの追加。 

レジスタを追加して積分を行い、細かな反応を地均ししている。

Screen Shot 2017-10-09 at 9.15.03 PM.png

3) オーバーフロー対策用のリミッターを追加。 

トランジションをコントロールした場合、いきなりデータがフルになる情況が発生するので、それを回避するための仕掛け。

WS001151.JPG

4) トランジション使用時のオーバーフロー対策として、ヴォリュームカーヴ設定ファイルの最大値を変更。

リミッターでは吸収されないレベルの変化幅の発生を予め予防するために、ピークの重複を見越してWavetableの最大値を設定している。

WS001147.JPG

5) FTMカウンターの分周率を1/2から1/4に変更。

差分のセンシングを行う場合、反応の速さとセンス出来る最低周波数はトレードオフとなる。低い方のセンシングを安定させたい場合は分周率を上げる方向で調整するが、遅延時間が大きくなると音響処理に使用出来る時間が削られてしまう。

WS001148.JPG

6) VolumeCounterから出力される16bitデータを右に1bit分シフト。

4bit分の不感帯を多少なりとも解消するための細工。 センシングと同時にInitialValueに記憶されるレジスタの変更を忘れずに。

WS001149.JPG

以上の変更を行っていたが、イマイチ効果が薄い。

そこで、Wavetable方式で、ヴォリュームカーヴを読み取り出力に反映することにした。

Screen Shot 2017-10-09 at 9.13.11 PM.png

これにはかなり効果があって、ピアニッシモ時の息継ぎ現象や、急峻な音量変化を抑えることができている。

ただし、妙にノイズっぽい音質の改善は進んでおらず、引き続き対策を考えなければならない。
posted by Yasuski at 18:47| open.Theremin