SSブログ

モノレールとか、ライブの席ガチャの話。 [その他]

 RP2040の実験は進んでいますが、リピート再生するとか、フローにするとかの段で、音のところにこんなバグがあるから直してみたいなところをこまごまとやっているので、ソースとしてお見せするものはありません。
 Nagodenさんから、RP2040用のデコーダ開発ボードが届きましたので、ブレッドボードは卒業して、そっちで開発をやっていこうと思います。
DSC03573.jpg

 と、これは今回の本題ではなく、今日は声優のライブに行っていました。ZeppHanedaでやっていたのですが、浜松町からモノレールで行きました。神奈川県民になってから、羽田空港へは、京急や高速バス、車なんかで行っていたので、なんか、乗るのは20年ぶりぐらいでしょうか?
 モノレールの軌条は古びていましたが、車両の速度計とかが液晶で新しいことに驚きました。
IMG20220130132901.jpg

 そして、オミクロン株のせいでとても空いていて、並ばずに運転席後ろに陣取れました。
IMG20220130131256.jpg

 で、ZeppHanedaから羽田空港の端の方を見ると、なんか飛行機がたくさん止まっていました。航空会社大変そうと思いました。
IMG20220130163440.jpg

 SelectionProjectというアニメのライブを見ていました。メインの楽曲の音域が広くてよいし、物語も面白かったので、見に行くことにしました。
IMG20220130141745.jpg

 さて、で本題です。ライブの席です。
コロナ禍になってから、立ち見ライブがなくなり、基本的に席があるようになりました。
ライブの席は抽選ですが、自分の席が悪いと、なんか、関係者はいいところに座っているとか、ファンクラブの偉い人だと前にいるんじゃないかとか、なんか思ってしまっていました。
どうなのかを確認すべく、ファンクラブに入っているもの、入っていないものも含めて、一昨年9月からから今年の1月まで、行った11件のライブについて、会場を正規化(縦方向は1階、2階、3階で連続して数えて正規化。一番前を1列目とする。横方向は座った列で左から正規化)したときにどういう風に偏っているかを見てみました。縦も横も正規化後の値が0.5になると、真っ当に抽選されているのねと考えられます。
で結果は以下の通り。
ライブの席について.png

縦は0.49で、1階、2階、3階を連続で考えた時に、ほぼ前後の真ん中が当たっている。横方向は0.44で、中央より少し左側が当たる傾向があったとなりました。
 席ガチャとして、損していないこと(当たっているのがいつも後ろの方じゃないこと)がわかって私は満足でした。
 それでは。

 
コメント(0) 

RP2040で音の再生実験 その3 [DCCデコーダ]

 気づいたら、1月も半分が終わっていますね。昨日はトンガの噴火が原因で、携帯から津波注意報が何回も流れていたようですが、私は気づきませんでした。理由は、ハーゲンダッツのラムレーズンを半分食べたのですが、アルコールがきつすぎて、寝込んでいたせいです。
 さて、RP2040での音の再生実験ですが、細々と続けています。(時間はすごいかかっています)
 動画として見せられるようなものはありませんが・・・。
DSC03571.jpg

やることは、
(1)PWMレジスタにDMA伝送する機能の追加。
(2)DMA用のバッファ(0.5秒分x2?)の定義の追加、バッファに書き出す処理の追加(今の割込みごとを、0.5秒分まとめてガツンと書くなど)
(3)LittleFSでのサウンドデータアクセス
でしたが、もちろん全然できていません。

 前回、(3)をやってみたものの、LittleFSでデータアクセスすると、処理量が増えるためか、同時発音が増えるとともに、音が揺れて遅くなるという現象があり、オシロで見ていてもPWM変更の割込みがずれまくります。
 で、原因はタイマーでした。
https://github.com/khoih-prog/RPI_PICO_TimerInterrupt
を使っていたのですが、もしかしたら使い方が悪いだけかもですが、割込みの呼ばれ方が、割込み処理が終了したら、XX us後にまた割込みが入るというもののようで、いろいろと処理が立て込んでくると、音用のサンプリングクロックが遅くなっていたようでした。
 調べていったら、もともとpico SDKにある、repeating_timerで十分で、
https://qiita.com/keyyum/items/3ce448c098c546dced20
に、わかりやすく書いてありましたが、-の値を入れると設定したタイマー周期で呼び出してくれることがわかりました。音も揺れなくなったし、コンパイルのWarningも出なくなったし、早速乗り換えました。
 https://raspberrypi.github.io/pico-sdk-doxygen/group__repeating__timer.html

 メモですが、デバッグしているときに、割込みに時間がどのくらいかかるのかというので、Arduino標準のdigitalWriteを使ってPinに出力を出してオシロで見ていたのですが、RP2040には、gpio_putという高速な命令があります。
