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