1 /* Mednafen - Multi-system Emulator 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program; if not, write to the Free Software 15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 */ 17 18 #ifndef __MDFN_OKIADPCM_H 19 #define __MDFN_OKIADPCM_H 20 21 // PC-FX ADPCM decoder not finished! 22 23 typedef enum 24 { 25 OKIADPCM_MSM5205 = 0, 26 OKIADPCM_MSM5218 = 1, 27 OKIADPCM_COUNT 28 } OKIADPCM_Chip; 29 30 extern const int OKIADPCM_StepSizes[49]; 31 extern const int OKIADPCM_StepIndexDeltas[16]; 32 extern const int32 OKIADPCM_DeltaTable[49][16]; 33 34 template <OKIADPCM_Chip CHIP_TYPE> 35 class OKIADPCM_Decoder 36 { 37 public: 38 OKIADPCM_Decoder()39 OKIADPCM_Decoder() 40 { 41 assert(CHIP_TYPE < OKIADPCM_COUNT); 42 43 CurSample = 0x0800; 44 45 StepSizeIndex = 0; 46 } ~OKIADPCM_Decoder()47 ~OKIADPCM_Decoder() 48 { 49 50 } 51 GetSample(void)52 INLINE uint16 GetSample(void) 53 { 54 return(CurSample); 55 } 56 SetSample(uint16 new_sample)57 INLINE void SetSample(uint16 new_sample) 58 { 59 assert(new_sample <= 0xFFF); 60 CurSample = new_sample; 61 } 62 GetSSI(void)63 INLINE uint8 GetSSI(void) 64 { 65 return(StepSizeIndex); 66 } 67 SetSSI(uint8 new_ssi)68 INLINE void SetSSI(uint8 new_ssi) 69 { 70 assert(new_ssi <= 48); 71 StepSizeIndex = new_ssi; 72 } 73 74 // DecodeDelta returns the coded delta for the given nibble and (previous) predictor. 75 // It will not wrap nor saturate the returned value, and CurSample is not updated. DecodeDelta(const uint8 nibble)76 INLINE int32 DecodeDelta(const uint8 nibble) 77 { 78 int32 ret = OKIADPCM_DeltaTable[StepSizeIndex][nibble]; 79 80 StepSizeIndex += OKIADPCM_StepIndexDeltas[nibble]; 81 82 if(StepSizeIndex < 0) 83 StepSizeIndex = 0; 84 85 if(StepSizeIndex > 48) 86 StepSizeIndex = 48; 87 88 return(ret); 89 } 90 91 // This function will return the full 12-bits, it's up to the caller to 92 // truncate as necessary(MSM5205 only has a 10-bit D/A, MSM5218 has a 12-bit D/A) Decode(const uint8 nibble)93 INLINE uint16 Decode(const uint8 nibble) 94 { 95 CurSample += DecodeDelta(nibble); 96 97 if(CHIP_TYPE == OKIADPCM_MSM5205) 98 { 99 CurSample &= 0xFFF; 100 } 101 else if(CHIP_TYPE == OKIADPCM_MSM5218) 102 { 103 if(CurSample > 0xFFF) 104 CurSample = 0xFFF; 105 if(CurSample < 0) 106 CurSample = 0; 107 } 108 return(CurSample); 109 } 110 111 private: 112 int32 CurSample; 113 int32 StepSizeIndex; 114 }; 115 116 template <OKIADPCM_Chip CHIP_TYPE> 117 class OKIADPCM_Encoder 118 { 119 public: 120 OKIADPCM_Encoder()121 OKIADPCM_Encoder() 122 { 123 Accum = 0x800; 124 StepSizeIndex = 0; 125 } 126 ~OKIADPCM_Encoder()127 ~OKIADPCM_Encoder() 128 { 129 130 } 131 EncodeSample(uint16 in_sample)132 uint8 EncodeSample(uint16 in_sample) 133 { 134 uint8 nibble = 0; 135 int32 sample_delta = in_sample - Accum; 136 int piece; 137 138 piece = (abs(sample_delta) * 4 / OKIADPCM_StepSizes[StepSizeIndex]); 139 if(piece > 0x7) 140 piece = 0x7; 141 142 nibble = ((uint32)(sample_delta >> 31) & 0x8) | piece; 143 144 // Update Accum and StepSizeIndex! 145 Accum += OKIADPCM_DeltaTable[StepSizeIndex][nibble]; 146 StepSizeIndex += OKIADPCM_StepIndexDeltas[nibble]; 147 148 if(Accum > 0xFFF) Accum = 0xFFF; 149 if(Accum < 0) Accum = 0; 150 151 if(StepSizeIndex < 0) 152 StepSizeIndex = 0; 153 154 if(StepSizeIndex > 48) 155 StepSizeIndex = 48; 156 157 return(nibble); 158 } 159 160 private: 161 int32 Accum; 162 int32 StepSizeIndex; 163 OKIADPCM_Chip ChipType; 164 }; 165 #endif 166