一回の時間を計ってみたら、
digitalwrite:672ns
gpio_put:39ns
と17倍速いです。
 というかDigitalWriteを使うと、割込みの時間を計っているつもりがdigitalWriteの時間を計っているような状態になっていました・・・。割込み内の処理(PWMの切り替えとBuffferの切り替え)は
500ns~600nsぐらいで、なんか工夫しないでも十分速いです。

 次に、音のRepeatの話です。Esuと同様のものを目指すなら、音が終了した後に継ぎ目なく、次の音を入れないといけませんが、そこをBufferでとなると、配列のどこからどう入れるかというので、音の継ぎ目が・・・と試行錯誤しながらできました。順序回路で作り直しました。44KHzでも、サイン波のなかに、1個だけ唐突に0とかが入っていると、継ぎ目音として聞こえます。
 ということで、現在、の出来は、
・100ms周期程度のバッファ(Ach,Bchの2ch)
・モノラル同時8音の発声
・44kHz 8bit(DAC(PWMだけど)を10bitとしているので、元音は8bitでよいのかなあと思っている。44kHzなら125MHzなので、11bitぐらいまでなら可能。I2S使うなら16bitも可能かと思うけど)
・同じファイル/違うファイルで継ぎ目のない、継ぎ目再生
が可能となりました。
次は、
・フローファイルに基づいて、音をだす(警笛のStart,Repeat,Endみたいなところ)
・各音のボリューム機能( interp機能でとても速くできそう。)
https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware__interp.html
・音階を変える機能(できると、疑似音の和音での遷移ができるが、必要かどうかは不明)
・べた書きしたもののクラス化。
あたりです。

 今回のスケッチになります。
https://desktopstation.net/wiki/lib/exe/fetch.php/timer_test2_752_31.zip
 なお、前回までA0ピンにPWMを出していたのですが、デバッグ中の不注意で12Vを入れてしまい、A0~A3が死んでしまいましたので、現在D4に出しています・・・。
 あと、Core1で実行すると、グダグダになります。(割込みとかも守られないし、それに合わせて音もとぎれとぎれ、・・・。なぜでしょう。)

(1)、(2)のDMA関係はArduinoでのPIOのコンパイル環境がまだなさそうですので、誰かが作ってくれてからにしようかなあと思います。
 
コメント(0) 

RP2040で音の再生実験 その2 [DCCデコーダ]

 今日は箱根駅伝でした。沿道での感染はお控えくださいと主催者が案内していたような気がするので、見に行きませんでしたが、テレビで見ると、観戦者がいっぱいですね。まあ、オミクロン株って重症化しないようですし、リスクは低いってことですかね。
 で、本題ですが、年末に、やあさんさんから、以下のメールが・・・。面倒なので、ほぼ原文を書いてしまいますが、
ーーーーーーーーーーー
RP2040となり機能が増えているので、以下の2つの対応を順次、やっていければと思ってます。
【DMA伝送】
(1)PWMレジスタにDMA伝送する機能の追加。
(2)DMA用のバッファ(0.5秒分x2?)の定義の追加、バッファに書き出す処理の追加(今の割込みごとを、0.5秒分まとめてガツンと書くなど)
→割込みごとにPWMを書いているとCPUが食われるので、それを自動化する。DMA化することで同時発音数をさらに増やせるのではと。
あとのちのちのサウンドシーケンス(LokProgrammerのブロック図の状態遷移の実行)を実装するには必須になります。
【ファイルシステム対応】
(3)LittleFSでのサウンドデータアクセス
(4)LittleFSのファイルシステムに置くバイナリデータの作成ツールDSwav2の修正、バイナリ出力機能の追加(やあさんさんの仕事です)
ーーーーーーーーーーー

で、音声ファイルを16MByteも入れられる、Nano RP2040も送っていただいたので、さっそく実験です。
DSC03567.jpg

 (1)は難しいので、(3)、(2)の順に進めています。
 まず、(3)「LittleFSでのサウンドデータアクセス」ですが、1音だと、事前にファイルをオープンして、割込み中にファイルアクセスしてもとりあえずは音が出ましたが、複数音だと、うまくできませんでした。ということで、LittleFSを使ってのファイルアクセスはできましたが、現状のPWM割込み部分にすべて詰め込もうとすると、全然ダメです。
 次に(2)「DMA用のバッファ(0.5秒分x2?)の定義の追加、バッファに書き出す処理の追加(今の割込みごとを、0.5秒分まとめてガツンと書くなど)」ですが、最初リングバッファ作って・・・と半日ほど考えましたが、なんか良い案が思いつかずに眠気だけが出てきてたので、それはやめて、字面通りの方法をとることにしました。ただし、現状は以下のいくつか制約付きです。
