大昔、MS-DOS上でCで書いたプログラムを走らせていて遭遇するエラーは大体次の2つだった。
Null Pointer Assignment
Division by Zero (Divided by Zeroだったかも知れない)

 

今はもっぱらLinux上で書いているのだが、何か問題があると
segmentation fault(せぐめんてーしょんふぉると、セグメンテーション違反)
と宣って終わることが多い。というか、ほとんど全部。

 

何かのライブラリを使っていると、比較的丁寧なエラーメッセージを吐いてくれて助かることがある。

このあいだ遭遇したのは double free というものだった。開放したポインタを再度開放していたのですね。

 

PC上のプログラミングであればデバッグはそれ程難しいものではないが、マイコン相手となるとそうもいかない。

ソフトウェアレベルではリストファイルとマップファイルに書かれていることが手がかりの全て、ということも多い。

 

ハードウェアのバグというのもある。まあ、ブレッドボードで遊ぶレベルであれば、この手のバグは設計図に隠れているのがほとんどである。

 

 

アンダーで撮った写真を "Lightzone"というレタッチソフトにある「ゾーンマッパ」という機能で露出調整してみました。暗室作業経験のある身としては大変わかり易い機能ではありますが、暗室の苦労をPC上で再現してどうするのか、という気がしないでもありません。

 

 

 

ここ暫く、R8C/M12Aを使って受信機向けのディジタルオーディオフィルタを作っていました。なにせ何も判らないところから始めたので、なかなか思うように進みませんでした。ネット上の情報だけでは理解できず、久しぶりに本屋で参考書を買ってきたくらいです。

 

用いたフィルタは双2次フィルタと呼ばれるものです。演算負荷が軽い割にそれらしい効果が得られます。これで遮断周波数を変えたパラメータをいくつか用意して、動作中に切替のできるLPFを作りました。当初、Peakingフィルタを用いてBPF的な動作を考えていたのですが、どうしても歪んでしまい今回は諦めました。代わりに利得をマイナスに振ってノッチ的な特性にしたものを入れています。これで遮断周波数を3kHzとか5kHzにすると、全体でLPFに近い特性になります(なるはず)。

 

例によって測定器がないので自分の耳だけが頼りです。FMラジオの出力を通して試した限りでは、期待した動作が得られています。

S/Nを稼ぐためにAD変換器の出力10ビットを全て使っています。また、出力側のPWMの最大幅は1000クロック(CPUクロック20MHz時)で、こちらは10ビットに僅かに足りません。これらから、音声入力レベルは結構微妙な調整が必要なのでは、と思います(比較対象が無いので実はよく分かっていない)。

 

M12Aはアナログ電源端子(AVCC,AVSS)がディジタル側と共用になっており、ノイズの混入は避けられないはずですが、実際に聞いてみるとそれ程でもありませんでした。バッテリー駆動なら実用レベルと思います。むしろ演算誤差からくるノイズの方が問題だと思います。

 

主な仕様


サンプリング周波数 20kHz
ビットレート 10ビット
音声出力 1W
入力 4.8V 9mA (無信号時)

 

CPUの処理能力の割にサンプリング周波数が高めなのは、16kHzではモスキート音が取りきれなかった為です。放送やアマチュア無線の電話通信を聞く程度なら16kHzで充分なのですが。

 

 

ハードについて


ディジタル・アナログ混載は余り経験が無く、分からないことだらけです。AD変換入力とか適当過ぎる気もします。
PWM出力(TRCIOB)は当初オープンドレインにして4.7kで吊っていたのですが、ポート出力のみでドライブできそうだったので外しました。これが適切かどうか分かりません。
AFアンプは手持ちの都合でHT82V739を使いました。この石はCEを持っているので使ってみました。あくまでもCEでありミュート端子では無いためこのままでは起動時のポップ音を取り除くことはできません。データシートによれば、ディセーブル時に入力端子を1/2VCCをしておいて一定時間経過後(VREFのCに依存)CEするのが手順らしいです。しかし入力端子はCで直流を切って使うのがもっぱらなので、この手順通りとするにはひと工夫必要になると思います。

 


