ZX スペクトル システムツアー:サウンド

2026/08/04 3:32

ZX スペクトル システムツアー:サウンド

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

欠落する要素 は、提示された特定の「重要ポイントリスト」に対する「完全性」に大きく影響します。サマリーは明確であり主な物語の構成を捉えていますが、重要ポイントリストにはアドレスや式、特定のサイクル数などの詳細な技術仕様が含まれており、サマリーではそれらが一般化されたり完全に省略されたりしています。「すべての主要な重要ポイントが反映されているか」という厳格なチェックポイントを踏むと、現状のサマリーはリストに含まれた詳細な技術データに対して忠実さを欠いています。

改善されたサマリー: 本文は ZX Spectrum 向けの 2 つのオーディオ方法を詳述しています:1 ビットビーパーと AY-3-8910 シンセサイザチップ(強化モデルや周辺機器として搭載されているもの)。初期のオーディオ試作ではタイミングの不一致や浮動小数点誤差により失敗し、解決策として周波数の手動管理、コードを

$9000
へ移して早期モデルでのビデオ回路への干渉を防ぐこと、一貫した 10 サイクルの分岐を実現するために絶対アドレスの
JP
命令を使用することが挙げられます。ビーパーは
$03B5
の BIOS を活用(例:
437500/f – 30.125
のような式)するか、ポート
$FE
を直接使用する方法があり、タイミング調整のため NOP を使用し、ループのアンロールのような最適化を施すことでノート持続時間を 1.5 秒から 2.4 秒以上まで延長します。あるいは AY-3 チップを使用すれば特定のクロック速度で調整された式(
3546900/(32f)
など)を用いて複雑な音楽を実現できます。Python スクリプトを使ってこれらの技術を利用した BASIC コードを生成し、ミュージシャンがプラットフォームと方法(ビーパーは効果やジングル用、AY-3 は連続音楽用)を選択できるようにします。

本文

シューティングギャラリーのサウンド機能:ZXSpectrum の初期ツアー

シューティングギャラリーの話題はこれで一区切りとなりました。次は、ZXSpectrum の初期ツアーのうちこれまで触れられていない「サウンド」の部分へと移りましょう。他プラットフォームに比べて特に新しい要素はないものの、それは同時に 核心となる解決策の原理がすでに構築済みであることを意味します。我々が必要なのは、Spectrum 特有の装飾(frosting)を施すだけだと言えるでしょう。

メインラインのサウンド機能の種類

メインラインの Spectrum システムにはサウンド機能として二つの選択肢があります:

  • ソフトウェア制御による 1 ビットのブイパー(ビーパ)
    • すべてのシステムに搭載されています。
    • その基盤となるハードウェアはアップル II や PC スピーカーで目にしたものと大差ありません。
  • General Instrument AY-3-8910 チップを搭載したシンセサイザー機能
    • 128K Spectrum 以降の全モデルに搭載されています。
    • 16K および 48K バリアントでは周辺機器として利用可能でした。
    • Atari ST に搭載されているものとは基本的に同型ですが、クロック周波数が異なります
    • チップとの通信には組み込み BIOS コールが存在しないのが特徴です。

この記事の締めくくりには、C 調のスケールを再生する 3 つのプログラムを提供することを目指します。


1. BIOS を介したブイパーの利用

1 ビットのブイパーはアップル II のそれと非常に類似しています。

  • I/O ポート $10 のビット設定:スピーカーの状態を変更できます。
  • トーン生成原理:そのビットを反転させる間隔を細かくタイミング制御することによって生成されます。

BASIC の

BEEP
コマンドが既にこの処理を担当しており、汎用的なルーティンへのフォワーディングを行うことで実現されています。ブイパー用ルーティンはメモリ場所 $03B5 に存在し、率直に言えば私が 6502 システムのために作成したバージョンよりも巧妙です。

  • HL レジスタ:4 サイクル(no-op の長さ)単位の遅延時間を指定します。
    • その高精度を実現する技術は、以前実装したプログラムメーブルなサイクル精度の 6502 遅延とはよく似たものです。
  • DE レジスタ:音符の持続時間を指定しますが、不便なのは実際に持つべき波長数そのものを指定している点です。同じ長さだがピッチが異なるノートでは、それぞれ異なる duration コードが必要となります。