・もちろんDMA非対応です。
・バッファの最初からしか音は鳴らせない(将来的には、オフセットをつけて、バッファの途中からならすことも考えようかとは思う)
・バッファの途中でファイルが終わったらあとは無音(そのうちリピートモードを実装しようかとは思う)
。音のchは6chとする(For文を追加するだけで処理時間が間に合えば音の数は増やせるが・・・)
 スケッチです。
https://desktopstation.net/wiki/lib/exe/fetch.php/timer_test75.zip
 まあなんとなく作れましたが、音の周波数やバッファの大きさによって、制御がバグったりしたので、PWMの割込みと、バッファ制御計算部分にどのくらいの時間かかっているのかオシロで確認しました。
 ところで、PWMの制御は、bool TimerHandler1(struct repeating_timer *t)
で行っており、中身はバッファA、バッファBの切り替えと1byteずつ音を出していくという作業をしています。
 また、バッファ制御計算部分は、void manage_wave()
で、行っており、この関数はLoop()から呼ばれ、バッファが切り替わっているフラグをつかんだら動きます。各chについて音を鳴らすフラグが立っていたら、音をコピーし始めます。バッファ分だけファイルからPWMのバッファへコピーします。次に呼ばれたときに音の再生が終わっていなければ、またバッファ分だけコピーします。

 で、まずはPWMの制御がどのくらいの時間かかっているのかオシロで確認しました。
DSC03569.jpg

 デバッグ用に出力ピンを設定して、黄色い波形のパルスが立っているところがPWMの制御を行っているところで、1.13us程度で終わっています。ただし、このインターバルに問題がありました。
 なんか、踏切の音は低いし、車内放送の声が低くて暗いなと思っていたら、出力周波数が微妙に低かったです。
 Setup()のITimer1.attachInterruptInterval(TIMER1_INTERVAL_us, TimerHandler1);
の、TIMER1_INTERVAL_usで割り込みのインターバルを設定しているのですが、実出力からみると、+5usのインターバルになるようです。インターバルは下記で設定しているのですが、-5usするように直しておきました。これで、車掌さんの声もやる気がみなぎるようになりました。(最初の方の#define)
//44k 22->17
#define TIMER1_INTERVAL_us 17
//32k 31 -> 26
//#define TIMER1_INTERVAL_us 26
//16k 62 -> 57
//#define TIMER1_INTERVAL_us 57
//8k 125 -> 120
//#define TIMER1_INTERVAL_us 120

 次に、バッファ制御計算部分ですが、こちらは、
void manage_wave()で行っています。
 こちらもデバッグ用に出力ピンを設定して、オシロで青いパルスが立っているところが処理中です。
 バッファは8KHzの時に1024Byteとして、一秒に7回ぐらいは反応してくれるようにしております。
 バッファ数は下記で定義しています。(最初の方の#define)
//#define BUF_LENGTH 32768
//#define BUF_LENGTH 16384
//#define BUF_LENGTH 8192
#define BUF_LENGTH 4096
//#define BUF_LENGTH 2048
//#define BUF_LENGTH 1024

また、周波数によって、読み出すファイルを変更しています。(Setup()内)
//String dir = "/8kHz_8/";
//String dir = "/16kHz_8/";
//String dir = "/32kHz_8/";
String dir = "/";
 ルートフォルダに44KHz版を入れています。

 この時、同時発音数を振って、処理時間のパルス幅を確認した表が以下になります。
データ数と処理時間.png

 44KHz、バッファサイズ4096で6音同時に出したとき、35.1ms処理にかかり、インターバルに対する処理の占有率は32%程度となります。(ただし、この後に、PWM制御の割込みインターバルがおかしいことを見つけたため、もう少し占有率は高いかも)
 まあ、まだバッファ制御計算部分は適当に書いていて、速くできそうな感じはあるので、あまり気になるところではありません。

 あと、波形を見ていて気になったのが、音が揺れることがあるのですが、PWM制御の割込みを見てみると不安定です。黄色いパルスで真ん中のパルスでトリガーをかけてそろえているが、右のパルスが二重に見えている→パルスが揺れている。
クロックがふらつく.jpg

 なんか、バックグランドでこそこそ他の処理が動いている感があります。
 例えば、今回のスケッチに入れているvoid serialEvent()
 をトリガーに確認してみると、その前後で、PWMの割込みが数クロック消えるのが見えました。
 また、Core1は使っていないからいいかなあと思って、Setup1(),loop1()にスケッチを移してみてみたら、PWM制御の1.13usが大きく間延びすることもあるなど、やばそうな現象が見られました。
 まあ普通に考えて、割込み内では、ほかの割込み禁止!の命令を入れるべきだよなあとそういえば思い出しました。なんて命令だろう・・・。
 PWMのところはPIO化か?ちょっと敷居が高そうだけど、そのうち。
 
 今後ですが、16bitのWav対応、音の切れ目ないリピート、二つの音をシームレスにつなげる方法などをやっていこうかと思います。

コメント(0) 

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。