2025年03月19日

PSGでのPCM再生に関する考察


1.はじめに
 国立図書館のサイトでエンサイクロペディア・アスキーVol6を見ていたところデルタ変調方式を使った 「ソフトウェア・スピーチ・シンセサイザー」の記事が目に留まりました。当時、Z80の自作マイコンでダンプリストのデータを入力して試したことがあります。懐かしい・・・


2.ダンプリストの入力
 今時であれば、AIを使ってダンプリストを文字化すれば割合簡単にテキスト化できます。いくつかの生成AIを試しましたが、16進のダンプリストのテキスト化は Gemini さんが誤変換が少なくて良好な結果が得られるようです。
 AIによる文字化ではAIがダンプリストと判っている為か16進以外の文字へ誤変換することも無く割合良好なのですが、現時点のAIでは'8'と'B'との誤変換などは発生しますので人間による再確認が必要です。しかし当時とは比べ物にならない程楽になりました。


3.実行環境
 自作のマイコンにパラレルI/Fとラダー回路+アンプを付けて実験するのも面倒なので手軽に利用できるエミュレータの MSXPen で実験することにします。D/A機能を実現するためにPSG(Programmable Sound Generator)を使うことにしました。MSX Turbo R に設定すればD/A機能が実装されていますが今回の音源はそれ程の精度は必要無いので敢えてPSGを使います(PSGを使った方が面白そうですよね)。


4.PSGのレベル設定
 PSGは矩形波を3チェンネル分出力可能でそれぞれの出力レベルを16段階で設定可能です。
 下図は General Instrument社の AY-3-8910 のデータシートから抜粋したものです(以降の参照図も同様です)。下図ではボリューム設定レジスタが R10,R11,R12 になっていますが MSX Datapack wiki化計画のサイトにもあるようにMSXではR8~R10がボリュームコントロールのレジスタです。

PSGの設定ボリューム設定


 上記のPSGのボリュームは下図のように指数関数特性の出力になっています。ウェーバー・フェヒナーの法則にもあるように「人間の感覚の大きさは刺激の強さの対数に比例する」ので少ないビット数で聴感上の音量を制御するためには妥当な選択と言えます。

PSGのボリュームと出力値の関係


 しかし、リニアな8ビットのPCMデータの上位ニブルをそのままボリューム値として出力すると歪んでしまします。
 今回はデータ自体の精度がそれほど高くないことからPCMデータの上位ニブルを下記のような簡易的な変換を行った後にPSGのボリュームとして設定しました。

VolCurv: ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0, 4, 7, 9,10,11,12,12,13,13,14,14,14,15,15,15

 下記は母音部のデルタ変調データの抜粋ですが、一つの母音のデータが僅か20バイトなのでかなりの圧縮率なのではないでしょうか?
 また、子音に関しては各子音が256バイト構成のデータになっていて、ローマ字表記式で任意のフレーズの音声を合成できます。

; a:2180h VoiAA: DB 080H,025H,0BFH,0FEH,0A2H,005H,0F5H,00AH DB 0F5H,024H,055H,0CAH,0AFH,054H,02AH,0BBH DB 029H,05BH,054H,0A5H ; i:2194h VoiII: DB 020H,087H,00EH,05EH,0FBH,0DFH,01FH,01CH DB 00CH,043H,00EH,039H,0E7H,0AAH,0B2H,0B1H DB 054H,0B5H,06CH,0C8H

 母音は第二ホルマント(声道の共振周波数)までの情報で認識可能と言われているのでFM音源であればホルマント周波数に合わせた3つのサイン波で母音を合成できると思います。PSGの出力は矩形波なので3倍音が含まれますがホルマント周波数に合わせた周波数で出力すれば母音のように聞こえるかもしれませんね。
 X(旧Twitter)に投稿したメッセージに添付した動画を貼っておきます。「あいうえお はろおわあるど」と言っているのですがそのように聞こえますか?


★追記 2025/03/30 {
 X(Twitter)に投稿したピッチ制御を追加したメッセージに添付した動画も貼っておきます。

}

 定常状態である母音に関してはそれなりに聞こえますが子音の方は中々聞こえ辛いですね。
  • 子音に後続する母音は子音の影響を受けかなり変化する
  • 子音の長さは一定では無い(母音部との境目は不明瞭)
等の理由から単純な音素結合方式では高品質な合成は難しいと思います。


5.PSGによるPCM再生の高音質化
 今回のPCM音源の音質はあまり高くないのでPSGで簡易的に再生しましたが、PSGには独立にボリューム調整可能な3チャンネルの音源があるのでこれらを組合わせて8ビットのPCMデータをもっと高品質に再生する方法を考えてみました。
 PSGのボリューム設定に対する出力は前述のように指数関数の特性になっていて

2^-((15-n)/2)

で計算すると下表のようになります。

PSGのボリュームと出力値

 PCMデータをより高品質に再生するためには各音源のボリューム値の組合せをどうすればいいか・・ですが、下記の観点で考えてみました。
  • PSGのボリュームでステップ幅の大きい14,15の値は使用しない
  • 上記の制限からダイナミックレンジとしてはPCMが最大値(0xff)で1V出力とする
  • 設定するボリューム値は ch0 >= ch1 >= ch2 とする(I/O設定も同順)
 上記の観点で算出したPCM再生時のPSGのボリューム値の組合せが下記になります。

