2 * Copyright (c) 1999-2000, Eric Moon.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 // audio_buffer_tools.h
33 // eamoon@meadgroup.com
35 // Some straightforward audio buffer-handling routines
37 #ifndef __AUDIO_BUFFER_TOOLS_H__
38 #define __AUDIO_BUFFER_TOOLS_H__
40 #include <ByteOrder.h>
43 // ---------------------------------------------------------------- //
44 // sample conversion +++++
45 // 31mar99: providing conversion to and from float, and defining
46 // other conversions based on that.
47 // ---------------------------------------------------------------- //
50 template<class from_sample_t, class to_sample_t>
51 void convert_sample(from_sample_t in, to_sample_t& out) {
52 out = (to_sample_t)in; // +++++ arbitrary conversion stub
56 inline void convert_sample(float& in
, float& out
) {
60 inline void convert_sample(uchar
& in
, float& out
) {
61 out
= (float)(in
- 128) / 127.0;
64 inline void convert_sample(short& in
, float& out
) {
65 out
= (float)in
/ 32767.0;
68 inline void convert_sample(int32
& in
, float& out
) {
69 out
= (float)in
/ (float)0x7fffffff;
72 inline void convert_sample(float& in
, uchar
& out
) {
73 out
= (uchar
)(in
* 127.0);
76 inline void convert_sample(float& in
, short& out
) {
77 out
= (short)(in
* 32767.0);
80 inline void convert_sample(float& in
, int32
& out
) {
81 out
= (int32
)(in
* 0x7fffffff);
84 inline void swap_convert_sample(float& in
, float& out
) {
85 out
= B_SWAP_FLOAT(in
);
88 inline void swap_convert_sample(uchar
& in
, float& out
) {
89 // no swap needed for char
90 out
= (float)(in
- 128) / 127.0;
93 inline void swap_convert_sample(short& in
, float& out
) {
94 out
= (float)(int16
)(B_SWAP_INT16(in
)) / 32767.0;
97 inline void swap_convert_sample(int32
& in
, float& out
) {
98 out
= (float)(int32
)(B_SWAP_INT32(in
)) / (float)0x7fffffff;
101 inline void swap_convert_sample(float& in
, uchar
& out
) {
102 out
= (uchar
)((B_SWAP_FLOAT(in
)) * 127.0);
105 inline void swap_convert_sample(float& in
, short& out
) {
106 out
= (short)((B_SWAP_FLOAT(in
)) * 32767.0);
109 inline void swap_convert_sample(float& in
, int32
& out
) {
110 out
= (int32
)((B_SWAP_FLOAT(in
)) * 0x7fffffff);
114 template<class to_sample_t
>
115 inline void convert_sample(void* pIn
, to_sample_t
& out
, int32 in_audio_format
) {
116 switch(in_audio_format
) {
117 case media_raw_audio_format::B_AUDIO_UCHAR
:
118 convert_sample(*(uchar
*)pIn
, out
);
120 case media_raw_audio_format::B_AUDIO_SHORT
:
121 convert_sample(*(short*)pIn
, out
);
123 case media_raw_audio_format::B_AUDIO_FLOAT
:
124 convert_sample(*(float*)pIn
, out
);
126 case media_raw_audio_format::B_AUDIO_INT
:
127 convert_sample(*(int32
*)pIn
, out
);
130 ASSERT(!"convert_sample(): bad raw_audio_format value");
134 template<class from_sample_t
>
135 inline void convert_sample(from_sample_t in
, void* pOut
, int32 out_audio_format
) {
136 switch(out_audio_format
) {
137 case media_raw_audio_format::B_AUDIO_UCHAR
:
138 convert_sample(in
, *(uchar
*)pOut
);
140 case media_raw_audio_format::B_AUDIO_SHORT
:
141 convert_sample(in
, *(short*)pOut
);
143 case media_raw_audio_format::B_AUDIO_FLOAT
:
144 convert_sample(in
, *(float*)pOut
);
146 case media_raw_audio_format::B_AUDIO_INT
:
147 convert_sample(in
, *(int32
*)pOut
);
150 ASSERT(!"convert_sample(): bad raw_audio_format value");
154 inline void convert_sample(void* pIn
, void* pOut
,
155 int32 in_audio_format
, int32 out_audio_format
) {
158 if(in_audio_format
== out_audio_format
)
162 if(in_audio_format
== media_raw_audio_format::B_AUDIO_FLOAT
)
163 convert_sample(*(float*)pIn
, pOut
, out_audio_format
);
165 else if(out_audio_format
== media_raw_audio_format::B_AUDIO_FLOAT
)
166 convert_sample(pOut
, *(float*)pIn
, in_audio_format
);
171 convert_sample(pIn
, fTemp
, in_audio_format
);
172 convert_sample(fTemp
, pOut
, out_audio_format
);
176 // ---------------------------------------------------------------- //
177 // data-copying helper templates
178 // ---------------------------------------------------------------- //
180 // copy from linear buffer to circular buffer; no rescaling
181 // returns new offset into destination buffer
183 template<class from_sample_t
, class to_sample_t
>
184 inline size_t copy_linear_to_circular(
185 from_sample_t
* pFrom
,
187 size_t samples
, size_t toOffset
, size_t toLength
) {
192 ASSERT(toLength
> 0);
193 ASSERT(toOffset
< toLength
);
196 for(; samples
; samples
--) {
197 pTo
[n
] = (to_sample_t
)*pFrom
++;
205 // copy from a linear buffer in one sample format to a circular buffer
206 // in another, delegating rescaling duties to convert_sample().
207 // returns new offset into destination buffer
209 template<class from_sample_t
, class to_sample_t
>
210 inline size_t copy_linear_to_circular_convert(
211 from_sample_t
* pFrom
,
213 size_t samples
, size_t toOffset
, size_t toLength
) {
218 ASSERT(toLength
> 0);
219 ASSERT(toOffset
< toLength
);
222 for(; samples
; samples
--) {
223 convert_sample(*pFrom
++, pTo
[n
]);
231 // copy from linear buffer to circular buffer; no rescaling
232 // returns new offset into source buffer
234 template<class from_sample_t
, class to_sample_t
>
235 inline size_t copy_circular_to_linear(
236 from_sample_t
* pFrom
,
238 size_t samples
, size_t fromOffset
, size_t fromLength
) {
243 ASSERT(fromLength
> 0);
244 ASSERT(fromOffset
< fromLength
);
246 size_t n
= fromOffset
;
247 for(; samples
; samples
--) {
248 *pTo
++ = (to_sample_t
)pFrom
[n
];
249 if(++n
>= fromLength
)
256 // copy from a circular buffer in one sample format to a linear buffer
257 // in another, delegating rescaling duties to convert_sample().
258 // returns new offset into source buffer
260 template<class from_sample_t
, class to_sample_t
>
261 inline size_t copy_circular_to_linear_convert(
262 from_sample_t
* pFrom
,
264 size_t samples
, size_t fromOffset
, size_t fromLength
) {
269 ASSERT(fromLength
> 0);
270 ASSERT(fromOffset
< fromLength
);
272 size_t n
= fromOffset
;
273 for(; samples
; samples
--) {
274 convert_sample(pFrom
[n
], *pTo
++);
275 if(++n
>= fromLength
)
282 //// copy between circular buffers in the same format
283 //// +++++ re-templatize
285 ///*template<class samp_t>
286 //inline*/ void copy_circular_to_circular(
290 // size_t& ioFromOffset, size_t fromLength,
291 // size_t& ioToOffset, size_t toLength);
293 // mix from a linear buffer to a circular buffer (no rescaling)
294 // input samples are multiplied by fSourceGain; destination samples
295 // are multiplied by fFeedback
296 // returns new offset within destination buffer
298 template<class from_sample_t
, class to_sample_t
>
299 inline size_t mix_linear_to_circular(
300 from_sample_t
* pFrom
,
310 if(fFeedback
== 0.0) // +++++ memset?
311 for(n
= toOffset
, nLength
= samples
;
313 n
= (n
+1 == toLength
) ? 0 : n
+1, nLength
--) { pTo
[n
] = 0.0; }
314 else if(fFeedback
!= 1.0)
315 for(n
= toOffset
, nLength
= samples
;
317 n
= (n
+1 == toLength
) ? 0 : n
+1, nLength
--) { pTo
[n
] *= fFeedback
; }
318 // else nothing to do
320 // mix source, unless muted or not provided
321 if(pFrom
&& fSourceGain
!= 0.0) {
322 if(fSourceGain
== 1.0)
323 for(n
= toOffset
, nLength
= samples
;
325 n
= (n
+1 == toLength
) ? 0 : n
+1, nLength
--) {
326 pTo
[n
] += (to_sample_t
)*pFrom
++;
329 for(n
= toOffset
, nLength
= samples
;
331 n
= (n
+1 == toLength
) ? 0 : n
+1, nLength
--) {
332 pTo
[n
] += (to_sample_t
)*pFrom
++ * fSourceGain
; // +++++ re-cast to dest format?
336 // increment loop position w/ rollover
338 if(toOffset
>= toLength
)
339 toOffset
-= toLength
;
344 // mix from a linear buffer in one sample format to a
345 // circular buffer in another, delegating to convert_sample() for rescaling
346 // input samples are multiplied by fSourceGain; destination samples
347 // are multiplied by fFeedback
348 // returns new offset within destination buffer
350 template<class from_sample_t
, class to_sample_t
>
351 inline size_t mix_linear_to_circular_convert(
352 from_sample_t
* pFrom
,
362 if(fFeedback
== 0.0) // +++++ memset?
363 for(n
= toOffset
, nLength
= samples
;
365 n
= (n
+1 == toLength
) ? 0 : n
+1, nLength
--) { pTo
[n
] = 0.0; }
366 else if(fFeedback
!= 1.0)
367 for(n
= toOffset
, nLength
= samples
;
369 n
= (n
+1 == toLength
) ? 0 : n
+1, nLength
--) { pTo
[n
] *= fFeedback
; }
370 // else nothing to do
372 // mix source, unless muted or not provided
373 if(pFrom
&& fSourceGain
!= 0.0) {
374 if(fSourceGain
== 1.0)
375 for(n
= toOffset
, nLength
= samples
;
377 n
= (n
+1 == toLength
) ? 0 : n
+1, nLength
--) {
379 convert_sample(*pFrom
++, from
);
383 for(n
= toOffset
, nLength
= samples
;
385 n
= (n
+1 == toLength
) ? 0 : n
+1, nLength
--) {
387 convert_sample(*pFrom
++, from
);
388 pTo
[n
] += from
* fSourceGain
; // +++++ re-cast to dest format?
392 // increment loop position w/ rollover
394 if(toOffset
>= toLength
)
395 toOffset
-= toLength
;
400 #endif /* __AUDIO_BUFFER_TOOLS_H__ */