Mercurial > audlegacy-plugins
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 |