PCM再生用PSGボリューム値の組合せ
PCM Value ch0 Vol ch1 vol ch2 vol error error[%] PCM: 0 (-0.006) : ch0= 0 ch1= 0 ch2= 0 dif=-0.0060 -0.60% PCM: 1 (-0.002) : ch0= 0 ch1= 0 ch2= 0 dif=-0.0021 -0.21% PCM: 2 ( 0.002) : ch0= 0 ch1= 0 ch2= 0 dif= 0.0018 0.18% PCM: 3 ( 0.006) : ch0= 0 ch1= 0 ch2= 0 dif= 0.0058 0.58% PCM: 4 ( 0.010) : ch0= 1 ch1= 0 ch2= 0 dif= 0.0017 0.17% PCM: 5 ( 0.014) : ch0= 2 ch1= 0 ch2= 0 dif= 0.0026 0.26% PCM: 6 ( 0.018) : ch0= 3 ch1= 0 ch2= 0 dif= 0.0015 0.15% PCM: 7 ( 0.021) : ch0= 3 ch1= 0 ch2= 0 dif= 0.0055 0.55% PCM: 8 ( 0.025) : ch0= 4 ch1= 0 ch2= 0 dif= 0.0034 0.34% PCM: 9 ( 0.029) : ch0= 4 ch1= 0 ch2= 0 dif= 0.0073 0.73% PCM: 10 ( 0.033) : ch0= 5 ch1= 0 ch2= 0 dif= 0.0022 0.22% PCM: 11 ( 0.037) : ch0= 5 ch1= 0 ch2= 0 dif= 0.0061 0.61% PCM: 12 ( 0.041) : ch0= 5 ch1= 1 ch2= 0 dif= 0.0021 0.21% PCM: 13 ( 0.045) : ch0= 6 ch1= 0 ch2= 0 dif= 0.0010 0.10% PCM: 14 ( 0.049) : ch0= 6 ch1= 0 ch2= 0 dif= 0.0049 0.49% PCM: 15 ( 0.053) : ch0= 6 ch1= 1 ch2= 0 dif= 0.0008 0.08% PCM: 16 ( 0.057) : ch0= 6 ch1= 2 ch2= 0 dif= 0.0017 0.17% PCM: 17 ( 0.061) : ch0= 6 ch1= 3 ch2= 0 dif= 0.0007 0.07% PCM: 18 ( 0.065) : ch0= 7 ch1= 0 ch2= 0 dif= 0.0016 0.16% PCM: 19 ( 0.069) : ch0= 7 ch1= 0 ch2= 0 dif= 0.0055 0.55% PCM: 20 ( 0.072) : ch0= 7 ch1= 1 ch2= 0 dif= 0.0014 0.14% PCM: 21 ( 0.076) : ch0= 7 ch1= 2 ch2= 0 dif= 0.0024 0.24% PCM: 22 ( 0.080) : ch0= 7 ch1= 3 ch2= 0 dif= 0.0013 0.13% PCM: 23 ( 0.084) : ch0= 7 ch1= 3 ch2= 0 dif= 0.0052 0.52% PCM: 24 ( 0.088) : ch0= 8 ch1= 0 ch2= 0 dif= 0.0001 0.01% PCM: 25 ( 0.092) : ch0= 8 ch1= 0 ch2= 0 dif= 0.0040 0.40% PCM: 26 ( 0.096) : ch0= 8 ch1= 0 ch2= 0 dif= 0.0080 0.80% PCM: 27 ( 0.100) : ch0= 8 ch1= 2 ch2= 0 dif= 0.0009 0.09% PCM: 28 ( 0.104) : ch0= 8 ch1= 2 ch2= 0 dif= 0.0048 0.48% PCM: 29 ( 0.108) : ch0= 8 ch1= 3 ch2= 0 dif= 0.0037 0.37% PCM: 30 ( 0.112) : ch0= 8 ch1= 4 ch2= 0 dif= 0.0016 0.16% PCM: 31 ( 0.116) : ch0= 8 ch1= 4 ch2= 0 dif= 0.0056 0.56% PCM: 32 ( 0.119) : ch0= 8 ch1= 5 ch2= 0 dif= 0.0005 0.05% PCM: 33 ( 0.123) : ch0= 8 ch1= 5 ch2= 0 dif= 0.0044 0.44% PCM: 34 ( 0.127) : ch0= 9 ch1= 0 ch2= 0 dif= 0.0023 0.23% PCM: 35 ( 0.131) : ch0= 9 ch1= 0 ch2= 0 dif= 0.0063 0.63% PCM: 36 ( 0.135) : ch0= 9 ch1= 1 ch2= 0 dif= 0.0022 0.22% PCM: 37 ( 0.139) : ch0= 9 ch1= 2 ch2= 0 dif= 0.0031 0.31% PCM: 38 ( 0.143) : ch0= 9 ch1= 3 ch2= 0 dif= 0.0020 0.20% PCM: 39 ( 0.147) : ch0= 9 ch1= 3 ch2= 0 dif= 0.0059 0.59% PCM: 40 ( 0.151) : ch0= 9 ch1= 4 ch2= 0 dif= 0.0039 0.39% PCM: 41 ( 0.155) : ch0= 9 ch1= 4 ch2= 0 dif= 0.0078 0.78% PCM: 42 ( 0.159) : ch0= 9 ch1= 5 ch2= 0 dif= 0.0027 0.27% PCM: 43 ( 0.163) : ch0= 9 ch1= 5 ch2= 0 dif= 0.0066 0.66% PCM: 44 ( 0.167) : ch0= 9 ch1= 5 ch2= 1 dif= 0.0025 0.25% PCM: 45 ( 0.170) : ch0= 9 ch1= 6 ch2= 0 dif= 0.0015 0.15% PCM: 46 ( 0.174) : ch0= 9 ch1= 6 ch2= 0 dif= 0.0054 0.54% PCM: 47 ( 0.178) : ch0= 10 ch1= 0 ch2= 0 dif= 0.0013 0.13% PCM: 48 ( 0.182) : ch0= 10 ch1= 0 ch2= 0 dif= 0.0052 0.52% PCM: 49 ( 0.186) : ch0= 10 ch1= 1 ch2= 0 dif= 0.0012 0.12% PCM: 50 ( 0.190) : ch0= 10 ch1= 2 ch2= 0 dif= 0.0021 0.21% PCM: 51 ( 0.194) : ch0= 10 ch1= 3 ch2= 0 dif= 0.0010 0.10% PCM: 52 ( 0.198) : ch0= 10 ch1= 3 ch2= 0 dif= 0.0049 0.49% PCM: 53 ( 0.202) : ch0= 10 ch1= 4 ch2= 0 dif= 0.0028 0.28% PCM: 54 ( 0.206) : ch0= 10 ch1= 4 ch2= 0 dif= 0.0068 0.68% PCM: 55 ( 0.210) : ch0= 10 ch1= 5 ch2= 0 dif= 0.0017 0.17% PCM: 56 ( 0.214) : ch0= 10 ch1= 5 ch2= 0 dif= 0.0056 0.56% PCM: 57 ( 0.218) : ch0= 10 ch1= 5 ch2= 1 dif= 0.0015 0.15% PCM: 58 ( 0.221) : ch0= 10 ch1= 6 ch2= 0 dif= 0.0005 0.05% PCM: 59 ( 0.225) : ch0= 10 ch1= 6 ch2= 0 dif= 0.0044 0.44% PCM: 60 ( 0.229) : ch0= 10 ch1= 6 ch2= 1 dif= 0.0003 0.03% PCM: 61 ( 0.233) : ch0= 10 ch1= 6 ch2= 2 dif= 0.0012 0.12% PCM: 62 ( 0.237) : ch0= 10 ch1= 6 ch2= 3 dif= 0.0001 0.01% PCM: 63 ( 0.241) : ch0= 10 ch1= 7 ch2= 0 dif= 0.0011 0.11% PCM: 64 ( 0.245) : ch0= 10 ch1= 7 ch2= 0 dif= 0.0050 0.50% PCM: 65 ( 0.249) : ch0= 10 ch1= 7 ch2= 1 dif= 0.0009 0.09% PCM: 66 ( 0.253) : ch0= 11 ch1= 0 ch2= 0 dif= 0.0028 0.28% PCM: 67 ( 0.257) : ch0= 11 ch1= 0 ch2= 0 dif= 0.0067 0.67% PCM: 68 ( 0.261) : ch0= 11 ch1= 1 ch2= 0 dif= 0.0027 0.27% PCM: 69 ( 0.265) : ch0= 11 ch1= 2 ch2= 0 dif= 0.0036 0.36% PCM: 70 ( 0.269) : ch0= 11 ch1= 3 ch2= 0 dif= 0.0025 0.25% PCM: 71 ( 0.272) : ch0= 11 ch1= 4 ch2= 0 dif= 0.0004 0.04% PCM: 72 ( 0.276) : ch0= 11 ch1= 4 ch2= 0 dif= 0.0044 0.44% PCM: 73 ( 0.280) : ch0= 11 ch1= 4 ch2= 1 dif= 0.0003 0.03% PCM: 74 ( 0.284) : ch0= 11 ch1= 5 ch2= 0 dif= 0.0032 0.32% PCM: 75 ( 0.288) : ch0= 11 ch1= 5 ch2= 0 dif= 0.0071 0.71% PCM: 76 ( 0.292) : ch0= 11 ch1= 5 ch2= 2 dif= 0.0000 0.00% PCM: 77 ( 0.296) : ch0= 11 ch1= 6 ch2= 0 dif= 0.0020 0.20% PCM: 78 ( 0.300) : ch0= 11 ch1= 6 ch2= 0 dif= 0.0059 0.59% PCM: 79 ( 0.304) : ch0= 11 ch1= 6 ch2= 1 dif= 0.0018 0.18% PCM: 80 ( 0.308) : ch0= 11 ch1= 6 ch2= 2 dif= 0.0027 0.27% PCM: 81 ( 0.312) : ch0= 11 ch1= 6 ch2= 3 dif= 0.0016 0.16% PCM: 82 ( 0.316) : ch0= 11 ch1= 7 ch2= 0 dif= 0.0026 0.26% PCM: 83 ( 0.319) : ch0= 11 ch1= 7 ch2= 0 dif= 0.0065 0.65% PCM: 84 ( 0.323) : ch0= 11 ch1= 7 ch2= 1 dif= 0.0024 0.24% PCM: 85 ( 0.327) : ch0= 11 ch1= 7 ch2= 2 dif= 0.0033 0.33% PCM: 86 ( 0.331) : ch0= 11 ch1= 7 ch2= 3 dif= 0.0023 0.23% PCM: 87 ( 0.335) : ch0= 11 ch1= 7 ch2= 4 dif= 0.0002 0.02% PCM: 88 ( 0.339) : ch0= 11 ch1= 8 ch2= 0 dif= 0.0011 0.11% PCM: 89 ( 0.343) : ch0= 11 ch1= 8 ch2= 0 dif= 0.0050 0.50% PCM: 90 ( 0.347) : ch0= 11 ch1= 8 ch2= 1 dif= 0.0009 0.09% PCM: 91 ( 0.351) : ch0= 11 ch1= 8 ch2= 2 dif= 0.0019 0.19% PCM: 92 ( 0.355) : ch0= 12 ch1= 0 ch2= 0 dif= 0.0008 0.08% PCM: 93 ( 0.359) : ch0= 12 ch1= 0 ch2= 0 dif= 0.0047 0.47% PCM: 94 ( 0.363) : ch0= 12 ch1= 1 ch2= 0 dif= 0.0006 0.06% PCM: 95 ( 0.367) : ch0= 12 ch1= 2 ch2= 0 dif= 0.0015 0.15% PCM: 96 ( 0.370) : ch0= 12 ch1= 3 ch2= 0 dif= 0.0005 0.05% PCM: 97 ( 0.374) : ch0= 12 ch1= 3 ch2= 0 dif= 0.0044 0.44% PCM: 98 ( 0.378) : ch0= 12 ch1= 4 ch2= 0 dif= 0.0023 0.23% PCM: 99 ( 0.382) : ch0= 12 ch1= 4 ch2= 0 dif= 0.0062 0.62% PCM:100 ( 0.386) : ch0= 12 ch1= 5 ch2= 0 dif= 0.0012 0.12% PCM:101 ( 0.390) : ch0= 12 ch1= 5 ch2= 0 dif= 0.0051 0.51% PCM:102 ( 0.394) : ch0= 12 ch1= 5 ch2= 1 dif= 0.0010 0.10% PCM:103 ( 0.398) : ch0= 12 ch1= 5 ch2= 2 dif= 0.0019 0.19% PCM:104 ( 0.402) : ch0= 12 ch1= 6 ch2= 0 dif= 0.0038 0.38% PCM:105 ( 0.406) : ch0= 12 ch1= 6 ch2= 0 dif= 0.0078 0.78% PCM:106 ( 0.410) : ch0= 12 ch1= 6 ch2= 2 dif= 0.0007 0.07% PCM:107 ( 0.414) : ch0= 12 ch1= 6 ch2= 2 dif= 0.0046 0.46% PCM:108 ( 0.418) : ch0= 12 ch1= 7 ch2= 0 dif= 0.0005 0.05% PCM:109 ( 0.421) : ch0= 12 ch1= 7 ch2= 0 dif= 0.0045 0.45% PCM:110 ( 0.425) : ch0= 12 ch1= 7 ch2= 1 dif= 0.0004 0.04% PCM:111 ( 0.429) : ch0= 12 ch1= 7 ch2= 2 dif= 0.0013 0.13% PCM:112 ( 0.433) : ch0= 12 ch1= 7 ch2= 3 dif= 0.0002 0.02% PCM:113 ( 0.437) : ch0= 12 ch1= 7 ch2= 3 dif= 0.0041 0.41% PCM:114 ( 0.441) : ch0= 12 ch1= 7 ch2= 4 dif= 0.0021 0.21% PCM:115 ( 0.445) : ch0= 12 ch1= 8 ch2= 0 dif= 0.0030 0.30% PCM:116 ( 0.449) : ch0= 12 ch1= 8 ch2= 0 dif= 0.0069 0.69% PCM:117 ( 0.453) : ch0= 12 ch1= 8 ch2= 1 dif= 0.0028 0.28% PCM:118 ( 0.457) : ch0= 12 ch1= 8 ch2= 2 dif= 0.0037 0.37% PCM:119 ( 0.461) : ch0= 12 ch1= 8 ch2= 3 dif= 0.0027 0.27% PCM:120 ( 0.465) : ch0= 12 ch1= 8 ch2= 4 dif= 0.0006 0.06% PCM:121 ( 0.469) : ch0= 12 ch1= 8 ch2= 4 dif= 0.0045 0.45% PCM:122 ( 0.472) : ch0= 12 ch1= 8 ch2= 4 dif= 0.0084 0.84% PCM:123 ( 0.476) : ch0= 12 ch1= 8 ch2= 5 dif= 0.0034 0.34% PCM:124 ( 0.480) : ch0= 12 ch1= 9 ch2= 0 dif= 0.0013 0.13% PCM:125 ( 0.484) : ch0= 12 ch1= 9 ch2= 0 dif= 0.0052 0.52% PCM:126 ( 0.488) : ch0= 12 ch1= 9 ch2= 1 dif= 0.0011 0.11% PCM:127 ( 0.492) : ch0= 12 ch1= 9 ch2= 2 dif= 0.0020 0.20% PCM:128 ( 0.496) : ch0= 12 ch1= 9 ch2= 3 dif= 0.0010 0.10% PCM:129 ( 0.500) : ch0= 12 ch1= 9 ch2= 3 dif= 0.0049 0.49% PCM:130 ( 0.504) : ch0= 13 ch1= 0 ch2= 0 dif= 0.0038 0.38% PCM:131 ( 0.508) : ch0= 13 ch1= 0 ch2= 0 dif= 0.0077 0.77% PCM:132 ( 0.512) : ch0= 13 ch1= 2 ch2= 0 dif= 0.0006 0.06% PCM:133 ( 0.516) : ch0= 13 ch1= 2 ch2= 0 dif= 0.0046 0.46% PCM:134 ( 0.519) : ch0= 13 ch1= 3 ch2= 0 dif= 0.0035 0.35% PCM:135 ( 0.523) : ch0= 13 ch1= 4 ch2= 0 dif= 0.0014 0.14% PCM:136 ( 0.527) : ch0= 13 ch1= 4 ch2= 0 dif= 0.0053 0.53% PCM:137 ( 0.531) : ch0= 13 ch1= 5 ch2= 0 dif= 0.0003 0.03% PCM:138 ( 0.535) : ch0= 13 ch1= 5 ch2= 0 dif= 0.0042 0.42% PCM:139 ( 0.539) : ch0= 13 ch1= 5 ch2= 1 dif= 0.0001 0.01% PCM:140 ( 0.543) : ch0= 13 ch1= 5 ch2= 2 dif= 0.0010 0.10% PCM:141 ( 0.547) : ch0= 13 ch1= 6 ch2= 0 dif= 0.0029 0.29% PCM:142 ( 0.551) : ch0= 13 ch1= 6 ch2= 0 dif= 0.0069 0.69% PCM:143 ( 0.555) : ch0= 13 ch1= 6 ch2= 1 dif= 0.0028 0.28% PCM:144 ( 0.559) : ch0= 13 ch1= 6 ch2= 2 dif= 0.0037 0.37% PCM:145 ( 0.563) : ch0= 13 ch1= 6 ch2= 3 dif= 0.0026 0.26% PCM:146 ( 0.567) : ch0= 13 ch1= 7 ch2= 0 dif= 0.0035 0.35% PCM:147 ( 0.570) : ch0= 13 ch1= 7 ch2= 0 dif= 0.0075 0.75% PCM:148 ( 0.574) : ch0= 13 ch1= 7 ch2= 2 dif= 0.0004 0.04% PCM:149 ( 0.578) : ch0= 13 ch1= 7 ch2= 2 dif= 0.0043 0.43% PCM:150 ( 0.582) : ch0= 13 ch1= 7 ch2= 3 dif= 0.0032 0.32% PCM:151 ( 0.586) : ch0= 13 ch1= 7 ch2= 4 dif= 0.0012 0.12% PCM:152 ( 0.590) : ch0= 13 ch1= 8 ch2= 0 dif= 0.0021 0.21% PCM:153 ( 0.594) : ch0= 13 ch1= 8 ch2= 0 dif= 0.0060 0.60% PCM:154 ( 0.598) : ch0= 13 ch1= 8 ch2= 1 dif= 0.0019 0.19% PCM:155 ( 0.602) : ch0= 13 ch1= 8 ch2= 2 dif= 0.0028 0.28% PCM:156 ( 0.606) : ch0= 13 ch1= 8 ch2= 3 dif= 0.0018 0.18% PCM:157 ( 0.610) : ch0= 13 ch1= 8 ch2= 3 dif= 0.0057 0.57% PCM:158 ( 0.614) : ch0= 13 ch1= 8 ch2= 4 dif= 0.0036 0.36% PCM:159 ( 0.618) : ch0= 13 ch1= 8 ch2= 4 dif= 0.0075 0.75% PCM:160 ( 0.621) : ch0= 13 ch1= 8 ch2= 5 dif= 0.0025 0.25% PCM:161 ( 0.625) : ch0= 13 ch1= 9 ch2= 0 dif= 0.0004 0.04% PCM:162 ( 0.629) : ch0= 13 ch1= 9 ch2= 0 dif= 0.0043 0.43% PCM:163 ( 0.633) : ch0= 13 ch1= 9 ch2= 1 dif= 0.0002 0.02% PCM:164 ( 0.637) : ch0= 13 ch1= 9 ch2= 2 dif= 0.0011 0.11% PCM:165 ( 0.641) : ch0= 13 ch1= 9 ch2= 3 dif= 0.0001 0.01% PCM:166 ( 0.645) : ch0= 13 ch1= 9 ch2= 3 dif= 0.0040 0.40% PCM:167 ( 0.649) : ch0= 13 ch1= 9 ch2= 4 dif= 0.0019 0.19% PCM:168 ( 0.653) : ch0= 13 ch1= 9 ch2= 4 dif= 0.0058 0.58% PCM:169 ( 0.657) : ch0= 13 ch1= 9 ch2= 5 dif= 0.0007 0.07% PCM:170 ( 0.661) : ch0= 13 ch1= 9 ch2= 5 dif= 0.0047 0.47% PCM:171 ( 0.665) : ch0= 13 ch1= 9 ch2= 5 dif= 0.0086 0.86% PCM:172 ( 0.669) : ch0= 13 ch1= 9 ch2= 5 dif= 0.0125 1.25% PCM:173 ( 0.672) : ch0= 13 ch1= 9 ch2= 6 dif= 0.0034 0.34% PCM:174 ( 0.676) : ch0= 13 ch1= 9 ch2= 6 dif= 0.0074 0.74% PCM:175 ( 0.680) : ch0= 13 ch1= 10 ch2= 0 dif= 0.0033 0.33% PCM:176 ( 0.684) : ch0= 13 ch1= 10 ch2= 0 dif= 0.0072 0.72% PCM:177 ( 0.688) : ch0= 13 ch1= 10 ch2= 2 dif= 0.0001 0.01% PCM:178 ( 0.692) : ch0= 13 ch1= 10 ch2= 2 dif= 0.0040 0.40% PCM:179 ( 0.696) : ch0= 13 ch1= 10 ch2= 3 dif= 0.0030 0.30% PCM:180 ( 0.700) : ch0= 13 ch1= 10 ch2= 4 dif= 0.0009 0.09% PCM:181 ( 0.704) : ch0= 13 ch1= 10 ch2= 4 dif= 0.0048 0.48% PCM:182 ( 0.708) : ch0= 13 ch1= 10 ch2= 4 dif= 0.0087 0.87% PCM:183 ( 0.712) : ch0= 13 ch1= 10 ch2= 5 dif= 0.0036 0.36% PCM:184 ( 0.716) : ch0= 13 ch1= 10 ch2= 5 dif= 0.0076 0.76% PCM:185 ( 0.719) : ch0= 13 ch1= 10 ch2= 5 dif= 0.0115 1.15% PCM:186 ( 0.723) : ch0= 13 ch1= 10 ch2= 6 dif= 0.0024 0.24% PCM:187 ( 0.727) : ch0= 13 ch1= 10 ch2= 6 dif= 0.0063 0.63% PCM:188 ( 0.731) : ch0= 13 ch1= 10 ch2= 6 dif= 0.0103 1.03% PCM:189 ( 0.735) : ch0= 13 ch1= 10 ch2= 6 dif= 0.0142 1.42% PCM:190 ( 0.739) : ch0= 13 ch1= 10 ch2= 6 dif= 0.0181 1.81% PCM:191 ( 0.743) : ch0= 13 ch1= 10 ch2= 7 dif= 0.0030 0.30% PCM:192 ( 0.747) : ch0= 13 ch1= 10 ch2= 7 dif= 0.0069 0.69% PCM:193 ( 0.751) : ch0= 13 ch1= 11 ch2= 0 dif= 0.0009 0.09% PCM:194 ( 0.755) : ch0= 13 ch1= 11 ch2= 0 dif= 0.0048 0.48% PCM:195 ( 0.759) : ch0= 13 ch1= 11 ch2= 1 dif= 0.0007 0.07% PCM:196 ( 0.763) : ch0= 13 ch1= 11 ch2= 2 dif= 0.0016 0.16% PCM:197 ( 0.767) : ch0= 13 ch1= 11 ch2= 3 dif= 0.0005 0.05% PCM:198 ( 0.770) : ch0= 13 ch1= 11 ch2= 3 dif= 0.0045 0.45% PCM:199 ( 0.774) : ch0= 13 ch1= 11 ch2= 4 dif= 0.0024 0.24% PCM:200 ( 0.778) : ch0= 13 ch1= 11 ch2= 4 dif= 0.0063 0.63% PCM:201 ( 0.782) : ch0= 13 ch1= 11 ch2= 5 dif= 0.0012 0.12% PCM:202 ( 0.786) : ch0= 13 ch1= 11 ch2= 5 dif= 0.0052 0.52% PCM:203 ( 0.790) : ch0= 13 ch1= 11 ch2= 5 dif= 0.0091 0.91% PCM:204 ( 0.794) : ch0= 13 ch1= 11 ch2= 6 dif= 0.0000 0.00% PCM:205 ( 0.798) : ch0= 13 ch1= 11 ch2= 6 dif= 0.0039 0.39% PCM:206 ( 0.802) : ch0= 13 ch1= 11 ch2= 6 dif= 0.0078 0.78% PCM:207 ( 0.806) : ch0= 13 ch1= 11 ch2= 6 dif= 0.0118 1.18% PCM:208 ( 0.810) : ch0= 13 ch1= 11 ch2= 6 dif= 0.0157 1.57% PCM:209 ( 0.814) : ch0= 13 ch1= 11 ch2= 7 dif= 0.0006 0.06% PCM:210 ( 0.818) : ch0= 13 ch1= 11 ch2= 7 dif= 0.0045 0.45% PCM:211 ( 0.821) : ch0= 13 ch1= 11 ch2= 7 dif= 0.0085 0.85% PCM:212 ( 0.825) : ch0= 13 ch1= 11 ch2= 7 dif= 0.0124 1.24% PCM:213 ( 0.829) : ch0= 13 ch1= 11 ch2= 7 dif= 0.0163 1.63% PCM:214 ( 0.833) : ch0= 13 ch1= 11 ch2= 7 dif= 0.0202 2.02% PCM:215 ( 0.837) : ch0= 13 ch1= 11 ch2= 7 dif= 0.0241 2.41% PCM:216 ( 0.841) : ch0= 13 ch1= 11 ch2= 8 dif= 0.0031 0.31% PCM:217 ( 0.845) : ch0= 13 ch1= 11 ch2= 8 dif= 0.0070 0.70% PCM:218 ( 0.849) : ch0= 13 ch1= 11 ch2= 8 dif= 0.0109 1.09% PCM:219 ( 0.853) : ch0= 13 ch1= 11 ch2= 8 dif= 0.0148 1.48% PCM:220 ( 0.857) : ch0= 13 ch1= 12 ch2= 0 dif= 0.0027 0.27% PCM:221 ( 0.861) : ch0= 13 ch1= 12 ch2= 0 dif= 0.0067 0.67% PCM:222 ( 0.865) : ch0= 13 ch1= 12 ch2= 1 dif= 0.0026 0.26% PCM:223 ( 0.869) : ch0= 13 ch1= 12 ch2= 2 dif= 0.0035 0.35% PCM:224 ( 0.872) : ch0= 13 ch1= 12 ch2= 3 dif= 0.0024 0.24% PCM:225 ( 0.876) : ch0= 13 ch1= 12 ch2= 4 dif= 0.0004 0.04% PCM:226 ( 0.880) : ch0= 13 ch1= 12 ch2= 4 dif= 0.0043 0.43% PCM:227 ( 0.884) : ch0= 13 ch1= 12 ch2= 4 dif= 0.0082 0.82% PCM:228 ( 0.888) : ch0= 13 ch1= 12 ch2= 5 dif= 0.0031 0.31% PCM:229 ( 0.892) : ch0= 13 ch1= 12 ch2= 5 dif= 0.0070 0.70% PCM:230 ( 0.896) : ch0= 13 ch1= 12 ch2= 5 dif= 0.0110 1.10% PCM:231 ( 0.900) : ch0= 13 ch1= 12 ch2= 6 dif= 0.0019 0.19% PCM:232 ( 0.904) : ch0= 13 ch1= 12 ch2= 6 dif= 0.0058 0.58% PCM:233 ( 0.908) : ch0= 13 ch1= 12 ch2= 6 dif= 0.0097 0.97% PCM:234 ( 0.912) : ch0= 13 ch1= 12 ch2= 6 dif= 0.0136 1.36% PCM:235 ( 0.916) : ch0= 13 ch1= 12 ch2= 6 dif= 0.0176 1.76% PCM:236 ( 0.919) : ch0= 13 ch1= 12 ch2= 7 dif= 0.0025 0.25% PCM:237 ( 0.923) : ch0= 13 ch1= 12 ch2= 7 dif= 0.0064 0.64% PCM:238 ( 0.927) : ch0= 13 ch1= 12 ch2= 7 dif= 0.0103 1.03% PCM:239 ( 0.931) : ch0= 13 ch1= 12 ch2= 7 dif= 0.0143 1.43% PCM:240 ( 0.935) : ch0= 13 ch1= 12 ch2= 7 dif= 0.0182 1.82% PCM:241 ( 0.939) : ch0= 13 ch1= 12 ch2= 7 dif= 0.0221 2.21% PCM:242 ( 0.943) : ch0= 13 ch1= 12 ch2= 8 dif= 0.0010 0.10% PCM:243 ( 0.947) : ch0= 13 ch1= 12 ch2= 8 dif= 0.0049 0.49% PCM:244 ( 0.951) : ch0= 13 ch1= 12 ch2= 8 dif= 0.0089 0.89% PCM:245 ( 0.955) : ch0= 13 ch1= 12 ch2= 8 dif= 0.0128 1.28% PCM:246 ( 0.959) : ch0= 13 ch1= 12 ch2= 8 dif= 0.0167 1.67% PCM:247 ( 0.963) : ch0= 13 ch1= 12 ch2= 8 dif= 0.0206 2.06% PCM:248 ( 0.967) : ch0= 13 ch1= 12 ch2= 8 dif= 0.0245 2.45% PCM:249 ( 0.970) : ch0= 13 ch1= 12 ch2= 8 dif= 0.0285 2.85% PCM:250 ( 0.974) : ch0= 13 ch1= 12 ch2= 8 dif= 0.0324 3.24% PCM:251 ( 0.978) : ch0= 13 ch1= 12 ch2= 8 dif= 0.0363 3.63% PCM:252 ( 0.982) : ch0= 13 ch1= 12 ch2= 9 dif= 0.0032 0.32% PCM:253 ( 0.986) : ch0= 13 ch1= 12 ch2= 9 dif= 0.0072 0.72% PCM:254 ( 0.990) : ch0= 13 ch1= 12 ch2= 9 dif= 0.0111 1.11% PCM:255 ( 0.994) : ch0= 13 ch1= 12 ch2= 9 dif= 0.0150 1.50%

 上記のボリューム組合せで8ビットPCMデータを再生すれば、かなり高品質で聞くことができるのではないかと思います。
 ボリュームの組合せを算出したソースも貼っておきます。

