Stop conversion when no more source samples are available
[openal-soft.git] / Alc / converter.c
blobbc9d5087d86eb5e95113b8cd70864eaeb1390bcb
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 ((ALint)(val>>7) - 16777216) * (1.0f/16777216.0f); }
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(prepcount < MAX_POST_SAMPLES+MAX_PRE_SAMPLES &&
198 MAX_POST_SAMPLES+MAX_PRE_SAMPLES-prepcount >= srcframes)
200 /* Not enough input samples to generate an output sample. */
201 return 0;
204 DataSize64 = prepcount;
205 DataSize64 += srcframes;
206 DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
207 DataSize64 <<= FRACTIONBITS;
208 DataSize64 -= DataPosFrac;
210 /* If we have a full prep, we can generate at least one sample. */
211 return (ALsizei)clampu64(DataSize64/increment, 1, INT_MAX);
215 ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALsizei *srcframes, ALvoid *dst, ALsizei dstframes)
217 const ALsizei SrcFrameSize = converter->mNumChannels * converter->mSrcTypeSize;
218 const ALsizei DstFrameSize = converter->mNumChannels * converter->mDstTypeSize;
219 const ALsizei increment = converter->mIncrement;
220 ALsizei pos = 0;
222 while(pos < dstframes && *srcframes > 0)
224 ALfloat *restrict SrcData = ASSUME_ALIGNED(converter->mSrcSamples, 16);
225 ALfloat *restrict DstData = ASSUME_ALIGNED(converter->mDstSamples, 16);
226 ALint prepcount = converter->mSrcPrepCount;
227 ALsizei DataPosFrac = converter->mFracOffset;
228 ALuint64 DataSize64;
229 ALsizei DstSize;
230 ALint toread;
231 ALsizei chan;
233 if(prepcount < 0)
235 /* Negative prepcount means we need to skip that many input samples. */
236 if(-prepcount >= *srcframes)
238 converter->mSrcPrepCount = prepcount + *srcframes;
239 *srcframes = 0;
240 break;
242 *src = (const ALbyte*)*src + SrcFrameSize*-prepcount;
243 *srcframes += prepcount;
244 converter->mSrcPrepCount = 0;
245 continue;
247 toread = mini(*srcframes, BUFFERSIZE-(MAX_POST_SAMPLES+MAX_PRE_SAMPLES));
249 if(prepcount < MAX_POST_SAMPLES+MAX_PRE_SAMPLES &&
250 MAX_POST_SAMPLES+MAX_PRE_SAMPLES-prepcount >= toread)
252 /* Not enough input samples to generate an output sample. Store
253 * what we're given for later.
255 for(chan = 0;chan < converter->mNumChannels;chan++)
256 LoadSamples(&converter->Chan[chan].mPrevSamples[prepcount],
257 (const ALbyte*)*src + converter->mSrcTypeSize*chan,
258 converter->mNumChannels, converter->mSrcType, toread
261 converter->mSrcPrepCount = prepcount + toread;
262 *srcframes = 0;
263 break;
266 DataSize64 = prepcount;
267 DataSize64 += toread;
268 DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
269 DataSize64 <<= FRACTIONBITS;
270 DataSize64 -= DataPosFrac;
272 /* If we have a full prep, we can generate at least one sample. */
273 DstSize = (ALsizei)clampu64(DataSize64/increment, 1, BUFFERSIZE);
274 DstSize = mini(DstSize, dstframes-pos);
276 for(chan = 0;chan < converter->mNumChannels;chan++)
278 const ALbyte *SrcSamples = (const ALbyte*)*src + converter->mSrcTypeSize*chan;
279 ALbyte *DstSamples = (ALbyte*)dst + converter->mSrcTypeSize*chan;
280 const ALfloat *ResampledData;
281 ALsizei SrcDataEnd;
283 /* Load the previous samples into the source data first, then the
284 * new samples from the input buffer.
286 memcpy(SrcData, converter->Chan[chan].mPrevSamples,
287 prepcount*sizeof(ALfloat));
288 LoadSamples(SrcData + prepcount, SrcSamples,
289 converter->mNumChannels, converter->mSrcType, toread
292 /* Store as many prep samples for next time as possible, given the
293 * number of output samples being generated.
295 SrcDataEnd = (DataPosFrac + increment*DstSize)>>FRACTIONBITS;
296 if(SrcDataEnd >= prepcount+toread)
297 memset(converter->Chan[chan].mPrevSamples, 0,
298 sizeof(converter->Chan[chan].mPrevSamples));
299 else
301 size_t len = mini(MAX_PRE_SAMPLES+MAX_POST_SAMPLES, prepcount+toread-SrcDataEnd);
302 memcpy(converter->Chan[chan].mPrevSamples, &SrcData[SrcDataEnd],
303 len*sizeof(ALfloat));
304 memset(converter->Chan[chan].mPrevSamples+len, 0,
305 sizeof(converter->Chan[chan].mPrevSamples) - len*sizeof(ALfloat));
308 /* Now resample, and store the result in the output buffer. */
309 ResampledData = converter->mResample(NULL,
310 SrcData+MAX_PRE_SAMPLES, DataPosFrac, increment,
311 DstData, DstSize
314 StoreSamples(DstSamples, ResampledData, converter->mNumChannels,
315 converter->mDstType, DstSize);
318 /* Update the number of prep samples still available, as well as the
319 * fractional offset.
321 DataPosFrac += increment*DstSize;
322 converter->mSrcPrepCount = mini(MAX_PRE_SAMPLES+MAX_POST_SAMPLES,
323 prepcount+toread-(DataPosFrac>>FRACTIONBITS));
324 converter->mFracOffset = DataPosFrac & FRACTIONMASK;
326 /* Update the src and dst pointers in case there's still more to do. */
327 *src = (const ALbyte*)*src + SrcFrameSize*(DataPosFrac>>FRACTIONBITS);
328 *srcframes -= mini(*srcframes, (DataPosFrac>>FRACTIONBITS));
330 dst = (ALbyte*)dst + DstFrameSize*DstSize;
331 pos += DstSize;
334 return pos;
338 ChannelConverter *CreateChannelConverter(enum DevFmtType srcType, enum DevFmtChannels srcChans, enum DevFmtChannels dstChans)
340 ChannelConverter *converter;
342 if(srcChans != dstChans && !((srcChans == DevFmtMono && dstChans == DevFmtStereo) ||
343 (srcChans == DevFmtStereo && dstChans == DevFmtMono)))
344 return NULL;
346 converter = al_calloc(DEF_ALIGN, sizeof(*converter));
347 converter->mSrcType = srcType;
348 converter->mSrcChans = srcChans;
349 converter->mDstChans = dstChans;
351 return converter;
354 void DestroyChannelConverter(ChannelConverter **converter)
356 if(converter)
358 al_free(*converter);
359 *converter = NULL;
364 #define DECL_TEMPLATE(T) \
365 static void Mono2Stereo##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
367 ALsizei i; \
368 for(i = 0;i < frames;i++) \
369 dst[i*2 + 1] = dst[i*2 + 0] = Sample_##T(src[i]) * 0.707106781187f; \
372 static void Stereo2Mono##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
374 ALsizei i; \
375 for(i = 0;i < frames;i++) \
376 dst[i] = (Sample_##T(src[i*2 + 0])+Sample_##T(src[i*2 + 1])) * \
377 0.707106781187f; \
380 DECL_TEMPLATE(ALbyte)
381 DECL_TEMPLATE(ALubyte)
382 DECL_TEMPLATE(ALshort)
383 DECL_TEMPLATE(ALushort)
384 DECL_TEMPLATE(ALint)
385 DECL_TEMPLATE(ALuint)
386 DECL_TEMPLATE(ALfloat)
388 #undef DECL_TEMPLATE
390 void ChannelConverterInput(ChannelConverter *converter, const ALvoid *src, ALfloat *dst, ALsizei frames)
392 if(converter->mSrcChans == converter->mDstChans)
394 LoadSamples(dst, src, 1, converter->mSrcType,
395 frames*ChannelsFromDevFmt(converter->mSrcChans, 0));
396 return;
399 if(converter->mSrcChans == DevFmtStereo && converter->mDstChans == DevFmtMono)
401 switch(converter->mSrcType)
403 case DevFmtByte:
404 Stereo2MonoALbyte(dst, src, frames);
405 break;
406 case DevFmtUByte:
407 Stereo2MonoALubyte(dst, src, frames);
408 break;
409 case DevFmtShort:
410 Stereo2MonoALshort(dst, src, frames);
411 break;
412 case DevFmtUShort:
413 Stereo2MonoALushort(dst, src, frames);
414 break;
415 case DevFmtInt:
416 Stereo2MonoALint(dst, src, frames);
417 break;
418 case DevFmtUInt:
419 Stereo2MonoALuint(dst, src, frames);
420 break;
421 case DevFmtFloat:
422 Stereo2MonoALfloat(dst, src, frames);
423 break;
426 else /*if(converter->mSrcChans == DevFmtMono && converter->mDstChans == DevFmtStereo)*/
428 switch(converter->mSrcType)
430 case DevFmtByte:
431 Mono2StereoALbyte(dst, src, frames);
432 break;
433 case DevFmtUByte:
434 Mono2StereoALubyte(dst, src, frames);
435 break;
436 case DevFmtShort:
437 Mono2StereoALshort(dst, src, frames);
438 break;
439 case DevFmtUShort:
440 Mono2StereoALushort(dst, src, frames);
441 break;
442 case DevFmtInt:
443 Mono2StereoALint(dst, src, frames);
444 break;
445 case DevFmtUInt:
446 Mono2StereoALuint(dst, src, frames);
447 break;
448 case DevFmtFloat:
449 Mono2StereoALfloat(dst, src, frames);
450 break;