MachiKaniaで和音出力(ちょっと失敗編)
2016年6月5日
PIC32MXは、コンパレーター用のD/Aコンバーターを内蔵している。以前、NTSCビデオシグナルの作成用に使えないかと色々調べた時、データーシートにsetting timeが10 μseconds(100 kHz)とあるのを見て、MHz単位でのシグナル変化が要求されるビデオシグナルには使えないことを知り、諦めた。
他方、100 kHzのsetting timeは、音声出力には十分の筈である。CDのサンプリングレートである44.1 kHzを、超えている。この機能を用いて、PIC32MX / MachiKaniaで音声出力が出来ないか、調べてみた。
CVrefoutは、28ピンのPIC32MXでは、25番ピン(RB14)に出力できる。MachiKaniaでは"Fire"ボタンの入力に用いられているものの、テスト目的であれば、ボタンを押さなければ出力にも使えるはずである。ここから、トランジスターのベースにつなぎ、エミッターフォロワーにして、スピーカー(もしくは、TVの音声入力)につないでみた。
CVRCONbits.CVRR=0とすると、0.83Vから2.37Vの間で、16段階の異なる電圧を出力できる。トランジスターで電圧低下が起こるが、出力電圧は直線的に変化することが期待できる。
ソフトウェアとしては、タイマーで割り込みを15769 Hzで掛けた。MachiKaniaのNTSCビデオシグナルと同じ頻度である。従って、音声のサンプリングレートは、この速度になる。WAVファイルをサンプルレート16000 Hzで準備し、このファイルを再生する形式とした。レートに若干のズレ(1.4%)があるが、音楽家でもない限り、違いはほとんど分からない筈である。テストの結果は、下記の動画の通り。
うーん、良い線行っているのだけれど、雑音がひどい。低音はいい音が出ているが、高音がダメ。ということは、D/Aコンバーターの速度が追いついていない可能性が高い。ということで、CVrefoutを用いた音声出力は、難しいことが分かった。
しかしながら、PIC32MXでのWAVファイル演奏エンジンは出来たので、速度の出せるD/Aコンバーターが準備できれば、使えそうだ。MachiKaniaの次の次のバージョン、 megalopaでは、64ピンの石を使う予定になっているので、それなら使えるかも知れない。
テストに用いたMachiKania用のアプリケーションのダウンロードは、こちらから。"mario.hex"に加えて、サンプルレートが16000 Hz (8 bit)のWAVファイルを、mario.wavのファイル名でSDカードにコピーすることで、演奏が行える。
他方、100 kHzのsetting timeは、音声出力には十分の筈である。CDのサンプリングレートである44.1 kHzを、超えている。この機能を用いて、PIC32MX / MachiKaniaで音声出力が出来ないか、調べてみた。
CVrefoutは、28ピンのPIC32MXでは、25番ピン(RB14)に出力できる。MachiKaniaでは"Fire"ボタンの入力に用いられているものの、テスト目的であれば、ボタンを押さなければ出力にも使えるはずである。ここから、トランジスターのベースにつなぎ、エミッターフォロワーにして、スピーカー(もしくは、TVの音声入力)につないでみた。
CVRCONbits.CVRR=0とすると、0.83Vから2.37Vの間で、16段階の異なる電圧を出力できる。トランジスターで電圧低下が起こるが、出力電圧は直線的に変化することが期待できる。
ソフトウェアとしては、タイマーで割り込みを15769 Hzで掛けた。MachiKaniaのNTSCビデオシグナルと同じ頻度である。従って、音声のサンプリングレートは、この速度になる。WAVファイルをサンプルレート16000 Hzで準備し、このファイルを再生する形式とした。レートに若干のズレ(1.4%)があるが、音楽家でもない限り、違いはほとんど分からない筈である。テストの結果は、下記の動画の通り。
うーん、良い線行っているのだけれど、雑音がひどい。低音はいい音が出ているが、高音がダメ。ということは、D/Aコンバーターの速度が追いついていない可能性が高い。ということで、CVrefoutを用いた音声出力は、難しいことが分かった。
しかしながら、PIC32MXでのWAVファイル演奏エンジンは出来たので、速度の出せるD/Aコンバーターが準備できれば、使えそうだ。MachiKaniaの次の次のバージョン、 megalopaでは、64ピンの石を使う予定になっているので、それなら使えるかも知れない。
テストに用いたMachiKania用のアプリケーションのダウンロードは、こちらから。"mario.hex"に加えて、サンプルレートが16000 Hz (8 bit)のWAVファイルを、mario.wavのファイル名でSDカードにコピーすることで、演奏が行える。
コメント
特になし (2016年8月11日 00:41:54)
LPFが無ければ高域のイメージ成分が耳障りな歪として聞こえます. LPFを付加すればもっと良い音になるはずです.
Katsumi (2016年8月21日 15:19:09)
コメントをどうも有り難うございます。WAVファイルの再生に関しては、抵抗アレイを用いたD/Aコンバーターを使うことで落ち着きそうです。LPFを用いた方法も色々やってみたのですが、どうも雑音が取れなくて、抵抗アレイを用いるのが一番綺麗に音が出そうです。
Gombe (2016年12月6日 15:31:19)
多分PWMが一番安定しそうです。既存のハードそのままのポートで動きますし。
https://github.com/elect-gombe/WAON_onMachiKania/tree/tetris_bootloader?files=1
結果としてPCM音源ではないですがWaveTable方式にてまあまあな音が出ました。PCMは試してないですが読み取りが追いつくか。。。きつそう。。。
ちなみにノイズの原因の一つにサンプリング周波数の低さがあると思います。矩形波の場合は周波数が高い場合、Duty比が崩れやすくてそれがそのままノイズのように聞こえてしまうようです。矩形波はDuty比で音色が変わってしまいますのでしょうがないですね。あとは分解能の低さですかね?
対策としては32kくらいまでサンプリング周波数をあげたり波形を変更したりできます。その場合は映像出力中にも波形を出さないとならないのでDMAなどを使うといいと思います。
https://github.com/elect-gombe/WAON_onMachiKania/tree/tetris_bootloader?files=1
結果としてPCM音源ではないですがWaveTable方式にてまあまあな音が出ました。PCMは試してないですが読み取りが追いつくか。。。きつそう。。。
ちなみにノイズの原因の一つにサンプリング周波数の低さがあると思います。矩形波の場合は周波数が高い場合、Duty比が崩れやすくてそれがそのままノイズのように聞こえてしまうようです。矩形波はDuty比で音色が変わってしまいますのでしょうがないですね。あとは分解能の低さですかね?
対策としては32kくらいまでサンプリング周波数をあげたり波形を変更したりできます。その場合は映像出力中にも波形を出さないとならないのでDMAなどを使うといいと思います。
Katsumi (2016年12月8日 20:09:30)
Gombeさん
初めまして。コメントをどうも有り難うございます。ケンケンさんの掲示板で、議論を拝見致しました。Gombeさんのは、1ポートで和音が出ているんですね。Zoeaは1ポートで音を出す必要があるので、魅力的です。
実は、上のコメントにも書きましたが、D/Aコンバーターを使ったWAVファイルの再生には成功しているんですよ。TouTubeに動画があるので、ちゃんと公開しないといけないですね。時期メジャーアップデートになる、Megalopa(コードネーム)では石の足がたくさんあるので、これが使えそうです。
初めまして。コメントをどうも有り難うございます。ケンケンさんの掲示板で、議論を拝見致しました。Gombeさんのは、1ポートで和音が出ているんですね。Zoeaは1ポートで音を出す必要があるので、魅力的です。
実は、上のコメントにも書きましたが、D/Aコンバーターを使ったWAVファイルの再生には成功しているんですよ。TouTubeに動画があるので、ちゃんと公開しないといけないですね。時期メジャーアップデートになる、Megalopa(コードネーム)では石の足がたくさんあるので、これが使えそうです。
Gombe (2016年12月9日 00:01:07)
Wave形式ですか。手軽に扱えるのでその点は良さそうです。ただ心配なのはSD読み出しなどは間に合うのでしょうか?あまり音声にはリソースを割きたくないところなのでその点が心配ですね。
効果音も入れるとしたら例えばWave+WaveTableなどのハイブリッドで効果音とBGMみたいな感じになるんでしょうか?
あとラダーの抵抗だと回路の規模が大きくなってしまいそうですね。せっかくマイコンなんだから最もピンを明け渡す必要があります。PWMでいいんじゃないでしょうか?音質は多少は落ちますが分解能は8bit以上確保できますよ。
効果音も入れるとしたら例えばWave+WaveTableなどのハイブリッドで効果音とBGMみたいな感じになるんでしょうか?
あとラダーの抵抗だと回路の規模が大きくなってしまいそうですね。せっかくマイコンなんだから最もピンを明け渡す必要があります。PWMでいいんじゃないでしょうか?音質は多少は落ちますが分解能は8bit以上確保できますよ。
Katsumi (2016年12月9日 11:16:37)
リソースの問題ですが、サンプリングレート16 kHzで実装しています。NTSCビデオシグナルの1ラインの周波数、15769 Hzをそのまま用いていて、それ用の割り込み関数に簡単なコードを追加するだけなので、それほど負担にならないはずです。
SD読み出しは、どうでしょうね。16 kHzの速度で8ビットのデーターを読み込んでいますから、128 KHz+αの速度が必要ですが、SDカードとの通信に使うSPIの速度、CPUのリソースを考えると、微妙なところかも知れません。WAVファイルを再生する場合は、かなりのリソースの消費になると思います。ただ、Megalopa用のBASICでの実装としては、和音を指定すると音楽データーを計算してRAMに落としておく様なことを考えているので、そこそこのリソース消費で行けるとは思っています。
ピン数に関しては、Megalopaでは64ピンの石を採用することになるので、問題無さそうです。私も色々実験した結果、抵抗アレイが一番綺麗な音を出します。
Zoeaでは、仰るようにピン数に上限がありますから、Gombeさんが仰るような方法が魅力的ですね。これって、いわゆるDSPの手法なのでしょうか?
SD読み出しは、どうでしょうね。16 kHzの速度で8ビットのデーターを読み込んでいますから、128 KHz+αの速度が必要ですが、SDカードとの通信に使うSPIの速度、CPUのリソースを考えると、微妙なところかも知れません。WAVファイルを再生する場合は、かなりのリソースの消費になると思います。ただ、Megalopa用のBASICでの実装としては、和音を指定すると音楽データーを計算してRAMに落としておく様なことを考えているので、そこそこのリソース消費で行けるとは思っています。
ピン数に関しては、Megalopaでは64ピンの石を採用することになるので、問題無さそうです。私も色々実験した結果、抵抗アレイが一番綺麗な音を出します。
Zoeaでは、仰るようにピン数に上限がありますから、Gombeさんが仰るような方法が魅力的ですね。これって、いわゆるDSPの手法なのでしょうか?
Katsumi (2016年12月9日 11:54:12)
SDカードからのWAVファイルの読み込みに必要なリソース消費量ですが…。
MachiKania Zoeaに使っている石のSPIの最高速度は25 MHzですが、仮に5 MHzの速度でSDカードとのやりとりが出来ていると仮定すると、1秒当り25ミリ秒必要です。他方、1秒あたり700ミリ秒がNTSCビデオシグナル作成に消費されています(残り300ミリ秒)。
全体の10%弱のリソース消費でのWAVファイル再生は、そんなに悪くないと思います。
MachiKania Zoeaに使っている石のSPIの最高速度は25 MHzですが、仮に5 MHzの速度でSDカードとのやりとりが出来ていると仮定すると、1秒当り25ミリ秒必要です。他方、1秒あたり700ミリ秒がNTSCビデオシグナル作成に消費されています(残り300ミリ秒)。
全体の10%弱のリソース消費でのWAVファイル再生は、そんなに悪くないと思います。
Gombe (2016年12月9日 16:43:40)
DSPではないとおもいます。DSPを詳しく知らないのですみません。
32kサンプリング音源を流しました。音質の劣化はありません。PWMは言われてみてもわからないほど高音質でしたよ。
で、本題に戻ります。負荷の方は映像出力を除いて実際に使える時間の30%でした。16kだとこの半分になると予想されるので15%ですね。映像出力中は画像の更新ができないのでこの間をつかって更新するのが望ましいのでしょうか?そう考えると意外と使えます。
この結果はSDカードの読み出し時のオーバーヘッドが無視できないことを示しています。読み出し前にSDカードがビジー状態になるのでその時間があります。また、連続セクターアクセス以外のランダムアクセスの時間も考えると(データが飛び飛びに点在するとき)この時間は結構変動しそうです。
ソースコードはGithubにあげておきます。ブランチ名は(WAVって入っているやt)WAVって書いてあるけどRAWしか再生できません(wwwすみません手抜きです。
そういえばこの投稿時間っていつの時間ですか?なんかおかしい気がする。
32kサンプリング音源を流しました。音質の劣化はありません。PWMは言われてみてもわからないほど高音質でしたよ。
で、本題に戻ります。負荷の方は映像出力を除いて実際に使える時間の30%でした。16kだとこの半分になると予想されるので15%ですね。映像出力中は画像の更新ができないのでこの間をつかって更新するのが望ましいのでしょうか?そう考えると意外と使えます。
この結果はSDカードの読み出し時のオーバーヘッドが無視できないことを示しています。読み出し前にSDカードがビジー状態になるのでその時間があります。また、連続セクターアクセス以外のランダムアクセスの時間も考えると(データが飛び飛びに点在するとき)この時間は結構変動しそうです。
ソースコードはGithubにあげておきます。ブランチ名は(WAVって入っているやt)WAVって書いてあるけどRAWしか再生できません(wwwすみません手抜きです。
そういえばこの投稿時間っていつの時間ですか?なんかおかしい気がする。
Katsumi (2016年12月9日 17:43:13)
ソースコードを、一度じっくり眺めてみます。どうも有り難うございます。
ここの投稿時間は、アメリカ太平洋標準時です。カリフォルニア州に住んでいますので。日本と、17時間の時差があります。
ここの投稿時間は、アメリカ太平洋標準時です。カリフォルニア州に住んでいますので。日本と、17時間の時差があります。
Gombe (2016年12月9日 18:39:19)
あ、そういうわけなんですね。
でも日本語のサイトだし日本のタイムゾーンでもいい気がしますがそうするとあなたが混乱してしまうわけなんですね。
あとソースコード整理しなきゃ。。。検証のみなので結構雑に書いてしまいました。後で上げ直します。
サンプルのプログラムは書き込めば動きますが、サンプルの音源MARIO.WAVを使うひつようがあります。unsigned,32k1ch8bitのRAWを使っています。変換できるようだったらそれなら再生できます。終了後の動作すら書いていない手抜きですので。。。
でも日本語のサイトだし日本のタイムゾーンでもいい気がしますがそうするとあなたが混乱してしまうわけなんですね。
あとソースコード整理しなきゃ。。。検証のみなので結構雑に書いてしまいました。後で上げ直します。
サンプルのプログラムは書き込めば動きますが、サンプルの音源MARIO.WAVを使うひつようがあります。unsigned,32k1ch8bitのRAWを使っています。変換できるようだったらそれなら再生できます。終了後の動作すら書いていない手抜きですので。。。
Gombe (2016年12月9日 19:32:07)
立て続けにすみません。
コードを整理しました。すこしはよみやすくなったとおもいます。
https://git.io/v1rsI
眺めてみてください。実行のためにはブートローダから
/dist/default/production/
のHEXをりネームしてください。また、TETRIS.RAWをSDカードに入れおく必要があります。PWMなので不安ならローパスフィルターを入れておくといいとおもいます。
コードを整理しました。すこしはよみやすくなったとおもいます。
https://git.io/v1rsI
眺めてみてください。実行のためにはブートローダから
/dist/default/production/
のHEXをりネームしてください。また、TETRIS.RAWをSDカードに入れおく必要があります。PWMなので不安ならローパスフィルターを入れておくといいとおもいます。
Katsumi (2016年12月10日 16:24:22)
どうも有り難うございます。見てみます。ここの所、多忙で電子工作の時間がなかなか取れずにいるので、少し時間をください。
Katsumi (2016年12月17日 20:21:35)
試してみました。ローパスフィルターとか使っていなくても、PWMでちゃんと和音が出るんですね。奇声容量が効いているということなのでしょうか。
Katsumi (2016年12月17日 20:24:37)
ところで、このサンプルファイルですが、ブートローダーから読み込んだ直後はちゃんと動作しますが、リセットすると動かなくなりますね。私も同様のバグで悩んだことがあるのですが、何が原因なのか、失念してしまいました。SDカード用のピンの入出力の設定が必要か何かだったと思います。
Gombe (2016年12月20日 14:16:00)
Katsumi (2016年12月21日 10:13:25)
私の耳では、1 kHzで6ビット以上、モーツアルトだと10ビット以上なら、違いが分かりませんでした。ローパスフィルターを入れるとどうなるんでしょうね。高音域をどの周波数までサポートするかと、ビット数と、ローパスフィルターの特性の兼ね合いになりそうですね。
Gombe (2016年12月21日 14:12:10)
モーツアルトをMachiKaniaで再生することなんてありませんよね(w
でも4bitだけだとここまで音が劣化するとは思いませんでした。やっぱり分解能は重要なんですね。BGMの場合は最低8bitでできれば10bit以上でしょうか?
でも10bitにするとデータ量が2倍以上に増えるし、、、
でも一応PWMでは最大10bitまでならハード的には可能そうにも思えます。ただし、このレベルだとマイコンからのノイズの方も無視できなくなりそうですね。
でも4bitだけだとここまで音が劣化するとは思いませんでした。やっぱり分解能は重要なんですね。BGMの場合は最低8bitでできれば10bit以上でしょうか?
でも10bitにするとデータ量が2倍以上に増えるし、、、
でも一応PWMでは最大10bitまでならハード的には可能そうにも思えます。ただし、このレベルだとマイコンからのノイズの方も無視できなくなりそうですね。
Katsumi (2016年12月23日 13:29:15)
いえ、以前はサンプルプログラムの中にモーツアルトを再生する物があったのですが(笑)、今の配布ファイルの中には無くなっていますね。いずれ、矩形波ではないモーツアルト再生プログラムを、サンプルプログラムとして同梱するかも知れません(笑)。
データー幅は、8ビットで良い気がします。音質にトコトンこだわるという機械では無いでしょうし。
仰るとおり、マイコンからのノイズは結構あるらしく、この記事でやろうとしたコンパレーター用のD/Aコンバーターを使った音声の再生は、それが原因で諦めました。
データー幅は、8ビットで良い気がします。音質にトコトンこだわるという機械では無いでしょうし。
仰るとおり、マイコンからのノイズは結構あるらしく、この記事でやろうとしたコンパレーター用のD/Aコンバーターを使った音声の再生は、それが原因で諦めました。