回路図


コードについて


取り敢えず動くレベルなので全体を晒すのは控えます。以下に備忘録的に、部分を示します。

 

PWM部分です。サンプリング周波数が20kHzなので、処理で使えるのは最大1000クロックですが、割り込みルーチンに分岐してくるまでに20クロック必要です。

フリーランニングカウンタを回していますが、これはフォアグラウンドでの計時用です。切替スイッチ(押し釦)の検出をプログラムで行っていた時の名残りです(後述)。

 

void TIMER_RC_intr(void)
{
    asm ("    .equ    ADCON0, 0x9e"     );
    asm ("pushm     r0,r1,r2,r3,a0,a1"  );
    asm ("add.w     #1, __timer_counter");  // フリーランカウンター用のカウンタ
    asm ("jsr.a     _adc_read_quick"    );  // jsr.a 9 rts 6 計15ステート
    asm ("mov.b     #0x01, ADCON0"      );  // 次回分のAD変換を開始
    asm ("mov.w     r0, r1"             );
    
    asm ("jsr.a     _biquad"            );

    asm ("__TIMER_RC_intr:"             );
    asm ("mov.w     r0, 0xf0"           );  // 書込先はDレジスタ、Bレジスタのバッファに設定
    asm ("popm      r0,r1,r2,r3,a0,a1"  );
}

 

フィルタ演算部です。R8C/M12Aには積和命令があるのでコードそのものは簡潔なものになっています。
当初FIRフィルタ用に用意したブロック転送ルーチンをコールしていたのですが、転送数が少ない為mov命令に変更しています。

 

_biquad:
        pushm   r1,r2,r3,a0,a1
        mov.w   #_filter_buff, a0
        mov.w   _biquad_const, a1
        mov.w   r1, [a0]            ; v -> filter_buff[0]
        mov.w   #0, r0
        mov.w   #0, r2
        mov.w   #5, r3
        rmpa.w

        shl.l   #-8, r2r0
        shl.l   #-5, r2r0
        
        ;~ mov.w   #5, r1
        ;~ jsr.w   _buff_shift

        ; 5段しかないのでブロック転送しない
        mov.w   #_filter_buff, a0
        mov.w   a0, a1
        mov.w   2[a0], 4[a1]        ; filter_buff[1] -> filter_buff[2]
        mov.w   [a0], 2[a1]         ; filter_buff[0] -> filter_buff[1]
        
        mov.w   6[a0], 8[a1]        ; filter_buff[3] -> filter_buff[4]
        mov.w   r0, 6[a0]           ; output -> filter_buff[3]

        popm    r1,r2,r3,a0,a1
        rts

 

 

フィルタ係数


PC上で特性を計算し、実際にwavファイルを通して音を確認してからR8Cに持ってきています。

 

//lowpass 1300.000000[Hz] Q:1.400000
static int16_t biquad_const_lpf1300[5] = {
        (int16_t)(0.036014*(1<<13)),
        (int16_t)(0.072029*(1<<13)),
        (int16_t)(0.036014*(1<<13)),
        (int16_t)(-1*(-1.607503*(1<<13))),
        (int16_t)(-1*(0.751561*(1<<13)))
        };

 

上記係数を必要なだけ用意して配列にまとめておいて、別ルーチンで切替ています。

 

int16_t *biquad_const;
int16_t *biquad_table[] = {
            biquad_const_lpf1300,   // default
            biquad_const_lpf2700,
            biquad_const_lpf5000,
            biquad_const_bpf0880,
            biquad_const_bpf5000,
            biquad_const_bpf8000,
            biquad_const_lpf0660
         };

 

void biquad_setup (uint8_t n)
{
    if (n > 6) n = 0;
    di ();
    biquad_const = biquad_table[n];
    memset (filter_buff, 0, sizeof(filter_buff));
    ei ();
}

 

void filter_mode_next (void)
{
    filter_mode++;
    if (filter_mode > sizeof(biquad_table)/sizeof(biquad_table[0])) filter_mode = 0;
    biquad_setup (filter_mode);
}

 