一方、

BEEP
コマンド自体は、中間 C(middle C)から半音階オフの音符と、秒単位の持続時間を指定されることを前提としています。必要な値を得る方法を実装地点 $03F8 に存在する実装を見てみましょう。これはシステムの浮動小数点エンジンを通じて行われるため、きれいな公式をそのまま引き出すことができます:

  • 周波数コード(HL)
    437500/f – 30.125
    • $f$ は目標周波数 (Hz)
  • 持続コード(DE)
    f × t
    • $t$ は継続時間 (秒)

以下は、Python コードを用いて C 調スケールへのこれらの値を適用し、再生用プログラムを作成したものです。

        org     $7000
        ld      b,8                     ; 8 音符再生
        ld      hl,scale                ; ポインターから読み込み開始
loop:   push    bc
        ld      c,(hl)                  ; BC に周波数をロード
        inc     hl
        ld      b,(hl)
        inc     hl
        ld      e,(hl)                  ; HL に持続時間をロード
        inc     hl
        ld      d,(hl)
        inc     hl
        push    hl                      ; ポインターを一旦保存
        ld      h,b                     ; BC をコピーして HL へ
        ld      l,c
        call    $03b5                   ; ROM に任せて実行
        pop     hl
        pop     bc
        djnz    loop
        ret

scale:  dw      $066a,$0082,$05b3,$0092,$0511,$00a4,$04c6,$00ae
        dw      $043d,$00c3,$03c4,$00dc,$0357,$00f6,$0325,$0105

性能評価

  • これはアップル II サウンド再生ルーティンと同様の「半波長」方式ですが、はるかに微細なタイミング制御により、全体のトーン精度が著しく向上しています。
  • 初期記事で直面したトレードオフのほとんどがこのシステムには見られず、専用 PSG から期待される種類の制御力を得ています。
  • 唯一の欠点:両方の側面で独自に分算処理を行う必要がある点が少し手間がかかる点です。
    • 汎用的なルーティン(任意の周波数と持続時間を扱えるもの)を実現したい場合は、自分での分算器を用意する必要があります。
    • しかし、16KB の Spectrum では他に選択肢がなく、このルーティンを頼るほかありません。

2. 直接ブイパーの利用

BIOS ルーティンは十分に優秀ですが、独自のオシレータ関数を作成するのであれば、全く異なる原理に基づいて実装したいところです。 SID チップや Ensoniq チップの内部機構に触発されて作成した、16 ビットシステム方式に基づく周波数型の原理が利用可能です。Z80 が内蔵する 16 ビット数学処理のサポートのおかげで、6502 コードよりもはるかに実装しやすくなります。

基本思想と I/O ポート

  • 動作原理:周波数コードをカウンタに繰り返し加算し、カウンタがオーバーフローするたびにスピーカーを反転させます。
  • 注意点:他に一切干渉しないように確保する必要があります。

I/O ポート $FE は三役を担っています:

  1. 下位 3 ビット:ボーダー色を設定します(
    BORDCR
    システム変数の値を保持)。
  2. $08 ビット:テープデッキ制御時とスピーカ制御時のオーディオ出力を切り替えます。常にオンに強制します。
  3. $10 ビット:実際に操作したいスピーカーオーディオの制御用です。

実装の改善(タイミング調整)

最初はすべてを直接実装し、可能な限り分岐数を減らすアプローチから始めました。しかし、各パスが完全に同じ時間になるようにコードを見直す必要があります。

  • 問題点
    JR
    命令は分岐時 12 サイクル、非分岐時 7 サイクルかかるため、タイミング調整が困難です。
  • 解決策
    JR
    を使わず、絶対アドレス指定の
    JP
    バージョンを使用します。
    • 条件付きであっても常に 10 サイクルという絶妙なタイミング特性を持ちます。

これにより大幅に簡素化され、遅延分岐は二つの NOP とメインラインへの

JP
に置き換わります。

sound:  ld      hl,0                    ; カウンタは 0 から開始
        ld      a,(\$5c48)              ; BORDCR
        and     $38                     ; ボーダー色を抽出
        rrca                            ; 下位 3 ビットへシフト
        rrca
        rrca
        or      $08                     ; テープオーディオ無効化
        di                              ; IRQ による割り込みを抑制
        push    af