PCM再生用PSG設定ボリューム算出(C言語)
/* * calculatre PSG valume for PCM encode * Ver 0.01 2025/03/19 by skyriver */ #include <stdio.h> // INT((255*2^-((15-n)/2))*10+0.5) n=1..15 float PsgVol[] = { 0.006, 0.008, 0.011, 0.016 ,0.022, 0.031, 0.044, 0.063 ,0.088, 0.125, 0.177, 0.250 ,0.354, 0.500, 0.707, 1.000 }; int VolSt[] = { 13, 12, 10 }; int main( void ) { float full, rest; int pcm, ch, vol; for( pcm = 0; pcm < 256; pcm++ ) { full = 1.0; // full scale rest = pcm / 255.0 * full - PsgVol[ 0 ]; printf( "\n PCM:%3d (%6.3f) : ", pcm, rest ); for( ch = 0; ch < 3; ch++ ) { for( vol = VolSt[ ch ]; vol; vol-- ) { if( rest >= PsgVol[ vol ] ) { rest -= PsgVol[ vol ]; break; } } printf( " ch%d=%3d ", ch, vol ); } printf( " dif=%7.4f %6.2f%%", rest, rest / full * 100.0 ); } return 0; }

ラベル:PSG PCM MSX MSXPen
posted by skyriver at 22:01| Comment(0) | MSX | このブログの読者になる | 更新情報をチェックする

