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   CurSample = 0x0800;
42 
43   StepSizeIndex = 0;
44  }
~OKIADPCM_Decoder()45  ~OKIADPCM_Decoder()
46  {
47 
48  }
49 
GetSample(void)50  INLINE uint16 GetSample(void)
51  {
52   return(CurSample);
53  }
54 
SetSample(uint16 new_sample)55  INLINE void SetSample(uint16 new_sample)
56  {
57   CurSample = new_sample;
58  }
59 
GetSSI(void)60  INLINE uint8 GetSSI(void)
61  {
62   return(StepSizeIndex);
63  }
64 
SetSSI(uint8 new_ssi)65  INLINE void SetSSI(uint8 new_ssi)
66  {
67   StepSizeIndex = new_ssi;
68  }
69 
70  // DecodeDelta returns the coded delta for the given nibble and (previous) predictor.
71  // It will not wrap nor saturate the returned value, and CurSample is not updated.
DecodeDelta(const uint8 nibble)72  INLINE int32 DecodeDelta(const uint8 nibble)
73  {
74   int32 ret = OKIADPCM_DeltaTable[StepSizeIndex][nibble];
75 
76   StepSizeIndex += OKIADPCM_StepIndexDeltas[nibble];
77 
78   if(StepSizeIndex < 0)
79    StepSizeIndex = 0;
80 
81   if(StepSizeIndex > 48)
82    StepSizeIndex = 48;
83 
84   return(ret);
85  }
86 
87  // This function will return the full 12-bits, it's up to the caller to
88  // truncate as necessary(MSM5205 only has a 10-bit D/A, MSM5218 has a 12-bit D/A)
Decode(const uint8 nibble)89  INLINE uint16 Decode(const uint8 nibble)
90  {
91   CurSample += DecodeDelta(nibble);
92 
93   if(CHIP_TYPE == OKIADPCM_MSM5205)
94   {
95    CurSample &= 0xFFF;
96   }
97   else if(CHIP_TYPE == OKIADPCM_MSM5218)
98   {
99    if(CurSample > 0xFFF)
100     CurSample = 0xFFF;
101    if(CurSample < 0)
102     CurSample = 0;
103   }
104   return(CurSample);
105  }
106 
107  private:
108  int32 CurSample;
109  int32 StepSizeIndex;
110 };
111 #endif
112