Advertisement
Xeeynamo

PS1 SPU-ADPCM decoder

Oct 30th, 2015
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 1.74 KB | None | 0 0
  1. // PS1 SPU-ADPCM decoder
  2. // A lot of nooooise :'( probably the algorithm is wrong
  3. // https://dl.dropboxusercontent.com/u/26695489/adpcm/AUDIO.ADPCM
  4.  
  5. #include <stdio.h>
  6. #include <stdint.h>
  7. #include <assert.h>
  8.  
  9. typedef struct {
  10.     int32_t s_1;
  11.     int32_t s_2;
  12. } AdpcmState;
  13.  
  14. const int32_t FILTER0[5] = { 0, 60, 115, 98, 122 };
  15. const int32_t FILTER1[5] = { 0, 0, -52, -55, -60 };
  16. const float CurrentVolume = 0.0002f;
  17.  
  18. int32_t Clamp(int32_t n, int32_t min, int32_t max)
  19. {
  20.     if (n < min) return min;
  21.     if (n > max) return max;
  22.     return n;
  23. }
  24. int32_t Volume(int32_t n, float volume)
  25. {
  26.     return (int32_t)((float)n * volume);
  27. }
  28.  
  29. void Decode(int16_t *pOut, uint8_t *pIn, AdpcmState *state)
  30. {
  31.     int shift = (*pIn & 0x0F);
  32.     int filter = (*pIn >> 4) & 0x0F;
  33.     int flags = pIn[1];
  34.  
  35.     int32_t f0 = FILTER0[filter];
  36.     int32_t f1 = FILTER1[filter];
  37.     for (int i = 2, nSample = 0; i < 16; i++)
  38.     {
  39.         int data = pIn[i];
  40.         int nl = (signed)((data << 28) & 0xF0000000) >> shift;
  41.         int nh = (signed)((data << 24) & 0xF0000000) >> shift;
  42.         nl += ((f0 * state->s_1) + (f1 * state->s_2) + 32) >> 6;
  43.         nh += ((f0 * nl) + (f1 * state->s_1) + 32) >> 6;
  44.         state->s_2 = nl;
  45.         state->s_1 = nh;
  46.         pOut[nSample++] = Clamp(Volume(nl, CurrentVolume), -32768, +32767);
  47.         pOut[nSample++] = Clamp(Volume(nh, CurrentVolume), -32768, +32767);
  48.     }
  49. }
  50.  
  51. int main()
  52. {
  53.     uint8_t buf[16];
  54.     int16_t pcm[28];
  55.     AdpcmState state;
  56.     FILE *fIn = fopen("AUDIO.ADPCM", "rb");
  57.     FILE *fOut = fopen("AUDIO.PCM", "wb");
  58.     assert(fIn != NULL);
  59.     assert(fOut != NULL);
  60.     state.s_1 = state.s_2 = 0;
  61.     while (fread(buf, sizeof(buf), 1, fIn) == 1)
  62.     {
  63.         Decode(pcm, buf, &state);
  64.         fwrite(pcm, sizeof(pcm), 1, fOut);
  65.     }
  66.     fclose(fOut);
  67.     fclose(fIn);
  68. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement