dacHandlerは、MCUに内装されているI2Sを使用せずに、オーディオ用のDACと通信を行う目的で開発したシステムで、MCUの外部に32bit✕32stepのレジスタ群を設置することで、諸々の制約が発生するライブラリやDMAに頼らずに、独自のタイミングで通信を行うことができる。 取扱うデータのフォーマットは出力先のDACに依存するために、予め2の補数にオーディオデータを変換しておく必要がある。
”2の補数”でオーディオデータを扱う記事を検索すると、対 Decimal / Binary 変換に関心が集中しているようで、Binaryから2の補数に加工する際のオーディオの出力制御に絡んだトピックを見つけることは難しい。
これは自分の検索能力(特に英語)が拙いことを踏まえても明らかな傾向だと思うのだが、流通しているオーディオ用ADCの出力が概ね2の補数フォーマットなので、それを踏まえた常識的な反応なのかもしれない。
さらに検索を行った結果、I2S/Raspberryに絡む記事が散見されたものの、ライブラリを介さずにデバイスを直結する場合に必要とされるプロセスに関して書かれた記事を発見することは遂に出来なかった。
さて、2の補数フォーマットのオーディオ・データを扱う勘所は、負極側の扱いとなるのだが、概念的に-1が-128より大きいと解っていても、最初は2の補数によって示される 0xff と 0x80 といった数値に実感が沸かないために、ゼロクロス時の不連続な表現に戸惑わされることになった。
つまり、-1と0の間には概念上の「壁」が存在するのだが、ここで実際にデータを掛け合わせてレベルを設定するタスクが絡んだ場合、まず概念上のゼロポイントをフルスイングする波形データの振幅の中点に設定して、波形データを極性で二分することが最初の工程となる。
重要なのは、出力の最終的なデータ幅(分解能)にデータが纏められるまでは、MSBに添付される極性を表す「符号」を決定してはいけないことで、この事に理解が及ばなかったために、相応な廻り道を強いられることになった。
実験の結果到達した加工のプロセスを以下に示す。

1)まず、音声データの極性を決定するためのゼロクロス・ポイントを規定し、ゼロポイントの上下でデータを分離する。
2)正極側のデータからゼロクロス・ポイントに規定した値を引いて、最小値を0に設定する。
3)出力レベルを決定するデータを正負それぞれのデータと掛け合わせる。この際に念の為桁上りを防ぐためのリミッターを添付してもよい。
4)負側のデータにはオフセットが生じるので、レベルデータのフルビットから設定する値を引いたものをオーディオデータのフルビット値に掛けることでオフセット値を生成し、これを負側のデータに加算して、嵩上げを行う。
5)11bit✕12bit=23bitの音声データが確定した後、DACの仕様で求められる32bit幅に合わせてデータを8bit左にシフトする。
6)最後に負側のMSBに極性のフラグを立てて、2の補数フォーマットへの変換が完了する。
後から振り返ってみれば、何ということはない常識的な手順を踏んでいるだけなのだが、工程6)でMSBに添付する「符号」の意味を読みきれず、24bit環境で極性を決定しようとしたことが、錯綜の原因となっていた。
以上、「解っている人達」にとっては自明のことをつらつらと書き綴って来たのだが、抽象表現に弱い自分は、実験を繰り返すことで、やっと理解を進めることができた。
追記:
2022年7月に、Transition をコントロールするデータ幅を12bitに拡張している。
http://audiohologram.sblo.jp/article/189696350.html