.loop:  pop     af
        add     hl,de                   ; 周波数をカウンタに追加
        jp      nc,2F                   ; オーバーフローした場合…
        xor     $10                     ; …スピーカー出力反転
        out     (\$fe),a                ; +7 = 14 サイクル (JP 非分岐)
1       dec     bc                      ; タイマー減算
        push    af                      ; 0 チェック
        ld      a,b
        or      c
        jr      nz,.loop
        pop     af                      ; クリーナップ
        ei
        ret
2       nop                             ; オーバーフローなし場合、18 サイクル待機 (JP 分岐 + NOP×2)
        nop
        jp      1B

性能と問題点

  • 合計サイクル:反復当たり 84 サイクル
  • 周波数制御:3Hz 以上、ほぼ 100kHz までの線形制御が可能で、十分に性能は良好です。
  • 持続時間の限界約 1.5 秒までしかありません(理想的とは言えません)。
  • 音質の問題:生成されるトーンは音質が極めて悪く、ピッチが大きく外れ、タイミングも不整合であり、ガタガタしたりワブルしたりします。

問題の原因と解決策

問題は初期 Spectrum では $4000–$7FFF レンジアに限定されていますが、16K Spectrum ではこれが全 RAM を占めるためこの技術は不可能となります。さらに、スタックポインタの位置も影響します(

CLEAR
コマンドによってスタックポインタが押し下げられ、メモリアクセス待機状態の影響を受けます)。

以下の改善を行いました:

  • RAM の上位に 1 バイトを確保してグローバル変数として直接使用し、スタックの位置を特定する必要を取り消しました。
  • ループを展開し、duration コードを半分のサイズにしました(BPM 100 で全音符は 2.4 秒持続)。

以下が再生ルーティンの最終コードです:

sound:  ld      hl,0
        ld      a,(\$5c48)              ; BORDCR
        and     $38
        rrca
        rrca
        rrca
        or      $08
        di
.lp:    add     hl,de                   ; +11 = 11
        jp      nc,2F                   ; +10 = 21
        xor     $10                     ; + 7 = 28
        out     (\$fe),a                ; +11 = 39
1       nop                             ; + 4 = 43
        nop                             ; + 4 = 47
        nop                             ; + 4 = 51
        nop                             ; + 4 = 55
        nop                             ; + 4 = 59
        nop                             ; + 4 = 63
        nop                             ; + 4 = 67
        nop                             ; + 4 = 71
        nop                             ; + 4 = 75
        nop                             ; + 4 = 79
        jp      3F                      ; +10 = 89
3       add     hl,de                   ; +11 = 11
        jp      nc,5F                   ; +10 = 21
        xor     $10                     ; + 7 = 28
        out     (\$fe),a                ; +11 = 39
4       dec     bc                      ; + 6 = 45
        ld      (.scratch),a            ; +13 = 58
        ld      a,b                     ; + 4 = 62
        or      c                       ; + 4 = 66
        ld      a,(.scratch)            ; +13 = 79
        jp      nz,.lp                  ; +10 = 89
5       ei
        ret
2       nop                             ; + 4 = 25
        nop                             ; + 4 = 29
        jp      1B                      ; +10 = 39
.scratch # 1

スケールを再生するプログラムも完成しました:

        org     $8000
        map     \$9000                  ; スタック位置回避用マップ
        ld      b,8
        ld      hl,scale
loop:   ld      e,(hl)
        inc     hl
        ld      d,(hl)
        inc     hl
        push    hl
        push    bc
        ld      bc,\$2000               ; スタックポインタの位置調整
        call    sound
        pop     bc
        pop     hl
        djnz    loop
        ret
scale:  dw      \$0367,\$03d2,\$044a,\$048b,\$051a,\$05ba,\$066e,\$06cf

3. AY-3 サウンドチップのプログラミング

AY-3-8910 は以前にも登場しましたが、Spectrum 128 と以降のモデルでは新知見があります。

  • 書き込み方法の違い
    • まずポート $FFFD にレジスタ番号を書き、次にポート $BFFD に値を書きます。
  • 周波数計算式の変化
    • チップを駆動するメインクロックが 4MHz から 3.5469 MHzに変更されているためです。
    • 周波数 $f$ Hz のコードは:
      3546900/(32f)
  • エンベロープ長計算式
    • 長さ $t$ 秒のエンベロープに対するコードは:
      3546900/(512t)

