Annotation of nono/vm/sound.h, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2025 nono project
        !             4: // Licensed under nono-license.txt
        !             5: //
        !             6: 
        !             7: //
        !             8: // サウンドレンダラ
        !             9: //
        !            10: 
        !            11: #pragma once
        !            12: 
        !            13: #include "thread.h"
        !            14: #include "fixedqueue.h"
        !            15: #include <array>
        !            16: #include <condition_variable>
        !            17: #include <mutex>
        !            18: 
        !            19: class Syncer;
        !            20: class HostSoundDevice;
        !            21: 
        !            22: // 定数。
        !            23: class Sound
        !            24: {
        !            25:  public:
        !            26:        // (1フレームの)チャンネル数 (デバイスと SoundRenderer の間はステレオ固定)。
        !            27:        static constexpr int NCHAN = 2;
        !            28: 
        !            29:        // 1フレームのバイト数。
        !            30:        static constexpr size_t FRAME_BYTES = NCHAN * sizeof(int16);
        !            31: 
        !            32:        // 1ブロックの時間。
        !            33:        // ADPCM の制約からこれ以上小さくは出来ない(し大きくする必要もない)。
        !            34:        static constexpr uint64 BLK_NSEC = 40_msec;
        !            35: 
        !            36:        // サウンドソースのブロック数。
        !            37:        // ダブルバッファ方式なので 2。
        !            38:        static constexpr uint NSRCBLKS = 2;
        !            39: 
        !            40:        // 合成バッファのブロック数。
        !            41:        // 1ブロック境界ごとに逐次処理するので 1。
        !            42:        static constexpr uint NMIXBLKS = 1;
        !            43: 
        !            44:        // 出力バッファのブロック数。
        !            45:        // 最低 3 ブロック必要だが、2 のべき乗だとお得。
        !            46:        static constexpr uint NOUTBLKS = 4;
        !            47: };
        !            48: 
        !            49: enum SoundStat {
        !            50:        Stopped,        // デバイスは再生をしていない
        !            51:        Drained,
        !            52:        Running,        // デバイスは再生中
        !            53:        Draining,       // デバイスはこのブロック処理後に再生を停止
        !            54: };
        !            55: 
        !            56: // サウンドの 1 トラック (ソースデバイス) 分。
        !            57: class SoundTrack : private Sound
        !            58: {
        !            59:  public:
        !            60:        SoundTrack(Device *dev_, size_t frames_per_blk_);
        !            61: 
        !            62:        int16 *GetBlockBySeq(uint64 vseq);
        !            63:        int16 *GetBlockByIdx(uint32 idx);
        !            64:        int16 *AllocSeq(uint64 vseq);
        !            65:        void ClearSeq(uint64 vseq);
        !            66: 
        !            67:        // ソースデバイスを返す。
        !            68:        Device *GetDevice() const noexcept { return dev; }
        !            69: 
        !            70:        // ソースデバイス名を返す。
        !            71:        const std::string& GetName() const { return dev->GetName(); }
        !            72: 
        !            73:        // 再生状態
        !            74:        SoundStat status {};
        !            75: 
        !            76:        // レベル(L,R)。
        !            77:        std::array<double, NCHAN> dbfs {};
        !            78: 
        !            79:  private:
        !            80:        Device *dev {};
        !            81: 
        !            82:        // NBLKS 分のバッファ。
        !            83:        std::unique_ptr<int16[]> buf {};
        !            84: 
        !            85:        // buf の各ブロックが有効ならそのシーケンス。-1 なら未使用。
        !            86:        std::array<uint64, NSRCBLKS> blkseq {};
        !            87: 
        !            88:        // 1ブロックのサンプル数。
        !            89:        size_t samples_per_blk {};
        !            90: };
        !            91: 
        !            92: // サウンドレンダラ
        !            93: class SoundRenderer : public ThreadDevice, private Sound
        !            94: {
        !            95:        using inherited = ThreadDevice;
        !            96: 
        !            97:  private:
        !            98:        // ソースデバイスの最大数。2 のべき乗であること。
        !            99:        static constexpr uint32 MAX_SOUND_SOURCES       = 4;
        !           100: 
        !           101:        static constexpr uint32 REQ_TERMINATE   = 0x80000000;
        !           102:        static constexpr uint32 REQ_RECONFIG    = 0x00000001;
        !           103: 
        !           104:  public:
        !           105:        SoundRenderer();
        !           106:        ~SoundRenderer() override;
        !           107: 
        !           108:        bool Create() override;
        !           109:        void SetLogLevel(int loglevel_) override;
        !           110:        bool Init() override;
        !           111:        void ResetHard(bool poweron) override;
        !           112: 
        !           113:        SoundTrack *RegistTrack(Device *);
        !           114:        void StartPlay(SoundTrack *);
        !           115:        void StopPlay(SoundTrack *);
        !           116: 
        !           117:        uint GetMixerFreq() const noexcept { return mixerfreq; }
        !           118:        uint GetOutFrequency() const noexcept { return outfreq; }
        !           119:        uint GetOutBytesPerBlk() const noexcept;
        !           120: 
        !           121:        static void ClearDBFS(std::array<double, NCHAN>& dbFS);
        !           122: 
        !           123:  protected:
        !           124:        void ThreadRun() override;
        !           125:        void Terminate() override;
        !           126:        bool Reconfig(bool startup);
        !           127: 
        !           128:        void Callback(Event *);
        !           129: 
        !           130:        void Mix(uint64 vseq);
        !           131:        void AddPCM(int16 *dst, const int16 *src);
        !           132:        void CalcDBFS(std::array<double, NCHAN>& dbFS, const int16 *src);
        !           133: 
        !           134:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
        !           135:        void MonitorUpdateLevelMeter(TextScreen&, int x, int y,
        !           136:                const std::array<double, NCHAN> dbfs);
        !           137: 
        !           138:        // VM スレッドからの通知用。
        !           139:        uint32 request {};
        !           140:        std::mutex mtx {};
        !           141:        std::condition_variable cv {};
        !           142: 
        !           143:        // VM スレッドからの処理依頼キュー。
        !           144:        // キューにする必要ある?
        !           145:        FixedQueue<uint64, NSRCBLKS> request_q {};
        !           146: 
        !           147:        // サウンドトラック(ソース)。
        !           148:        std::vector<SoundTrack> tracks {};
        !           149: 
        !           150:        // サウンドミキサーのサンプリングレート [Hz]。
        !           151:        // サウンドトラック(ソース)もこの周波数。機種によって異なる。
        !           152:        uint mixerfreq {};
        !           153: 
        !           154:        // ミキサーバッファ 1ブロックのサンプル数。
        !           155:        size_t mixer_samples_per_blk {};
        !           156: 
        !           157:        // 合成用バッファ。
        !           158:        std::unique_ptr<int16[]> mixbuf {};
        !           159: 
        !           160:        // マスターレベル。
        !           161:        std::array<double, NCHAN> master_dbfs {};
        !           162: 
        !           163:        // 出力サンプリングレート [Hz]
        !           164:        uint outfreq {};
        !           165: 
        !           166:        // 出力バッファ 1ブロックのサンプル数。
        !           167:        size_t out_samples_per_blk {};
        !           168: 
        !           169:        // 出力バッファ。
        !           170:        std::unique_ptr<int16[]> outbuf {};
        !           171: 
        !           172:        // 現在の出力ブロック位置。
        !           173:        uint outpos {};
        !           174: 
        !           175:        // 出力キュー。バッファの先頭だけで扱う。
        !           176:        FixedQueue<const uint16 *, NOUTBLKS> output_q {};
        !           177: 
        !           178:        // 出力サンプリングレート変更指示。
        !           179:        uint request_outfreq {};
        !           180: 
        !           181:        std::unique_ptr<HostSoundDevice> hostsnd /*{}*/;
        !           182: 
        !           183:        Event *play_event {};
        !           184: 
        !           185:        Monitor *monitor {};
        !           186: 
        !           187:        Syncer *syncer {};
        !           188: };
        !           189: 
        !           190: static inline SoundRenderer *GetSoundRenderer() {
        !           191:        return Object::GetObject<SoundRenderer>(OBJ_SOUND_RENDERER);
        !           192: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.