comparison src/modplug/load_wav.cxx @ 136:6b5a52635b3b trunk

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