move more globals to PicoInterface
[picodrive.git] / pico / pico / xpcm.c
CommitLineData
ef4eb506 1/*
cff531af 2 * PicoDrive
3 * (C) notaz, 2008
4 *
5 * This work is licensed under the terms of MAME license.
6 * See COPYING file in the top-level directory.
7 *
ef4eb506 8 * The following ADPCM algorithm was stolen from MAME aica driver.
9 * I'm quite sure it's not the right one, but it's the
10 * best sounding of the ones that I tried.
11 */
12
efcba75f 13#include "../pico_int.h"
ef4eb506 14
15#define ADPCMSHIFT 8
16#define ADFIX(f) (int) ((double)f * (double)(1<<ADPCMSHIFT))
17
18/* limitter */
19#define Limit(val, max, min) { \
20 if ( val > max ) val = max; \
21 else if ( val < min ) val = min; \
22}
23
ed367a3f 24static const int TableQuant[8] =
ef4eb506 25{
26 ADFIX(0.8984375),
27 ADFIX(0.8984375),
28 ADFIX(0.8984375),
29 ADFIX(0.8984375),
30 ADFIX(1.19921875),
31 ADFIX(1.59765625),
32 ADFIX(2.0),
33 ADFIX(2.3984375)
34};
35
36// changed using trial and error..
213c16ad 37//static const int quant_mul[16] = { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15 };
ed367a3f 38static const int quant_mul[16] = { 1, 3, 5, 7, 9, 11, 13, -1, -1, -3, -5, -7, -9, -11, -13, -15 };
39
40static int sample = 0, quant = 0, sgn = 0;
41static int stepsamples = (44100<<10)/16000;
ef4eb506 42
ef4eb506 43
44PICO_INTERNAL void PicoPicoPCMReset(void)
45{
ed367a3f 46 sample = sgn = 0;
ef4eb506 47 quant = 0x7f;
48 memset(PicoPicohw.xpcm_buffer, 0, sizeof(PicoPicohw.xpcm_buffer));
49}
50
213c16ad 51PICO_INTERNAL void PicoPicoPCMRerate(int xpcm_rate)
ed367a3f 52{
6311a3ba 53 stepsamples = (PicoIn.sndRate<<10)/xpcm_rate;
ed367a3f 54}
55
213c16ad 56#define XSHIFT 6
ef4eb506 57
58#define do_sample() \
59{ \
213c16ad 60 int delta = quant * quant_mul[srcval] >> XSHIFT; \
61 sample += delta - (delta >> 2); /* 3/4 */ \
ef4eb506 62 quant = (quant * TableQuant[srcval&7]) >> ADPCMSHIFT; \
63 Limit(quant, 0x6000, 0x7f); \
213c16ad 64 Limit(sample, 32767*3/4, -32768*3/4); \
ef4eb506 65}
66
67PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo)
68{
69 unsigned char *src = PicoPicohw.xpcm_buffer;
70 unsigned char *lim = PicoPicohw.xpcm_ptr;
ed367a3f 71 int srcval, needsamples = 0;
ef4eb506 72
ed367a3f 73 if (src == lim) goto end;
ef4eb506 74
75 for (; length > 0 && src < lim; src++)
76 {
77 srcval = *src >> 4;
78 do_sample();
79
80 for (needsamples += stepsamples; needsamples > (1<<10) && length > 0; needsamples -= (1<<10), length--) {
ed367a3f 81 *buffer++ += sample;
ef4eb506 82 if (stereo) { buffer[0] = buffer[-1]; buffer++; }
83 }
84
85 srcval = *src & 0xf;
86 do_sample();
87
88 for (needsamples += stepsamples; needsamples > (1<<10) && length > 0; needsamples -= (1<<10), length--) {
ed367a3f 89 *buffer++ += sample;
ef4eb506 90 if (stereo) { buffer[0] = buffer[-1]; buffer++; }
91 }
ed367a3f 92
93 // lame normalization stuff, needed due to wrong adpcm algo
94 sgn += (sample < 0) ? -1 : 1;
95 if (sgn < -16 || sgn > 16) sample -= sample >> 5;
ef4eb506 96 }
97
98 if (src < lim) {
99 int di = lim - src;
100 memmove(PicoPicohw.xpcm_buffer, src, di);
101 PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer + di;
fa22af4c 102 elprintf(EL_PICOHW, "xpcm update: over %i", di);
ed367a3f 103 // adjust fifo
104 PicoPicohw.fifo_bytes = di;
105 return;
ef4eb506 106 }
ed367a3f 107
fa22af4c 108 elprintf(EL_PICOHW, "xpcm update: under %i", length);
ed367a3f 109 PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer;
110
111end:
112 if (stereo)
113 // still must expand SN76496 to stereo
114 for (; length > 0; buffer+=2, length--)
115 buffer[1] = buffer[0];
116
117 sample = sgn = 0;
118 quant = 0x7f;
ef4eb506 119}
120