--- nono/vm/adpcm.h 2026/04/29 17:05:14 1.1 +++ nono/vm/adpcm.h 2026/04/29 17:05:55 1.1.1.6 @@ -11,13 +11,16 @@ #pragma once #include "device.h" -#include "event.h" + +class DMACDevice; +class SoundRenderer; +class SoundTrack; class ADPCMDevice : public IODevice { using inherited = IODevice; - static const int baseaddr = 0xe92000; + static const uint32 baseaddr = 0xe92000; static const uint8 STAT_PLAY = 0x80; @@ -27,35 +30,93 @@ class ADPCMDevice : public IODevice public: ADPCMDevice(); - virtual ~ADPCMDevice() override; + ~ADPCMDevice() override; + bool Init() override; void ResetHard(bool poweron) override; // CT1 によるクロック切り替え。OPM から呼ばれる。 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 インタフェース static const uint32 NPORT = 2; - uint64 Read(uint32 offset); - uint64 Write(uint32 offset, uint32 data); - uint64 Peek(uint32 offset); + busdata ReadPort(uint32 offset); + busdata WritePort(uint32 offset, uint32 data); + busdata PeekPort(uint32 offset); + bool PokePort(uint32 offset, uint32 data); private: - void StartPlay(); + DECLARE_MONITOR_CALLBACK(MonitorUpdate); - void EventCallback(Event&); + 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フレームにかかる時間 [nsec] + uint64 guest_frame_nsec {}; + + // 周波数 + uint32 freq {}; + + // データバッファ(1バイト) + uint8 databuf {}; + + // ADPCM<->PCM 変換 + int32 xprev {}; + int stepidx {}; + + // 最後に書き込んだサンプル値 (線形補間用) + int16 pcm0 {}; + + // ミキサー周波数での1フレームにかかる時間 [nsec] + uint64 mixer_frame_nsec {}; + + // ミキサー周波数にアップスキャンするための倍率。 + // 15625 Hz なら 4(倍)。 + uint scale_factor {}; + + DMACDevice *dmac {}; + SoundRenderer *sound {}; + SoundTrack *track {}; + + Event *event {}; + Monitor *monitor {}; - Event event { this }; + static const int adpcm_stepadj[16]; + static const int32 adpcm_stepsize[49]; }; -extern ADPCMDevice *gADPCM; +static inline ADPCMDevice *GetADPCMDevice() { + return Object::GetObject(OBJ_ADPCM); +}