Use the correct destination channel offset
[openal-soft.git] / Alc / converter.c
blobc6e6045415e01ac65f259b33510eac8d28acbc2d
2 #include "config.h"
4 #include "converter.h"
6 #include "mixer_defs.h"
9 SampleConverter *CreateSampleConverter(enum DevFmtType srcType, enum DevFmtType dstType, ALsizei numchans, ALsizei srcRate, ALsizei dstRate)
11 SampleConverter *converter;
13 if(numchans <= 0 || srcRate <= 0 || dstRate <= 0)
14 return NULL;
16 converter = al_calloc(16, FAM_SIZE(SampleConverter, Chan, numchans));
17 converter->mSrcType = srcType;
18 converter->mDstType = dstType;
19 converter->mNumChannels = numchans;
20 converter->mSrcTypeSize = BytesFromDevFmt(srcType);
21 converter->mDstTypeSize = BytesFromDevFmt(dstType);
23 converter->mSrcPrepCount = 0;
25 converter->mFracOffset = 0;
26 converter->mIncrement = (ALsizei)clampu64((ALuint64)srcRate*FRACTIONONE/dstRate,
27 1, MAX_PITCH*FRACTIONONE);
28 if(converter->mIncrement == FRACTIONONE)
29 converter->mResample = Resample_copy32_C;
30 else
32 /* TODO: Allow other resamplers. */
33 converter->mResample = SelectResampler(LinearResampler);
36 return converter;
39 void DestroySampleConverter(SampleConverter **converter)
41 if(converter)
43 al_free(*converter);
44 *converter = NULL;
49 static inline ALfloat Sample_ALbyte(ALbyte val)
50 { return val * (1.0f/128.0f); }
51 static inline ALfloat Sample_ALubyte(ALubyte val)
52 { return Sample_ALbyte((ALint)val - 128); }
54 static inline ALfloat Sample_ALshort(ALshort val)
55 { return val * (1.0f/32768.0f); }
56 static inline ALfloat Sample_ALushort(ALushort val)
57 { return Sample_ALshort((ALint)val - 32768); }
59 static inline ALfloat Sample_ALint(ALint val)
60 { return (val>>7) * (1.0f/16777216.0f); }
61 static inline ALfloat Sample_ALuint(ALuint val)
62 { return Sample_ALint(val - INT_MAX - 1); }
64 static inline ALfloat Sample_ALfloat(ALfloat val)
65 { return val; }
67 #define DECL_TEMPLATE(T) \
68 static inline void Load_##T(ALfloat *restrict dst, const T *restrict src, \
69 ALint srcstep, ALsizei samples) \
70 { \
71 ALsizei i; \
72 for(i = 0;i < samples;i++) \
73 dst[i] = Sample_##T(src[i*srcstep]); \
76 DECL_TEMPLATE(ALbyte)
77 DECL_TEMPLATE(ALubyte)
78 DECL_TEMPLATE(ALshort)
79 DECL_TEMPLATE(ALushort)
80 DECL_TEMPLATE(ALint)
81 DECL_TEMPLATE(ALuint)
82 DECL_TEMPLATE(ALfloat)
84 #undef DECL_TEMPLATE
86 static void LoadSamples(ALfloat *dst, const ALvoid *src, ALint srcstep, enum DevFmtType srctype, ALsizei samples)
88 switch(srctype)
90 case DevFmtByte:
91 Load_ALbyte(dst, src, srcstep, samples);
92 break;
93 case DevFmtUByte:
94 Load_ALubyte(dst, src, srcstep, samples);
95 break;
96 case DevFmtShort:
97 Load_ALshort(dst, src, srcstep, samples);
98 break;
99 case DevFmtUShort:
100 Load_ALushort(dst, src, srcstep, samples);
101 break;
102 case DevFmtInt:
103 Load_ALint(dst, src, srcstep, samples);
104 break;
105 case DevFmtUInt:
106 Load_ALuint(dst, src, srcstep, samples);
107 break;
108 case DevFmtFloat:
109 Load_ALfloat(dst, src, srcstep, samples);
110 break;
115 static inline ALbyte ALbyte_Sample(ALfloat val)
116 { return (ALbyte)clampf(val*128.0f, -128.0f, 127.0f); }
117 static inline ALubyte ALubyte_Sample(ALfloat val)
118 { return ALbyte_Sample(val)+128; }
120 static inline ALshort ALshort_Sample(ALfloat val)
121 { return (ALshort)clampf(val*32768.0f, -32768.0f, 32767.0f); }
122 static inline ALushort ALushort_Sample(ALfloat val)
123 { return ALshort_Sample(val)+32768; }
125 static inline ALint ALint_Sample(ALfloat val)
126 { return (ALint)clampf(val*16777216.0f, -16777216.0f, 16777215.0f) << 7; }
127 static inline ALuint ALuint_Sample(ALfloat val)
128 { return ALint_Sample(val)+INT_MAX+1; }
130 static inline ALfloat ALfloat_Sample(ALfloat val)
131 { return val; }
133 #define DECL_TEMPLATE(T) \
134 static inline void Store_##T(T *restrict dst, const ALfloat *restrict src, \
135 ALint dststep, ALsizei samples) \
137 ALsizei i; \
138 for(i = 0;i < samples;i++) \
139 dst[i*dststep] = T##_Sample(src[i]); \
142 DECL_TEMPLATE(ALbyte)
143 DECL_TEMPLATE(ALubyte)
144 DECL_TEMPLATE(ALshort)
145 DECL_TEMPLATE(ALushort)
146 DECL_TEMPLATE(ALint)
147 DECL_TEMPLATE(ALuint)
148 DECL_TEMPLATE(ALfloat)
150 #undef DECL_TEMPLATE
152 static void StoreSamples(ALvoid *dst, const ALfloat *src, ALint dststep, enum DevFmtType dsttype, ALsizei samples)
154 switch(dsttype)
156 case DevFmtByte:
157 Store_ALbyte(dst, src, dststep, samples);
158 break;
159 case DevFmtUByte:
160 Store_ALubyte(dst, src, dststep, samples);
161 break;
162 case DevFmtShort:
163 Store_ALshort(dst, src, dststep, samples);
164 break;
165 case DevFmtUShort:
166 Store_ALushort(dst, src, dststep, samples);
167 break;
168 case DevFmtInt:
169 Store_ALint(dst, src, dststep, samples);
170 break;
171 case DevFmtUInt:
172 Store_ALuint(dst, src, dststep, samples);
173 break;
174 case DevFmtFloat:
175 Store_ALfloat(dst, src, dststep, samples);
176 break;
181 ALsizei SampleConverterAvailableOut(SampleConverter *converter, ALsizei srcframes)
183 ALint prepcount = converter->mSrcPrepCount;
184 ALsizei increment = converter->mIncrement;
185 ALsizei DataPosFrac = converter->mFracOffset;
186 ALuint64 DataSize64;
188 if(prepcount < 0)
190 /* Negative prepcount means we need to skip that many input samples. */
191 if(-prepcount >= srcframes)
192 return 0;
193 srcframes += prepcount;
194 prepcount = 0;
197 if(srcframes < 1)
199 /* No output samples if there's no input samples. */
200 return 0;
203 if(prepcount < MAX_POST_SAMPLES+MAX_PRE_SAMPLES &&
204 MAX_POST_SAMPLES+MAX_PRE_SAMPLES-prepcount >= srcframes)
206 /* Not enough input samples to generate an output sample. */
207 return 0;
210 DataSize64 = prepcount;
211 DataSize64 += srcframes;
212 DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
213 DataSize64 <<= FRACTIONBITS;
214 DataSize64 -= DataPosFrac;
216 /* If we have a full prep, we can generate at least one sample. */
217 return (ALsizei)clampu64(DataSize64/increment, 1, INT_MAX);
221 ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALsizei *srcframes, ALvoid *dst, ALsizei dstframes)
223 const ALsizei SrcFrameSize = converter->mNumChannels * converter->mSrcTypeSize;
224 const ALsizei DstFrameSize = converter->mNumChannels * converter->mDstTypeSize;
225 const ALsizei increment = converter->mIncrement;
226 ALsizei pos = 0;
228 while(pos < dstframes && *srcframes > 0)
230 ALfloat *restrict SrcData = ASSUME_ALIGNED(converter->mSrcSamples, 16);
231 ALfloat *restrict DstData = ASSUME_ALIGNED(converter->mDstSamples, 16);
232 ALint prepcount = converter->mSrcPrepCount;
233 ALsizei DataPosFrac = converter->mFracOffset;
234 ALuint64 DataSize64;
235 ALsizei DstSize;
236 ALint toread;
237 ALsizei chan;
239 if(prepcount < 0)
241 /* Negative prepcount means we need to skip that many input samples. */
242 if(-prepcount >= *srcframes)
244 converter->mSrcPrepCount = prepcount + *srcframes;
245 *srcframes = 0;
246 break;
248 *src = (const ALbyte*)*src + SrcFrameSize*-prepcount;
249 *srcframes += prepcount;
250 converter->mSrcPrepCount = 0;
251 continue;
253 toread = mini(*srcframes, BUFFERSIZE-(MAX_POST_SAMPLES+MAX_PRE_SAMPLES));
255 if(prepcount < MAX_POST_SAMPLES+MAX_PRE_SAMPLES &&
256 MAX_POST_SAMPLES+MAX_PRE_SAMPLES-prepcount >= toread)
258 /* Not enough input samples to generate an output sample. Store
259 * what we're given for later.
261 for(chan = 0;chan < converter->mNumChannels;chan++)
262 LoadSamples(&converter->Chan[chan].mPrevSamples[prepcount],
263 (const ALbyte*)*src + converter->mSrcTypeSize*chan,
264 converter->mNumChannels, converter->mSrcType, toread
267 converter->mSrcPrepCount = prepcount + toread;
268 *srcframes = 0;
269 break;
272 DataSize64 = prepcount;
273 DataSize64 += toread;
274 DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
275 DataSize64 <<= FRACTIONBITS;
276 DataSize64 -= DataPosFrac;
278 /* If we have a full prep, we can generate at least one sample. */
279 DstSize = (ALsizei)clampu64(DataSize64/increment, 1, BUFFERSIZE);
280 DstSize = mini(DstSize, dstframes-pos);
282 for(chan = 0;chan < converter->mNumChannels;chan++)
284 const ALbyte *SrcSamples = (const ALbyte*)*src + converter->mSrcTypeSize*chan;
285 ALbyte *DstSamples = (ALbyte*)dst + converter->mDstTypeSize*chan;
286 const ALfloat *ResampledData;
287 ALsizei SrcDataEnd;
289 /* Load the previous samples into the source data first, then the
290 * new samples from the input buffer.
292 memcpy(SrcData, converter->Chan[chan].mPrevSamples,
293 prepcount*sizeof(ALfloat));
294 LoadSamples(SrcData + prepcount, SrcSamples,
295 converter->mNumChannels, converter->mSrcType, toread
298 /* Store as many prep samples for next time as possible, given the
299 * number of output samples being generated.
301 SrcDataEnd = (DataPosFrac + increment*DstSize)>>FRACTIONBITS;
302 if(SrcDataEnd >= prepcount+toread)
303 memset(converter->Chan[chan].mPrevSamples, 0,
304 sizeof(converter->Chan[chan].mPrevSamples));
305 else
307 size_t len = mini(MAX_PRE_SAMPLES+MAX_POST_SAMPLES, prepcount+toread-SrcDataEnd);
308 memcpy(converter->Chan[chan].mPrevSamples, &SrcData[SrcDataEnd],
309 len*sizeof(ALfloat));
310 memset(converter->Chan[chan].mPrevSamples+len, 0,
311 sizeof(converter->Chan[chan].mPrevSamples) - len*sizeof(ALfloat));
314 /* Now resample, and store the result in the output buffer. */
315 ResampledData = converter->mResample(NULL,
316 SrcData+MAX_PRE_SAMPLES, DataPosFrac, increment,
317 DstData, DstSize
320 StoreSamples(DstSamples, ResampledData, converter->mNumChannels,
321 converter->mDstType, DstSize);
324 /* Update the number of prep samples still available, as well as the
325 * fractional offset.
327 DataPosFrac += increment*DstSize;
328 converter->mSrcPrepCount = mini(MAX_PRE_SAMPLES+MAX_POST_SAMPLES,
329 prepcount+toread-(DataPosFrac>>FRACTIONBITS));
330 converter->mFracOffset = DataPosFrac & FRACTIONMASK;
332 /* Update the src and dst pointers in case there's still more to do. */
333 *src = (const ALbyte*)*src + SrcFrameSize*(DataPosFrac>>FRACTIONBITS);
334 *srcframes -= mini(*srcframes, (DataPosFrac>>FRACTIONBITS));
336 dst = (ALbyte*)dst + DstFrameSize*DstSize;
337 pos += DstSize;
340 return pos;
344 ChannelConverter *CreateChannelConverter(enum DevFmtType srcType, enum DevFmtChannels srcChans, enum DevFmtChannels dstChans)
346 ChannelConverter *converter;
348 if(srcChans != dstChans && !((srcChans == DevFmtMono && dstChans == DevFmtStereo) ||
349 (srcChans == DevFmtStereo && dstChans == DevFmtMono)))
350 return NULL;
352 converter = al_calloc(DEF_ALIGN, sizeof(*converter));
353 converter->mSrcType = srcType;
354 converter->mSrcChans = srcChans;
355 converter->mDstChans = dstChans;
357 return converter;
360 void DestroyChannelConverter(ChannelConverter **converter)
362 if(converter)
364 al_free(*converter);
365 *converter = NULL;
370 #define DECL_TEMPLATE(T) \
371 static void Mono2Stereo##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
373 ALsizei i; \
374 for(i = 0;i < frames;i++) \
375 dst[i*2 + 1] = dst[i*2 + 0] = Sample_##T(src[i]) * 0.707106781187f; \
378 static void Stereo2Mono##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
380 ALsizei i; \
381 for(i = 0;i < frames;i++) \
382 dst[i] = (Sample_##T(src[i*2 + 0])+Sample_##T(src[i*2 + 1])) * \
383 0.707106781187f; \
386 DECL_TEMPLATE(ALbyte)
387 DECL_TEMPLATE(ALubyte)
388 DECL_TEMPLATE(ALshort)
389 DECL_TEMPLATE(ALushort)
390 DECL_TEMPLATE(ALint)
391 DECL_TEMPLATE(ALuint)
392 DECL_TEMPLATE(ALfloat)
394 #undef DECL_TEMPLATE
396 void ChannelConverterInput(ChannelConverter *converter, const ALvoid *src, ALfloat *dst, ALsizei frames)
398 if(converter->mSrcChans == converter->mDstChans)
400 LoadSamples(dst, src, 1, converter->mSrcType,
401 frames*ChannelsFromDevFmt(converter->mSrcChans, 0));
402 return;
405 if(converter->mSrcChans == DevFmtStereo && converter->mDstChans == DevFmtMono)
407 switch(converter->mSrcType)
409 case DevFmtByte:
410 Stereo2MonoALbyte(dst, src, frames);
411 break;
412 case DevFmtUByte:
413 Stereo2MonoALubyte(dst, src, frames);
414 break;
415 case DevFmtShort:
416 Stereo2MonoALshort(dst, src, frames);
417 break;
418 case DevFmtUShort:
419 Stereo2MonoALushort(dst, src, frames);
420 break;
421 case DevFmtInt:
422 Stereo2MonoALint(dst, src, frames);
423 break;
424 case DevFmtUInt:
425 Stereo2MonoALuint(dst, src, frames);
426 break;
427 case DevFmtFloat:
428 Stereo2MonoALfloat(dst, src, frames);
429 break;
432 else /*if(converter->mSrcChans == DevFmtMono && converter->mDstChans == DevFmtStereo)*/
434 switch(converter->mSrcType)
436 case DevFmtByte:
437 Mono2StereoALbyte(dst, src, frames);
438 break;
439 case DevFmtUByte:
440 Mono2StereoALubyte(dst, src, frames);
441 break;
442 case DevFmtShort:
443 Mono2StereoALshort(dst, src, frames);
444 break;
445 case DevFmtUShort:
446 Mono2StereoALushort(dst, src, frames);
447 break;
448 case DevFmtInt:
449 Mono2StereoALint(dst, src, frames);
450 break;
451 case DevFmtUInt:
452 Mono2StereoALuint(dst, src, frames);
453 break;
454 case DevFmtFloat:
455 Mono2StereoALfloat(dst, src, frames);
456 break;