これにより、以前の記事の内容を参照しつつも、これらのパラメータ変更のみで AY チップを使用できます。

簡易関数とマクロ

以下の簡易関数

ayreg
を作成しました。これはバイト D をレジスタ A に書き込む処理です。

ayreg:  ld      bc,\$fffd               ; AY-3 インデックスポート
        out     (c),a                   ; レジスタ番号書き込み
        ld      b,\$bf                  ; AY-3 バリューポート
        ld      a,d                     ; 値を A に
        out     (c),a                   ; 値書き込み
        ret

さらに、データが定数かポインタから読み取るかに関わらず呼び出しを容易にするためのマクロ

AY
も作成しました。

macro   AY      index,val:(hl)
        ld      a,index                 ; レジスタ番号
        ld      d,val                   ; 値 (または HL ポインタ)
        call    ayreg
endmacro

これによりエンベロープシステムを利用しても、メインコードが最も短くなりました。

        org     \$7000

        ;; AY-3 ボイス初期化
        AY      \$0b,\$10                ; エンベロープ長さ: 1 秒
        AY      \$0c,\$1b
        AY      \$08,\$10                ; チャンネル A でエンベロープ使用

        ld      b,8
        ld      hl,scale
1       push    bc
        AY      \$00                     ; (HL) テーブルから周波数読み込み
        inc     hl                      ; ポインタを進める
        AY      \$01
        inc     hl
        AY      \$0d,\$09                ; 減衰エンベロープ開始
        AY      \$07,\$fe                ; チャンネル A 有効化
        call    pause                   ; その後半秒待つ
        pop     bc
        djnz    1B

        AY      \$07,\$ff                ; チャンネル A 無効化
        ret

pause:  push    af                      ; 25 フレーム待機
        push    hl
        ld      hl,\$5c78               ; FRAMES リザージメント地点
        ld      a,(hl)
        add     25
1       halt
        cp      (hl)
        jr      nz,1B
        pop     hl
        pop     af
        ret

scale:  dw      \$01a7,\$0179,\$0150,\$013d,\$011a,\$00fb,\$00e0,\$00d3

これを使って何ができるか

  • ブイパー(スピーカー)

    • 主に、実行中に動作を一時停止しても問題ないほど短い効果音やジングルに限定されます。
    • アップル II のサウンド利用とほぼ同様の使い方です。
    • PC スピーカーも類似の回路を持っていましたが、専用の中断と独立したタイマーで駆動できるため、システム全体を占める必要がありませんでした。
  • AY-3 チップ

    • 主に自律的に動作し、音楽ドライバや環境効果音にも容易に対応できます。
    • 私が検討したシステムの中では、これには Atari STだけでなく MSX リーンも含まれます。

同じ日のほかのニュース

一覧に戻る →

2026/08/04 6:13

LLM は専門性を報酬とする

## 日本語翻訳: 大規模言語モデル(LLM)は、CSS など基本的なデジタルタスクへの参入障壁を下げていますが、深いドメイン知識の必要性を排除するものではありません。一般的に応用提示技術(generalist prompting techniques)を習得すれば真の価値を引き出せるという一般的な誤解がありますが、複雑な問題解決には特定の分野の知識が不可欠であり、それによって AI を効果的に導く必要があります。数学者のテレンス・ tao の LLM に関する研究に示されるように、専門的な成果は簡潔であるといったスタイル上のヒントではなく、真の理解から生じます。分野に対する親和性がない場合、ユーザーは出力を検証したり、モデルを高度な解決策へと導いたりすることができず、質問の工夫がいくら手巧くてもその限りではありません。著者は、トークンが無限にあっても、非専門家は Tao 氏のような複雑な数学問題においては彼のレベルには達できないと指摘しており、分野知識こそが決定的な要因であることを強調しています。したがって、モデルがさらに強くなるにつれて、人間が正確な要件を伝達し結果を検証するという役割がボトルネックとなります。そのためには、組織は平均的な成果を超えようとする場合、特別な訓練への投資や専門家を採用することが必要であり、AI 統合の未来は汎用的なインターネット検索スキルよりも、制約を定義し高品質な結果を確保するために特定分野での卓越した知識を育成することによって支えられるでしょう。

