Annotation of nono/vm/sound.h, revision 1.1.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.