切替が filter_mode_next と biquad_setup の2段構えなのは、当初biquadとは別に、窓関数を適用したFIRフィルタも使っていたからで、係数だけではなくフィルタルーチンの切替も必要だったことによります。
FIRフィルタは(処理時間の限界から)フィルタ長を短くすると特性がパッとしなかったので、取り外しました。


フィルタの特性切替は押し釦を押す毎に順に遷移するようにしています。フォアグラウンドでポートを読んで動かしていたのですが、R8C/M12Aにはキー入力割り込み(立ち上がり、立ち下がりを検出できる)があるので、割り込みルーチンに変更しました。プログラムはとても簡単になりましたが、ボタンスイッチのチャタリングをどうするか、何の配慮もありません。

なお、割り込み優先レベルはPWMより上にしないと動作しません。
 

キー入力割り込みのエントリーは参考にした開発環境には用意されていなかったので、自分で書き足しています。

 

void KEY_INPUT_intr (void)
{
    filter_mode_next ();
}

 

フォアグラウンド部分ですが、初期設定終了後は無限ループしているだけです。これによりCPUリソースの殆どをフィルター演算に費やすことが可能です。

 

 

 

参考・引用URL


R8C開発環境など
https://github.com/hirakuni45/R8C
双2次フィルタ
http://vstcpp.wpblog.jp/?page_id=523
http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt

 

 

参考文献


はじめて学ぶディジタル・フィルタと高速フーリエ変換
三上直樹,2005 CQ出版社

 

LinuxMint18.3のリポジトリにあるのはちょっと旧いので、flatpakから入れてみたのだが起動しない。

 

端末から起動してエラーメッセージを見てみたら、「gnomeがないよーん」とのこと。

 

さしものflatpakも、PCのオーナーに黙って別のDEをインストールする等という暴挙は控えたようだ。

 

 

というより。

 

darktableって何時からgnome必須になったんだろうね。ウィンドウ制御とか最初から変態なところはありましたけど。オープンソースでそこそこ使える現像ソフトだったので個人的には残念。まあ、新しいカメラに対応しなくなったら自分で対処すればいいだけなんですが。

 

ああ、アドビ以外のフォトツールなんて誰も真面目に使わないですか、そうですか。そうかも知れませんねえ。

 

自分宛てメモ

 

初心者には混乱の元、新しいパッケージシステム flatpakを試す。

 

LinuxMint18では最初から対応しているので、ソフトウェアの管理からflatpakを選んで実行すれば良い。

 

試しにgimpを入れてみる。事前に、インストールしてあったgimpはremoveした。
flatpakに用意されているのは2.10である。LinuxMintはポイントリリースで新し目のパッケージを使うにはppaを探すか、自分でビルドしかなかったので、flatpakで導入できるのはいいかも知れない。

 

但し、ダウンロードにはかなり時間がかかる。

 

関連ファイルは/var/libとかに格納される模様。詳しくは調べていない。

 

 

なお、gimp2.10ではLinuxMint18.3のibusが使えなかった。コンテキストメニューからinputメソッドをXに切り替えれば入力できる。

 

 

追記

画像を追加。

gimpに続いて Spotifyを試してみたがインストールに失敗する模様。途中で回線が切れた可能性もあり。


参考URL
http://gihyo.jp/admin/serial/01/ubuntu-recipe/0513

自分宛てメモ


症状

 

bluetoothを使ってスピーカーと接続中、PC側をサスペンドさせた後、復帰させるとスピーカーが認識されない。
デバイスを削除して最初から登録しなおうとしても無視される。

blueberryの再インストールでもこの状況は変化しない。

 

 

とりあえずの対策

 

blueberryをremoveして代わりにbluemanをインストールする。

 

 

その他

 

blueberryはLinuxMint純正なので外したくない一方、UIが最近のGnome準拠でXfce4のテイストとは微妙に合わないことも確か。
なお、blueberryはGnome-bluetoothに依存している。

 

 

ソースはここ。
https://github.com/linuxmint/blueberry

自分宛てメモ

 

今までまじめに取り組んでこなかったので。

 

固定小数点形式


