/* Copyright 2006 Theo Berkau Copyright (C) 2006-2010 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef SPU_H #define SPU_H #include #include #include #include "types.h" #include "matrix.h" #include "emufile.h" #include "metaspu/metaspu.h" #define SNDCORE_DEFAULT -1 #define SNDCORE_DUMMY 0 #define CHANSTAT_STOPPED 0 #define CHANSTAT_PLAY 1 //who made these static? theyre used in multiple places. //inline uint32_t sputrunc(float f) { return u32floor(f); } //inline uint32_t sputrunc(double d) { return u32floor(d); } inline int32_t spumuldiv7(int32_t val, uint8_t multiplier) { assert(multiplier <= 127); return multiplier == 127 ? val : ((val * multiplier) >> 7); } enum SPUInterpolationMode { SPUInterpolation_None = 0, SPUInterpolation_Linear = 1, SPUInterpolation_Cosine = 2 }; struct SoundInterface_struct { int id; const char *Name; int (*Init)(int buffersize); void (*DeInit)(); void (*UpdateAudio)(int16_t *buffer, uint32_t num_samples); uint32_t (*GetAudioSpace)(); void (*MuteAudio)(); void (*UnMuteAudio)(); void (*SetVolume)(int volume); void (*ClearBuffer)(); }; extern SoundInterface_struct SNDDummy; extern SoundInterface_struct SNDFile; extern int SPU_currentCoreNum; struct channel_struct { channel_struct() {} uint32_t num; uint8_t vol; uint8_t datashift; uint8_t hold; uint8_t pan; uint8_t waveduty; uint8_t repeat; uint8_t format; uint8_t keyon; uint8_t status; uint32_t addr; uint16_t timer; uint16_t loopstart; uint32_t length; uint32_t totlength; double double_totlength_shifted; union { int8_t *buf8; int16_t *buf16; }; double sampcnt; double sampinc; // ADPCM specific uint32_t lastsampcnt; int16_t pcm16b, pcm16b_last; int16_t loop_pcm16b; int32_t index; int loop_index; uint16_t x; int16_t psgnoise_last; }; class SPUFifo { public: SPUFifo(); void enqueue(int16_t val); int16_t dequeue(); int16_t buffer[16]; int32_t head,tail,size; //void save(EMUFILE* fp); bool load(EMUFILE* fp); void reset(); }; class SPU_struct { public: SPU_struct(int buffersize); uint32_t bufpos; uint32_t buflength; int32_t *sndbuf; int32_t lastdata; //the last sample that a channel generated int16_t *outbuf; uint32_t bufsize; channel_struct channels[16]; //registers struct REGS { REGS() : mastervol(0) , ctl_left(0) , ctl_right(0) , ctl_ch1bypass(0) , ctl_ch3bypass(0) , masteren(0) , soundbias(0) {} uint8_t mastervol; uint8_t ctl_left, ctl_right; uint8_t ctl_ch1bypass, ctl_ch3bypass; uint8_t masteren; uint16_t soundbias; enum LeftOutputMode { LOM_LEFT_MIXER=0, LOM_CH1=1, LOM_CH3=2, LOM_CH1_PLUS_CH3=3 }; enum RightOutputMode { ROM_RIGHT_MIXER=0, ROM_CH1=1, ROM_CH3=2, ROM_CH1_PLUS_CH3=3 }; struct CAP { CAP() : add(0), source(0), oneshot(0), bits8(0), active(0), dad(0), len(0) {} uint8_t add, source, oneshot, bits8, active; uint32_t dad; uint16_t len; struct Runtime { Runtime() : running(0), curdad(0), maxdad(0) {} uint8_t running; uint32_t curdad; uint32_t maxdad; double sampcnt; SPUFifo fifo; } runtime; } cap[2]; } regs; void reset(); ~SPU_struct(); void KeyOff(int channel); void KeyOn(int channel); void KeyProbe(int channel); void ProbeCapture(int which); void WriteByte(uint32_t addr, uint8_t val); uint8_t ReadByte(uint32_t addr); uint16_t ReadWord(uint32_t addr); uint32_t ReadLong(uint32_t addr); void WriteWord(uint32_t addr, uint16_t val); void WriteLong(uint32_t addr, uint32_t val); //kills all channels but leaves SPU otherwise running normally void ShutUp(); }; int SPU_ChangeSoundCore(int coreid, int buffersize); //SoundInterface_struct *SPU_SoundCore(); void SPU_ReInit(); int SPU_Init(int coreid, int buffersize); //void SPU_Pause(int pause); //void SPU_SetVolume(int volume); void SPU_SetSynchMode(ESynchMode mode, ESynchMethod method); //void SPU_ClearOutputBuffer(); void SPU_Reset(); void SPU_DeInit(); void SPU_KeyOn(int channel); void SPU_WriteByte(uint32_t addr, uint8_t val); void SPU_WriteWord(uint32_t addr, uint16_t val); void SPU_WriteLong(uint32_t addr, uint32_t val); uint8_t SPU_ReadByte(uint32_t addr); uint16_t SPU_ReadWord(uint32_t addr); uint32_t SPU_ReadLong(uint32_t addr); void SPU_Emulate_core(); void SPU_Emulate_user(bool mix = true); extern SPU_struct *SPU_core, *SPU_user; extern int spu_core_samples; //void spu_savestate(EMUFILE* os); bool spu_loadstate(EMUFILE* is, int size); /*enum WAVMode { WAVMODE_ANY = -1, WAVMODE_CORE = 0, WAVMODE_USER = 1 };*/ /*class WavWriter { public: WavWriter(); bool open(const std::string & fname); void close(); void update(void* soundData, int numSamples); bool isRecording() const; WAVMode mode; private: FILE *spufp; };*/ //void WAV_End(); //bool WAV_Begin(const char* fname, WAVMode mode=WAVMODE_CORE); //bool WAV_IsRecording(WAVMode mode=WAVMODE_ANY); //void WAV_WavSoundUpdate(void* soundData, int numSamples, WAVMode mode=WAVMODE_CORE); // we should make this configurable eventually // but at least defining it somewhere is probably a step in the right direction #define DESMUME_SAMPLE_RATE 44100 //#define DESMUME_SAMPLE_RATE 48000 #endif