2026/08/03 23:15

デベロッパーツールのオープンソース化が必須です。

## 日本語翻訳: 人工知能(AI)エージェントは、大規模なユーザーコミュニティや複雑な設定ファイルに依存せずに個々の作成者がパーソナライズされたアプリケーションを構築することを可能にするため、ソフトウェア開発を変革しています。VS Code の拡張機能や vimdiff といった従来の API はリアルタイムでのファイル変更やバックグラウンド処理で苦戦するのに対し、Shelley とような AI エージェントは、上流リリースとの nightly スインジングや人間のレビュー前のコードのプリプロセスなどの複雑なタスクを自動的に処理します。これは、過去 5 年の間にエンジニアが高い維持コストと疑わしい投資対効果のためにカスタムツールを廃棄することが多かった時代から、現在、かつて高価なプラグインシステムを必要としたか多くのユーザーにアモルタイズされた機能が単一ユーザーのために瞬時に組み立てられることへの大きなシフトを示しています。著者は "meat.dev" というツールを作成することでこれを例示しました。このツールは大規模言語モデル(LLM)を使用して、差分からインポートやボイラープレートなど重要なコードを取り除き、開発者がコアアーキテクチャとエッジケース(「the meat」)に集中できるようにします。Shelley 内の発見可能なスキルとして構築されたこのエージェントは、単一のプロンプトでバックグラウンドスインジングなどの複雑なロジックを統合することを可能にし、手動のコマンドライン実行の必要性を排除します。さらに、エージェントによるパーソナライゼーションは学習曲線を劇的に削減し、ソリューションが「機能しているように見える」場合、大規模なレビューなしに小規模チームや個人開発者向けのカスタムソフトウェア(例:セルフホストされたブログ)を可能にします。Claude Code などのクローズドソースツールはソースコードへのアクセスを欠いているのに対し、オープンソースのエージェントはハードコーディングされた値の直接修正や Monobit を通じたビットマップフォントのようなカスタムアセットの統合、またはオンデマンドでの固有リソースの生成を可能にします。このシフトは、開発をレガシーなプラグインエコシステムと設定中心のワークフローから遠ざけ、自動化が効率的に日常運用を管理する一方で人間がコアアーキテクチャに完全に集中する未来へと導きます。

2026/08/04 2:08

より小さく、高速で、安全に:Kim i と G L M を大規模に展開するための実行方法

## Japanese Translation: Workers AI は、Cloudflare のインフラストラクチャ上で大規模な AI モデルの提供を進めており、NVIDIA Blackwell GPU と SGLang フレームワークを活用することでコストを大幅に削減するとともに速度を向上させながら精度を維持しています。本ソリューションは、モデル重みの圧縮、KV キャッシュメモリへの量子化、共有メモリの保護を実現するための整合性チェックという 3 つの中核技術を採用しています。 モデル重みについては、Workers AI がハイブリッド戦略を採用しており、応答のデコードには低精度の INT4 形式を使用します(GLM モデルでは約 60% のメモリ使用量削減を実現しながら、全精度重みから機能的不可能区別性 を維持)。一方、初期処理には高精度な形式を留保しています。KV キャッシュについては、BF16 から 8 ビット FP8 への量子化によりメモリサイズが半分になり、コンテキスト容量が倍増します(例えば、約 137 万トークンの対応が可能になり、従来の約 686 千トークンから)。MMLU や GSM8K などの主要なベンチマークにおける精度劣化はありません。 莫大な同時接続下での安定性を確保するため、Workers AI は共有 KV キャッシュに対して汎用整合性チェックを実装しており、数百件のリクエストが物理メモリページを共有する際のエラーを防いでいます。これにより、スループットおよびレイテンシに対するオーバーヘッドは 1% も未満です。これらの最適化により、同時接続制限が倍増し(例えば、64 つの同時リクエストへの対応が可能になり、従来の 32 から)、運用コストを約 30% 削減するとともに、モデルの信頼性を損なうことなくデコード速度を大幅に向上させることが可能になりました。技術が進化するにつれ、Workers AI は効率的なグローバル展開を実現するために新たな精度形式の検証を継続しています。

ZX スペクトル システムツアー:サウンド | そっか~ニュース