6eaf91e6d468c597c820fcfedf015ca312636c66
[platform/upstream/gstreamer.git] / gst / modplug / libmodplug / load_wav.cpp
1 /*
2  * This source code is public domain.
3  *
4  * Authors: Olivier Lapicque <olivierl@jps.net>
5 */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include "stdafx.h"
12 #include "sndfile.h"
13
14 #ifndef WAVE_FORMAT_EXTENSIBLE
15 #define WAVE_FORMAT_EXTENSIBLE  0xFFFE
16 #endif
17
18 /////////////////////////////////////////////////////////////
19 // WAV file support
20
21 BOOL CSoundFile::ReadWav(const BYTE *lpStream, DWORD dwMemLength)
22 //---------------------------------------------------------------
23 {
24         DWORD dwMemPos = 0;
25         WAVEFILEHEADER *phdr = (WAVEFILEHEADER *)lpStream;
26         WAVEFORMATHEADER *pfmt = (WAVEFORMATHEADER *)(lpStream + sizeof(WAVEFILEHEADER));
27         if ((!lpStream) || (dwMemLength < (DWORD)sizeof(WAVEFILEHEADER))) return FALSE;
28         if ((phdr->id_RIFF != IFFID_RIFF) || (phdr->id_WAVE != IFFID_WAVE)
29          || (pfmt->id_fmt != IFFID_fmt)) return FALSE;
30         dwMemPos = sizeof(WAVEFILEHEADER) + 8 + pfmt->hdrlen;
31         if ((dwMemPos + 8 >= dwMemLength)
32          || ((pfmt->format != WAVE_FORMAT_PCM) && (pfmt->format != WAVE_FORMAT_EXTENSIBLE))
33          || (pfmt->channels > 4)
34          || (!pfmt->channels)
35          || (!pfmt->freqHz)
36          || (pfmt->bitspersample & 7)
37          || (pfmt->bitspersample < 8)
38          || (pfmt->bitspersample > 32))  return FALSE;
39         WAVEDATAHEADER *pdata;
40         for (;;)
41         {
42                 pdata = (WAVEDATAHEADER *)(lpStream + dwMemPos);
43                 if (pdata->id_data == IFFID_data) break;
44                 dwMemPos += pdata->length + 8;
45                 if (dwMemPos + 8 >= dwMemLength) return FALSE;
46         }
47         m_nType = MOD_TYPE_WAV;
48         m_nSamples = 0;
49         m_nInstruments = 0;
50         m_nChannels = 4;
51         m_nDefaultSpeed = 8;
52         m_nDefaultTempo = 125;
53         m_dwSongFlags |= SONG_LINEARSLIDES; // For no resampling
54         Order[0] = 0;
55         Order[1] = 0xFF;
56         PatternSize[0] = PatternSize[1] = 64;
57         if ((Patterns[0] = AllocatePattern(64, 4)) == NULL) return TRUE;
58         if ((Patterns[1] = AllocatePattern(64, 4)) == NULL) return TRUE;
59         UINT samplesize = (pfmt->channels * pfmt->bitspersample) >> 3;
60         UINT len = pdata->length, bytelen;
61         if (dwMemPos + len > dwMemLength - 8) len = dwMemLength - dwMemPos - 8;
62         len /= samplesize;
63         bytelen = len;
64         if (pfmt->bitspersample >= 16) bytelen *= 2;
65         if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH;
66         if (!len) return TRUE;
67         // Setting up module length
68         DWORD dwTime = ((len * 50) / pfmt->freqHz) + 1;
69         DWORD framesperrow = (dwTime + 63) / 63;
70         if (framesperrow < 4) framesperrow = 4;
71         UINT norders = 1;
72         while (framesperrow >= 0x20)
73         {
74                 Order[norders++] = 1;
75                 Order[norders] = 0xFF;
76                 framesperrow = (dwTime + (64 * norders - 1)) / (64 * norders);
77                 if (norders >= MAX_ORDERS-1) break;
78         }
79         m_nDefaultSpeed = framesperrow;
80         for (UINT iChn=0; iChn<4; iChn++)
81         {
82                 ChnSettings[iChn].nPan = (iChn & 1) ? 256 : 0;
83                 ChnSettings[iChn].nVolume = 64;
84                 ChnSettings[iChn].dwFlags = 0;
85         }
86         // Setting up speed command
87         MODCOMMAND *pcmd = Patterns[0];
88         pcmd[0].command = CMD_SPEED;
89         pcmd[0].param = (BYTE)m_nDefaultSpeed;
90         pcmd[0].note = 5*12+1;
91         pcmd[0].instr = 1;
92         pcmd[1].note = pcmd[0].note;
93         pcmd[1].instr = pcmd[0].instr;
94         m_nSamples = pfmt->channels;
95         // Support for Multichannel Wave
96         for (UINT nChn=0; nChn<m_nSamples; nChn++)
97         {
98                 MODINSTRUMENT *pins = &Ins[nChn+1];
99                 pcmd[nChn].note = pcmd[0].note;
100                 pcmd[nChn].instr = (BYTE)(nChn+1);
101                 pins->nLength = len;
102                 pins->nC4Speed = pfmt->freqHz;
103                 pins->nVolume = 256;
104                 pins->nPan = 128;
105                 pins->nGlobalVol = 64;
106                 pins->uFlags = (WORD)((pfmt->bitspersample >= 16) ? CHN_16BIT : 0);
107                 pins->uFlags |= CHN_PANNING;
108                 if (m_nSamples > 1)
109                 {
110                         switch(nChn)
111                         {
112                         case 0: pins->nPan = 0; break;
113                         case 1: pins->nPan = 256; break;
114                         case 2: pins->nPan = (WORD)((m_nSamples == 3) ? 128 : 64); pcmd[nChn].command = CMD_S3MCMDEX; pcmd[nChn].param = 0x91; break;
115                         case 3: pins->nPan = 192; pcmd[nChn].command = CMD_S3MCMDEX; pcmd[nChn].param = 0x91; break;
116                         default: pins->nPan = 128; break;
117                         }
118                 }
119                 if ((pins->pSample = AllocateSample(bytelen+8)) == NULL) return TRUE;
120                 if (pfmt->bitspersample >= 16)
121                 {
122                         int slsize = pfmt->bitspersample >> 3;
123                         signed short *p = (signed short *)pins->pSample;
124                         signed char *psrc = (signed char *)(lpStream+dwMemPos+8+nChn*slsize+slsize-2);
125                         for (UINT i=0; i<len; i++)
126                         {
127                                 p[i] = *((signed short *)psrc);
128                                 psrc += samplesize;
129                         }
130                         p[len+1] = p[len] = p[len-1];
131                 } else
132                 {
133                         signed char *p = (signed char *)pins->pSample;
134                         signed char *psrc = (signed char *)(lpStream+dwMemPos+8+nChn);
135                         for (UINT i=0; i<len; i++)
136                         {
137                                 p[i] = (signed char)((*psrc) + 0x80);
138                                 psrc += samplesize;
139                         }
140                         p[len+1] = p[len] = p[len-1];
141                 }
142         }
143         return TRUE;
144 }
145
146
147 ////////////////////////////////////////////////////////////////////////
148 // IMA ADPCM Support
149
150 #pragma pack(1)
151
152 typedef struct IMAADPCMBLOCK
153 {
154         WORD sample;
155         BYTE index;
156         BYTE Reserved;
157 } DVI_ADPCMBLOCKHEADER;
158
159 #pragma pack()
160
161 static const int gIMAUnpackTable[90] = 
162 {
163   7,     8,     9,    10,    11,    12,    13,    14,
164   16,    17,    19,    21,    23,    25,    28,    31,
165   34,    37,    41,    45,    50,    55,    60,    66,
166   73,    80,    88,    97,   107,   118,   130,   143,
167   157,   173,   190,   209,   230,   253,   279,   307,
168   337,   371,   408,   449,   494,   544,   598,   658,
169   724,   796,   876,   963,  1060,  1166,  1282,  1411,
170   1552,  1707,  1878,  2066,  2272,  2499,  2749,  3024,
171   3327,  3660,  4026,  4428,  4871,  5358,  5894,  6484,
172   7132,  7845,  8630,  9493, 10442, 11487, 12635, 13899,
173   15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
174   32767, 0
175 };
176
177
178 BOOL IMAADPCMUnpack16(signed short *pdest, UINT nLen, LPBYTE psrc, DWORD dwBytes, UINT pkBlkAlign)
179 //------------------------------------------------------------------------------------------------
180 {
181         static const int gIMAIndexTab[8] =  { -1, -1, -1, -1, 2, 4, 6, 8 };
182         UINT nPos;
183         int value;
184
185         if ((nLen < 4) || (!pdest) || (!psrc)
186          || (pkBlkAlign < 5) || (pkBlkAlign > dwBytes)) return FALSE;
187         nPos = 0;
188         while ((nPos < nLen) && (dwBytes > 4))
189         {
190                 int nIndex;
191                 value = *((short int *)psrc);
192                 nIndex = psrc[2];
193                 psrc += 4;
194                 dwBytes -= 4;
195                 pdest[nPos++] = (short int)value;
196                 for (UINT i=0; ((i<(pkBlkAlign-4)*2) && (nPos < nLen) && (dwBytes)); i++)
197                 {
198                         BYTE delta;
199                         if (i & 1)
200                         {
201                                 delta = (BYTE)(((*(psrc++)) >> 4) & 0x0F);
202                                 dwBytes--;
203                         } else
204                         {
205                                 delta = (BYTE)((*psrc) & 0x0F);
206                         }
207                         int v = gIMAUnpackTable[nIndex] >> 3;
208                         if (delta & 1) v += gIMAUnpackTable[nIndex] >> 2;
209                         if (delta & 2) v += gIMAUnpackTable[nIndex] >> 1;
210                         if (delta & 4) v += gIMAUnpackTable[nIndex];
211                         if (delta & 8) value -= v; else value += v;
212                         nIndex += gIMAIndexTab[delta & 7];
213                         if (nIndex < 0) nIndex = 0; else
214                         if (nIndex > 88) nIndex = 88;
215                         if (value > 32767) value = 32767; else
216                         if (value < -32768) value = -32768;
217                         pdest[nPos++] = (short int)value;
218                 }
219         }
220         return TRUE;
221 }
222
223
224