xpcm.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  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. *
  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. #include "../pico_int.h"
  13. #define ADPCMSHIFT 8
  14. #define ADFIX(f) (int) ((double)f * (double)(1<<ADPCMSHIFT))
  15. /* limitter */
  16. #define Limit(val, max, min) { \
  17. if ( val > max ) val = max; \
  18. else if ( val < min ) val = min; \
  19. }
  20. static const int TableQuant[8] =
  21. {
  22. ADFIX(0.8984375),
  23. ADFIX(0.8984375),
  24. ADFIX(0.8984375),
  25. ADFIX(0.8984375),
  26. ADFIX(1.19921875),
  27. ADFIX(1.59765625),
  28. ADFIX(2.0),
  29. ADFIX(2.3984375)
  30. };
  31. // changed using trial and error..
  32. //static const int quant_mul[16] = { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15 };
  33. static const int quant_mul[16] = { 1, 3, 5, 7, 9, 11, 13, -1, -1, -3, -5, -7, -9, -11, -13, -15 };
  34. static int sample = 0, quant = 0, sgn = 0;
  35. static int stepsamples = (44100<<10)/16000;
  36. PICO_INTERNAL void PicoPicoPCMReset(void)
  37. {
  38. sample = sgn = 0;
  39. quant = 0x7f;
  40. memset(PicoPicohw.xpcm_buffer, 0, sizeof(PicoPicohw.xpcm_buffer));
  41. }
  42. PICO_INTERNAL void PicoPicoPCMRerate(int xpcm_rate)
  43. {
  44. stepsamples = (PsndRate<<10)/xpcm_rate;
  45. }
  46. #define XSHIFT 6
  47. #define do_sample() \
  48. { \
  49. int delta = quant * quant_mul[srcval] >> XSHIFT; \
  50. sample += delta - (delta >> 2); /* 3/4 */ \
  51. quant = (quant * TableQuant[srcval&7]) >> ADPCMSHIFT; \
  52. Limit(quant, 0x6000, 0x7f); \
  53. Limit(sample, 32767*3/4, -32768*3/4); \
  54. }
  55. PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo)
  56. {
  57. unsigned char *src = PicoPicohw.xpcm_buffer;
  58. unsigned char *lim = PicoPicohw.xpcm_ptr;
  59. int srcval, needsamples = 0;
  60. if (src == lim) goto end;
  61. for (; length > 0 && src < lim; src++)
  62. {
  63. srcval = *src >> 4;
  64. do_sample();
  65. for (needsamples += stepsamples; needsamples > (1<<10) && length > 0; needsamples -= (1<<10), length--) {
  66. *buffer++ += sample;
  67. if (stereo) { buffer[0] = buffer[-1]; buffer++; }
  68. }
  69. srcval = *src & 0xf;
  70. do_sample();
  71. for (needsamples += stepsamples; needsamples > (1<<10) && length > 0; needsamples -= (1<<10), length--) {
  72. *buffer++ += sample;
  73. if (stereo) { buffer[0] = buffer[-1]; buffer++; }
  74. }
  75. // lame normalization stuff, needed due to wrong adpcm algo
  76. sgn += (sample < 0) ? -1 : 1;
  77. if (sgn < -16 || sgn > 16) sample -= sample >> 5;
  78. }
  79. if (src < lim) {
  80. int di = lim - src;
  81. memmove(PicoPicohw.xpcm_buffer, src, di);
  82. PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer + di;
  83. elprintf(EL_PICOHW, "xpcm update: over %i", di);
  84. // adjust fifo
  85. PicoPicohw.fifo_bytes = di;
  86. return;
  87. }
  88. elprintf(EL_PICOHW, "xpcm update: under %i", length);
  89. PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer;
  90. end:
  91. if (stereo)
  92. // still must expand SN76496 to stereo
  93. for (; length > 0; buffer+=2, length--)
  94. buffer[1] = buffer[0];
  95. sample = sgn = 0;
  96. quant = 0x7f;
  97. }