有限長のビット列に整数部と小数部をもたせたもの。境目となる小数点は固定。
例えば符号付き16ビット固定小数点で、符号1ビット整数部2ビット小数部13ビットに振り分けた形式をQ13とか呼ぶらしい。
整数部が2ビットしかないので0〜±4未満までしか格納できないが、これでも円周率や三角関数あたりならそれなりに使える、のかも知れない。

 

 

浮動小数点形式からの変換

 

単位1を乗じて溢れた桁は捨てる。即ち、Q13なら(1<<13)を乗じてキャストする。
int16_t n = (int16_t)(3.141592 * (1<<13));

 

 

丸め(四捨五入の類)

 

10進だと5がしきい値で四捨五入となるが2進数なのでその桁のビットのオンオフを見るだけである。
n += n & (1<<12); // 小数第1位を見る
小数第1位で丸めると四捨五入になる(この桁は固定2進では1の2分の1、即ち0.5)が、他の桁だとそうはならない。

 

 

小数点の位置

 

乗算・除算の時、10進数で筆算する時と同様に小数点の位置について常に留意しなくてはならない。

 


10進表記を得る

 

まず、絶対値にして符号をはずす。~(n-1)
次に整数部と小数部に分ける。が、実際はビットシフトで取り出すだけである。

 

整数部
1の位から求める
10で割って余りを格納する。
商が10より小さくなるまで繰り返す。

 

小数部(小数第1位から求める)
10を乗じて積の整数部分を格納する。
小数部が0になるまで繰り返す。

 

 

いろいろ弄って判ったのは、

  • 小数部は桁数の割に精度がでない。Q13で3桁程度。(16ビット符号付き整数では凡そ±32000、16ビット符号付きQ13だと整数部は±3だから、小数部3桁はだいたい合っている、と思う)
  • 10進変換とかの変換がものすごく手間。
  • 小数点の位置を常に意識しなくてはならない。

一方、

  • いわゆるキャストは簡単かも知れない。
  • 同様に整数×固定小数の計算は簡単である。但し桁溢れに注意しなくてはならない。

 

 

自分宛てメモ。

 

多くのメディアプレイヤーは、dbus経由でのリモートコントロールができるようになっている。

 

MopidyにはMopidy-mprisというプラグインが用意されているのだが、うまく機能しないようだ。

 

 

LinuxMint18での様子。曲名は正しく表示されている。しかし再生中にも関わらず、コントロールボタンはそのまま。トラックの移動もできない。

 

debianでは停止はできたが、それ以外は不可だった。

 

なお、見た目はよく似ているがLinuxMintとdebianとでは動いているUIが異なる。LinuxMintはUnity由来のindicator-soundというもの、らしい。debianのほうはxfce4のパネルプラグインである。

 

ドキュメントに従ってpython(python2.7のシェル)から少し操作してみたが、仕様通り制御できるようだ。であれば、UI側(xfce4-pulseaudio-plugin等)を弄らないとならない。

 

LinuxMint18では、このサウンドメニューの登録内容は dconf-editorで参照できる。(com->canonical->indicator->sound)

例えば表示したくないプレイヤーはblacklisted-media-playersに記述する。debianでは試していない。

 

LinuxMintでの該当パッケージはこの辺(違うかも知れない)

indicator-sound
indicator-sound-gtk2

 

ソースを眺めてみたが、うんざりしたので眺めただけで終わる。

 

LinuxMint18にて、xfce4-pulseaudio-pluginが代替にならないか試してみたが、0.2.4はプレイヤーの制御ができなかった(上記indicator-soundをアンインストールしてから、xfce4-pulseaudio-pluginをリポジトリから入れた)。 0.3系は0.4系と同じくgtkのバージョンが合わずにビルドできない。

 

indicator-soundはtrusty以降、大きな改変はないように見える。

 

 


Search

Calendar

S M T W T F S
     12
3456789
10111213141516
17181920212223
24252627282930
<< June 2018 >>

Archive

Mobile

qrcode

Selected Entry

Link

Profile

Search

Other

Powered

無料ブログ作成サービス JUGEM