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