2022年08月26日

MSX1(CF1200)の購入(その2)カーリッジケースの作成(その2)

 前回の記事で3DプリンタでのMSXカートリッジケースの作成について書きましたが、ネットでカードエッジ直後から横幅が広いプリント基板もあることを知りました。

 そこで幅広のプリント基板にも対応すべくカートリッジケースを改善してみました。今までは固定するネジが上の方にあり、これが邪魔して大きなサイズの基板が入らない状態でした。今回はプリント基板固定用スペーサー部をネジで固定するようにすることで幅広の基板に対応しました。カートリッジの上側は嵌め込み式にして開かないようにしています。











改善したケースの CAD 表示






 下図が rear 側(後ろ側)のケース部品です。下側の辺を除く3辺の内側にズレ防止の爪を付けました。











改善したケースの CAD 表示(rear)






 下図が front側(手前側)のケース部品でプリント基板を固定するスペーサ部に木ネジで固定できるように穴を設けています。











改善したケースの CAD 表示(front)






 下の写真が 3D プリンタで出力した rear 側(左)と front 側(右)の部品の内側です。中央部分がスロットに入れる部分(ケースの下側)になります。












3D プリンタで造形した部品(内側)






 下の写真は 3D プリンタで出力した rear 側(左)と front 側(右)の部品の外側です。3D プリンタのベッドに貼ったフィルムと同様に艶消しの様な仕上がりになっています。











