ディスクリプターのリングを作りDMAが動くようになったのですが、割り込みでchn_intr()を呼び出すと、DMAがunder runしてしまいます。
割り込みはDMAでバッファが空になり、再充填のために呼ばれます。
いろいろデバッグライトを入れて、確認したところ割り込みでchn_intr()で1つバッファを埋めてる間に3つ空になっています。これでは間に合うわけがありません。
chn_intr()はsys/dev/sound/pcm/channel.cにあります。
chnで始まる関数はchannel.cでsndbufで始まる関数はbuffer.cにあります。pcmインターフェースは名前の付け方に一貫性がない感じがします。
処理は
chn_intr() -> chn_wrfeed() -> sndbuf_feed()
と行われます。sndbuf_feed()の中の、
do {
cnt = FEEDER_FEED(feeder, channel, to->tmpbuf,
min(count, maxfeed), from);
if (cnt == 0)
break;
sndbuf_acquire(to, to->tmpbuf, cnt);
count -= cnt;
#ifdef SND_DIAGNOSTIC
cycle++;
#endif
} while (count != 0);
FEEDER_FEEDで大きく時間を使ってしまっているようです。FEEDER_FREEDはkobj interfaceでCore AudioでいうところのAudio Unitのようなもので、フォーマット変換などをしているようです。
小言ですがFEEDER_FEEDも馬から落ちて落馬してみたいで、センス悪いですね。
なんか回避策ないかな。。。
よくよく考えてみると、割込みハンドラの中でフォーマット変換するってありえない。
以下でログが出るようになります。
% sudo sysctl hw.snd.verbose=4
/dev/sndstatにも情報が追加されます。