--- nono/vm/adpcm.h 2026/04/29 17:05:51 1.1.1.5 +++ nono/vm/adpcm.h 2026/04/29 17:06:01 1.1.1.7 @@ -13,7 +13,8 @@ #include "device.h" class DMACDevice; -class PPIDevice; +class SoundRenderer; +class SoundTrack; class ADPCMDevice : public IODevice { @@ -38,8 +39,14 @@ class ADPCMDevice : public IODevice void SetClock(bool); // DMAC から呼ばれる。 - void AssertDACK(bool tc); - void NegateDACK(); + void AssertDACK(); + + // PPI + bool GetPanOutL() const { return panout_L; } + bool GetPanOutR() const { return panout_R; } + void SetPanOutL(bool on); + void SetPanOutR(bool on); + void SetRate(uint32 idx); protected: // BusIO インタフェース @@ -50,21 +57,66 @@ class ADPCMDevice : public IODevice bool PokePort(uint32 offset, uint32 data); private: + DECLARE_MONITOR_SCREEN(MonitorScreen); + + uint32 GetSTAT() const; void StartPlay(); + void StopPlay(); + void WriteData(uint32 data); + void CalcRate(); void EventCallback(Event *); + void DecodeADPCM(uint32 data); + void WritePCM(uint64 vtime, int16 target); + + uint32 pcm2adpcm_step(int16 pcm); + int16 adpcm2pcm_step(uint32 data); + inline uint32 adpcm_encode(int32 dn); + inline int32 adpcm_decode(uint32 data, int32 xn); + inline void adpcm_calcstep(uint32 data); + bool playing {}; - bool dack {}; - int clk {}; - int div {}; + int clkMHz {}; // 入力クロック[MHz] (4 or 8) + int div {}; // 512, 768, 1024 + + bool panout_L {}; + bool panout_R {}; + + // 選択周波数での 1フレームにかかる時間 [tsec] + uint64 guest_frame_tsec {}; + + // 周波数 + uint32 freq {}; + + // データバッファ(1バイト) + uint8 databuf {}; + + // ADPCM<->PCM 変換 + int32 xprev {}; + int stepidx {}; + + // 最後に書き込んだサンプル値 (線形補間用) + int16 pcm0 {}; + + // ミキサー周波数での1フレームにかかる時間 [tsec] + uint64 mixer_frame_tsec {}; + + // ミキサー周波数にアップスキャンするための倍率。 + // 15625 Hz なら 4(倍)。 + uint scale_factor {}; DMACDevice *dmac {}; - PPIDevice *ppi {}; + SoundRenderer *sound {}; + SoundTrack *track {}; Event *event {}; + Monitor *monitor {}; + + static const int adpcm_stepadj[16]; + static const int32 adpcm_stepsize[49]; }; -static inline ADPCMDevice *GetADPCMDevice() { +inline ADPCMDevice *GetADPCMDevice() { return Object::GetObject(OBJ_ADPCM); }