3D プリンタで造形した部品(外側)




★追記 2022/12/30 ベッドに貼ったフィルムが光沢の場合、表面は光沢になります。


 サンプルのプリント基板を rear 側に嵌め込んだ状態が下の写真になります。











プリント基板実装例






 2本のネジで固定後のカートリッジの下側(スロットのカードエッジコネクタに接続される側)が下の写真です。











カートリッジケース 外観1






 下の写真はカートリッジを上側から見た外観になります。











カートリッジケース 外観2






 今回は新たな試みとして3Dプリンタで出力した本カートリッジケースをBOOTHで配布することにしました。

 twitterに投稿した動画付きメッセージを貼っておきます。動画はフル画面で見るとケースの質感をより感じることが出来ます。





[TOP] [ 前へ ] 連載記事 [ 次へ ]
posted by skyriver at 18:07| Comment(0) | MSX | このブログの読者になる | 更新情報をチェックする

2022年08月02日

MSX1(CF1200)の購入(その1)カーリッジケースの作成

 最近、Twitter では MSX3 の話題で賑わっています。私は MSX の実機を弄ったことは無いのですが CPU が Z80 なので興味が沸き、MSX1 の初期の頃の機種である National 製 CF1200 の中古をマニュアル&箱付きで購入してみました。











購入した MSX1(CF1200)






 基本的な機能しか試していませんが動作上の問題はなさそうです。
 しかし、これだけでは内蔵 ROM から起動する BASIC で遊べるだけで他に何もできません。そこで、ROM を実装できる カートリッジ用基板が安く販売されていたので購入してみました。











カートリッジ用 ROM 実装基板






 これを使えばモニタプログラム等作り、カートリッジから立ち上げることが出来るようになります。
 基板が剥き出しの状態では扱いづらいのでカートリッジのケースを作ることにしました。ネットで探すとケースのSTL ファイルがいくつか見つかったので上記の基板が取り付けられそうなものを選び、3Dプリンタで出力してみましたが、丸ピンソケットで実装した ROM がつかえてうまくケースに収まりませんorz

 そこでケースを自作しようと思いましたがケースのサイズ情報がフルセットで記載されたサイトまたは資料が見つかりませんでした^^;
 下記のサイトの情報とネットで探した STL ファイルを参照してカートリッジのケースを CAD で設計してみました。

 作成したケースの CAD 表示が下図になります。ROM の部分は窓で外に出し、ROM の上面がケースの外側と面一くらいになりギリギリで収まりました。











カートリッジ用ケース(CAD画面)






 3Dプリンタで出力した結果が下の写真になります。若干お焦げが発生していますね^^;











カートリッジ用ケースの出力結果





★追記 2022/08/30 {
 フィラメントの流量調整やヒートブロックへのシリコンカバー装着等により焦げ問題はかなり改善されました。
}
 基板を嵌め込むと下図の様になります。基板は下側のホールで固定されていますが、これはコナミ仕様のサポータの位置だと思います。











カートリッジ用ケースと基板






 下の写真は3Dプリンタで出力したケースに基板を格納し、蓋をネジで固定した状態の様子です。











完成したカートリッジケース






 CF1200 のカートリッジスロットに入れてみましたが問題無さそうです。


★追記 2022/08/12
 何か新しいことをやってみようと思い、カートリッジシェルのSTLファイルを BOOTH にアップしてみました。


★追記 2022/08/30
 BOOTH ではカートリッジケースのSTLファイルでは無く、3Dプリンタで出力したケース自体を販売することにしました。


[TOP] [ 前へ ] 連載記事 [ 次へ ]
posted by skyriver at 23:56| Comment(0) | MSX | このブログの読者になる | 更新情報をチェックする