2001-04-26 16:45:43 +00:00
|
|
|
/*
|
2011-04-08 13:03:26 -07:00
|
|
|
Simple DirectMedia Layer
|
2017-01-01 18:33:28 -08:00
|
|
|
Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
|
2011-04-08 13:03:26 -07:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
2001-04-26 16:45:43 +00:00
|
|
|
*/
|
2013-11-24 23:56:17 -05:00
|
|
|
#include "../SDL_internal.h"
|
2008-08-26 07:34:49 +00:00
|
|
|
|
2001-04-26 16:45:43 +00:00
|
|
|
/* Functions for audio drivers to perform runtime conversion of audio format */
|
|
|
|
|
|
|
|
#include "SDL_audio.h"
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
#include "SDL_audio_c.h"
|
2001-04-26 16:45:43 +00:00
|
|
|
|
2012-02-07 02:11:15 -05:00
|
|
|
#include "SDL_assert.h"
|
2017-01-05 19:29:38 -05:00
|
|
|
#include "../SDL_dataqueue.h"
|
2008-08-25 15:08:59 +00:00
|
|
|
|
|
|
|
|
2001-04-26 16:45:43 +00:00
|
|
|
/* Effectively mix right and left channels into a single channel */
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
static void SDLCALL
|
|
|
|
SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
2016-11-05 02:34:38 -04:00
|
|
|
float *dst = (float *) cvt->buf;
|
|
|
|
const float *src = dst;
|
2006-07-10 21:04:37 +00:00
|
|
|
int i;
|
2001-04-26 16:45:43 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
LOG_DEBUG_CONVERT("stereo", "mono");
|
|
|
|
SDL_assert(format == AUDIO_F32SYS);
|
|
|
|
|
|
|
|
for (i = cvt->len_cvt / 8; i; --i, src += 2) {
|
|
|
|
*(dst++) = (float) ((((double) src[0]) + ((double) src[1])) * 0.5);
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
|
|
|
|
cvt->len_cvt /= 2;
|
2006-07-10 21:04:37 +00:00
|
|
|
if (cvt->filters[++cvt->filter_index]) {
|
|
|
|
cvt->filters[cvt->filter_index] (cvt, format);
|
|
|
|
}
|
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:
export SDL_AUDIODRIVER=alsa
There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.
There are two semantic changes:
(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.
(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.
With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.
The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.
If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.
Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:
(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.
(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.
(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.
(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.
(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.
(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.
I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.
I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.
The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)
Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40943
2004-08-21 12:27:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
/* Discard top 4 channels */
|
|
|
|
static void SDLCALL
|
|
|
|
SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:
export SDL_AUDIODRIVER=alsa
There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.
There are two semantic changes:
(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.
(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.
With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.
The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.
If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.
Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:
(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.
(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.
(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.
(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.
(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.
(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.
I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.
I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.
The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)
Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40943
2004-08-21 12:27:02 +00:00
|
|
|
{
|
2016-11-05 02:34:38 -04:00
|
|
|
float *dst = (float *) cvt->buf;
|
|
|
|
const float *src = dst;
|
2006-07-10 21:04:37 +00:00
|
|
|
int i;
|
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:
export SDL_AUDIODRIVER=alsa
There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.
There are two semantic changes:
(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.
(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.
With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.
The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.
If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.
Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:
(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.
(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.
(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.
(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.
(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.
(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.
I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.
I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.
The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)
Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40943
2004-08-21 12:27:02 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
LOG_DEBUG_CONVERT("6 channels", "stereo");
|
|
|
|
SDL_assert(format == AUDIO_F32SYS);
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 2) {
|
|
|
|
dst[0] = src[0];
|
|
|
|
dst[1] = src[1];
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
cvt->len_cvt /= 3;
|
|
|
|
if (cvt->filters[++cvt->filter_index]) {
|
|
|
|
cvt->filters[cvt->filter_index] (cvt, format);
|
|
|
|
}
|
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
/* Discard top 2 channels of 6 */
|
|
|
|
static void SDLCALL
|
|
|
|
SDL_ConvertStrip_2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
|
|
|
{
|
2016-11-05 02:34:38 -04:00
|
|
|
float *dst = (float *) cvt->buf;
|
|
|
|
const float *src = dst;
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
int i;
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
LOG_DEBUG_CONVERT("6 channels", "quad");
|
|
|
|
SDL_assert(format == AUDIO_F32SYS);
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 4) {
|
|
|
|
dst[0] = src[0];
|
|
|
|
dst[1] = src[1];
|
|
|
|
dst[2] = src[2];
|
|
|
|
dst[3] = src[3];
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cvt->len_cvt /= 6;
|
|
|
|
cvt->len_cvt *= 4;
|
2006-07-10 21:04:37 +00:00
|
|
|
if (cvt->filters[++cvt->filter_index]) {
|
|
|
|
cvt->filters[cvt->filter_index] (cvt, format);
|
|
|
|
}
|
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:
export SDL_AUDIODRIVER=alsa
There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.
There are two semantic changes:
(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.
(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.
With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.
The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.
If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.
Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:
(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.
(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.
(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.
(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.
(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.
(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.
I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.
I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.
The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)
Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40943
2004-08-21 12:27:02 +00:00
|
|
|
}
|
2001-04-26 16:45:43 +00:00
|
|
|
|
|
|
|
/* Duplicate a mono channel to both stereo channels */
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
static void SDLCALL
|
|
|
|
SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
2016-11-05 02:34:38 -04:00
|
|
|
const float *src = (const float *) (cvt->buf + cvt->len_cvt);
|
|
|
|
float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
|
2006-07-10 21:04:37 +00:00
|
|
|
int i;
|
2001-04-26 16:45:43 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
LOG_DEBUG_CONVERT("mono", "stereo");
|
|
|
|
SDL_assert(format == AUDIO_F32SYS);
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
for (i = cvt->len_cvt / sizeof (float); i; --i) {
|
|
|
|
src--;
|
|
|
|
dst -= 2;
|
|
|
|
dst[0] = dst[1] = *src;
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
}
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
cvt->len_cvt *= 2;
|
|
|
|
if (cvt->filters[++cvt->filter_index]) {
|
|
|
|
cvt->filters[cvt->filter_index] (cvt, format);
|
|
|
|
}
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
|
|
|
|
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:
export SDL_AUDIODRIVER=alsa
There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.
There are two semantic changes:
(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.
(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.
With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.
The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.
If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.
Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:
(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.
(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.
(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.
(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.
(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.
(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.
I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.
I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.
The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)
Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40943
2004-08-21 12:27:02 +00:00
|
|
|
|
|
|
|
/* Duplicate a stereo channel to a pseudo-5.1 stream */
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
static void SDLCALL
|
|
|
|
SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:
export SDL_AUDIODRIVER=alsa
There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.
There are two semantic changes:
(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.
(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.
With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.
The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.
If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.
Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:
(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.
(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.
(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.
(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.
(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.
(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.
I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.
I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.
The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)
Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40943
2004-08-21 12:27:02 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
int i;
|
2016-11-05 02:34:38 -04:00
|
|
|
float lf, rf, ce;
|
|
|
|
const float *src = (const float *) (cvt->buf + cvt->len_cvt);
|
|
|
|
float *dst = (float *) (cvt->buf + cvt->len_cvt * 3);
|
|
|
|
|
|
|
|
LOG_DEBUG_CONVERT("stereo", "5.1");
|
|
|
|
SDL_assert(format == AUDIO_F32SYS);
|
|
|
|
|
|
|
|
for (i = cvt->len_cvt / 8; i; --i) {
|
|
|
|
dst -= 6;
|
|
|
|
src -= 2;
|
|
|
|
lf = src[0];
|
|
|
|
rf = src[1];
|
|
|
|
ce = (lf * 0.5f) + (rf * 0.5f);
|
|
|
|
dst[0] = src[0];
|
|
|
|
dst[1] = src[1];
|
|
|
|
dst[2] = lf - ce;
|
|
|
|
dst[3] = rf - ce;
|
|
|
|
dst[4] = dst[5] = ce;
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2016-11-05 02:34:38 -04:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
cvt->len_cvt *= 3;
|
|
|
|
if (cvt->filters[++cvt->filter_index]) {
|
|
|
|
cvt->filters[cvt->filter_index] (cvt, format);
|
|
|
|
}
|
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:
export SDL_AUDIODRIVER=alsa
There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.
There are two semantic changes:
(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.
(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.
With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.
The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.
If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.
Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:
(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.
(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.
(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.
(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.
(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.
(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.
I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.
I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.
The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)
Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40943
2004-08-21 12:27:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Duplicate a stereo channel to a pseudo-4.0 stream */
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
static void SDLCALL
|
|
|
|
SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:
export SDL_AUDIODRIVER=alsa
There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.
There are two semantic changes:
(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.
(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.
With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.
The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.
If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.
Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:
(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.
(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.
(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.
(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.
(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.
(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.
I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.
I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.
The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)
Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40943
2004-08-21 12:27:02 +00:00
|
|
|
{
|
2016-11-05 02:34:38 -04:00
|
|
|
const float *src = (const float *) (cvt->buf + cvt->len_cvt);
|
|
|
|
float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
|
|
|
|
float lf, rf, ce;
|
2006-07-10 21:04:37 +00:00
|
|
|
int i;
|
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:
export SDL_AUDIODRIVER=alsa
There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.
There are two semantic changes:
(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.
(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.
With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.
The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.
If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.
Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:
(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.
(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.
(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.
(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.
(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.
(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.
I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.
I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.
The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)
Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40943
2004-08-21 12:27:02 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
LOG_DEBUG_CONVERT("stereo", "quad");
|
|
|
|
SDL_assert(format == AUDIO_F32SYS);
|
|
|
|
|
|
|
|
for (i = cvt->len_cvt / 8; i; --i) {
|
|
|
|
dst -= 4;
|
|
|
|
src -= 2;
|
|
|
|
lf = src[0];
|
|
|
|
rf = src[1];
|
|
|
|
ce = (lf / 2) + (rf / 2);
|
|
|
|
dst[0] = src[0];
|
|
|
|
dst[1] = src[1];
|
|
|
|
dst[2] = lf - ce;
|
|
|
|
dst[3] = rf - ce;
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2016-11-05 02:34:38 -04:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
cvt->len_cvt *= 2;
|
|
|
|
if (cvt->filters[++cvt->filter_index]) {
|
|
|
|
cvt->filters[cvt->filter_index] (cvt, format);
|
|
|
|
}
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
int
|
|
|
|
SDL_ConvertAudio(SDL_AudioCVT * cvt)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
2009-01-11 04:46:42 +00:00
|
|
|
/* !!! FIXME: (cvt) should be const; stack-copy it here. */
|
|
|
|
/* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
/* Make sure there's data to convert */
|
|
|
|
if (cvt->buf == NULL) {
|
2016-11-05 02:34:38 -04:00
|
|
|
return SDL_SetError("No buffer allocated for conversion");
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2016-11-05 02:34:38 -04:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
/* Return okay if no conversion is necessary */
|
|
|
|
cvt->len_cvt = cvt->len;
|
|
|
|
if (cvt->filters[0] == NULL) {
|
2016-11-05 02:34:38 -04:00
|
|
|
return 0;
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set up the conversion and go! */
|
|
|
|
cvt->filter_index = 0;
|
|
|
|
cvt->filters[0] (cvt, cvt->src_format);
|
2016-11-05 02:34:38 -04:00
|
|
|
return 0;
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
static void SDLCALL
|
|
|
|
SDL_Convert_Byteswap(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
{
|
2016-11-05 01:52:28 -07:00
|
|
|
#if DEBUG_CONVERT
|
|
|
|
printf("Converting byte order\n");
|
|
|
|
#endif
|
2016-11-05 02:34:38 -04:00
|
|
|
|
|
|
|
switch (SDL_AUDIO_BITSIZE(format)) {
|
|
|
|
#define CASESWAP(b) \
|
|
|
|
case b: { \
|
|
|
|
Uint##b *ptr = (Uint##b *) cvt->buf; \
|
|
|
|
int i; \
|
|
|
|
for (i = cvt->len_cvt / sizeof (*ptr); i; --i, ++ptr) { \
|
|
|
|
*ptr = SDL_Swap##b(*ptr); \
|
|
|
|
} \
|
|
|
|
break; \
|
|
|
|
}
|
|
|
|
|
|
|
|
CASESWAP(16);
|
|
|
|
CASESWAP(32);
|
|
|
|
CASESWAP(64);
|
|
|
|
|
|
|
|
#undef CASESWAP
|
|
|
|
|
|
|
|
default: SDL_assert(!"unhandled byteswap datatype!"); break;
|
|
|
|
}
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
if (cvt->filters[++cvt->filter_index]) {
|
|
|
|
/* flip endian flag for data. */
|
|
|
|
if (format & SDL_AUDIO_MASK_ENDIAN) {
|
|
|
|
format &= ~SDL_AUDIO_MASK_ENDIAN;
|
|
|
|
} else {
|
|
|
|
format |= SDL_AUDIO_MASK_ENDIAN;
|
|
|
|
}
|
|
|
|
cvt->filters[cvt->filter_index](cvt, format);
|
|
|
|
}
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2016-11-05 02:34:38 -04:00
|
|
|
SDL_BuildAudioTypeCVTToFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat src_fmt)
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
{
|
2016-11-05 02:34:38 -04:00
|
|
|
int retval = 0; /* 0 == no conversion necessary. */
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
|
|
|
|
cvt->filters[cvt->filter_index++] = SDL_Convert_Byteswap;
|
|
|
|
retval = 1; /* added a converter. */
|
|
|
|
}
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
if (!SDL_AUDIO_ISFLOAT(src_fmt)) {
|
2016-11-05 03:53:59 -04:00
|
|
|
const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
|
|
|
|
const Uint16 dst_bitsize = 32;
|
2016-11-05 02:34:38 -04:00
|
|
|
SDL_AudioFilter filter = NULL;
|
2016-11-05 03:53:59 -04:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
switch (src_fmt & ~SDL_AUDIO_MASK_ENDIAN) {
|
|
|
|
case AUDIO_S8: filter = SDL_Convert_S8_to_F32; break;
|
|
|
|
case AUDIO_U8: filter = SDL_Convert_U8_to_F32; break;
|
|
|
|
case AUDIO_S16: filter = SDL_Convert_S16_to_F32; break;
|
2016-11-07 21:10:01 +01:00
|
|
|
case AUDIO_U16: filter = SDL_Convert_U16_to_F32; break;
|
2016-11-05 02:34:38 -04:00
|
|
|
case AUDIO_S32: filter = SDL_Convert_S32_to_F32; break;
|
|
|
|
default: SDL_assert(!"Unexpected audio format!"); break;
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
}
|
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
if (!filter) {
|
|
|
|
return SDL_SetError("No conversion available for these formats");
|
|
|
|
}
|
|
|
|
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
cvt->filters[cvt->filter_index++] = filter;
|
|
|
|
if (src_bitsize < dst_bitsize) {
|
|
|
|
const int mult = (dst_bitsize / src_bitsize);
|
|
|
|
cvt->len_mult *= mult;
|
|
|
|
cvt->len_ratio *= mult;
|
|
|
|
} else if (src_bitsize > dst_bitsize) {
|
|
|
|
cvt->len_ratio /= (src_bitsize / dst_bitsize);
|
|
|
|
}
|
2016-11-05 03:53:59 -04:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
retval = 1; /* added a converter. */
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
}
|
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
return retval;
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
}
|
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
static int
|
|
|
|
SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt)
|
2008-08-25 15:08:59 +00:00
|
|
|
{
|
2016-11-05 02:34:38 -04:00
|
|
|
int retval = 0; /* 0 == no conversion necessary. */
|
|
|
|
|
|
|
|
if (!SDL_AUDIO_ISFLOAT(dst_fmt)) {
|
2016-11-05 03:56:55 -04:00
|
|
|
const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
|
|
|
|
const Uint16 src_bitsize = 32;
|
2016-11-05 02:34:38 -04:00
|
|
|
SDL_AudioFilter filter = NULL;
|
|
|
|
switch (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN) {
|
|
|
|
case AUDIO_S8: filter = SDL_Convert_F32_to_S8; break;
|
|
|
|
case AUDIO_U8: filter = SDL_Convert_F32_to_U8; break;
|
|
|
|
case AUDIO_S16: filter = SDL_Convert_F32_to_S16; break;
|
2016-11-07 21:10:01 +01:00
|
|
|
case AUDIO_U16: filter = SDL_Convert_F32_to_U16; break;
|
2016-11-05 02:34:38 -04:00
|
|
|
case AUDIO_S32: filter = SDL_Convert_F32_to_S32; break;
|
|
|
|
default: SDL_assert(!"Unexpected audio format!"); break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!filter) {
|
|
|
|
return SDL_SetError("No conversion available for these formats");
|
|
|
|
}
|
2008-08-25 15:08:59 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
cvt->filters[cvt->filter_index++] = filter;
|
|
|
|
if (src_bitsize < dst_bitsize) {
|
|
|
|
const int mult = (dst_bitsize / src_bitsize);
|
|
|
|
cvt->len_mult *= mult;
|
|
|
|
cvt->len_ratio *= mult;
|
|
|
|
} else if (src_bitsize > dst_bitsize) {
|
|
|
|
cvt->len_ratio /= (src_bitsize / dst_bitsize);
|
|
|
|
}
|
|
|
|
retval = 1; /* added a converter. */
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
|
|
|
|
cvt->filters[cvt->filter_index++] = SDL_Convert_Byteswap;
|
|
|
|
retval = 1; /* added a converter. */
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
2008-08-25 15:08:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-05 19:12:20 -05:00
|
|
|
/* !!! FIXME: We only have this macro salsa because SDL_AudioCVT doesn't store
|
|
|
|
!!! FIXME: channel info or integer sample rates, so we have to have
|
|
|
|
!!! FIXME: function entry points for each supported channel count and
|
|
|
|
!!! FIXME: multiple vs arbitrary. When we rev the ABI, remove this. */
|
2016-11-05 02:34:38 -04:00
|
|
|
#define RESAMPLER_FUNCS(chans) \
|
|
|
|
static void SDLCALL \
|
2017-01-05 19:12:20 -05:00
|
|
|
SDL_Upsample_Multiple_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
|
2016-11-05 02:34:38 -04:00
|
|
|
SDL_assert(format == AUDIO_F32SYS); \
|
2017-01-05 19:12:20 -05:00
|
|
|
SDL_Upsample_Multiple(cvt, chans); \
|
2016-11-05 02:34:38 -04:00
|
|
|
} \
|
|
|
|
static void SDLCALL \
|
2017-01-05 19:12:20 -05:00
|
|
|
SDL_Upsample_Arbitrary_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
|
2016-11-05 02:34:38 -04:00
|
|
|
SDL_assert(format == AUDIO_F32SYS); \
|
2017-01-05 19:12:20 -05:00
|
|
|
SDL_Upsample_Arbitrary(cvt, chans); \
|
|
|
|
}\
|
2016-11-05 02:34:38 -04:00
|
|
|
static void SDLCALL \
|
2017-01-05 19:12:20 -05:00
|
|
|
SDL_Downsample_Multiple_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
|
2016-11-05 02:34:38 -04:00
|
|
|
SDL_assert(format == AUDIO_F32SYS); \
|
2017-01-05 19:12:20 -05:00
|
|
|
SDL_Downsample_Multiple(cvt, chans); \
|
2016-11-05 02:34:38 -04:00
|
|
|
} \
|
|
|
|
static void SDLCALL \
|
2017-01-05 19:12:20 -05:00
|
|
|
SDL_Downsample_Arbitrary_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
|
2016-11-05 02:34:38 -04:00
|
|
|
SDL_assert(format == AUDIO_F32SYS); \
|
2017-01-05 19:12:20 -05:00
|
|
|
SDL_Downsample_Arbitrary(cvt, chans); \
|
2016-11-05 02:34:38 -04:00
|
|
|
}
|
|
|
|
RESAMPLER_FUNCS(1)
|
|
|
|
RESAMPLER_FUNCS(2)
|
|
|
|
RESAMPLER_FUNCS(4)
|
|
|
|
RESAMPLER_FUNCS(6)
|
|
|
|
RESAMPLER_FUNCS(8)
|
|
|
|
#undef RESAMPLER_FUNCS
|
|
|
|
|
2009-01-11 04:46:42 +00:00
|
|
|
static int
|
2017-01-05 19:12:20 -05:00
|
|
|
SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
|
2008-08-25 15:08:59 +00:00
|
|
|
{
|
2017-01-05 19:12:20 -05:00
|
|
|
int lo, hi;
|
2016-11-05 02:34:38 -04:00
|
|
|
|
2017-01-05 19:12:20 -05:00
|
|
|
SDL_assert(src_rate != 0);
|
|
|
|
SDL_assert(dst_rate != 0);
|
|
|
|
SDL_assert(src_rate != dst_rate);
|
2008-08-25 15:08:59 +00:00
|
|
|
|
2017-01-05 19:12:20 -05:00
|
|
|
if (src_rate < dst_rate) {
|
|
|
|
lo = src_rate;
|
|
|
|
hi = dst_rate;
|
|
|
|
} else {
|
|
|
|
lo = dst_rate;
|
|
|
|
hi = src_rate;
|
|
|
|
}
|
2008-08-25 15:08:59 +00:00
|
|
|
|
2017-01-05 19:12:20 -05:00
|
|
|
if ((hi % lo) != 0)
|
|
|
|
return 0; /* not a multiple. */
|
2016-11-05 02:34:38 -04:00
|
|
|
|
2017-01-05 19:12:20 -05:00
|
|
|
return hi / lo;
|
|
|
|
}
|
2016-11-05 02:34:38 -04:00
|
|
|
|
2017-01-05 19:12:20 -05:00
|
|
|
static SDL_AudioFilter
|
|
|
|
ChooseResampler(const int dst_channels, const int src_rate, const int dst_rate)
|
|
|
|
{
|
|
|
|
const int upsample = (src_rate < dst_rate) ? 1 : 0;
|
|
|
|
const int multiple = SDL_FindFrequencyMultiple(src_rate, dst_rate);
|
|
|
|
SDL_AudioFilter filter = NULL;
|
|
|
|
|
|
|
|
#define PICK_CHANNEL_FILTER(upordown, resampler) switch (dst_channels) { \
|
|
|
|
case 1: filter = SDL_##upordown##_##resampler##_c1; break; \
|
|
|
|
case 2: filter = SDL_##upordown##_##resampler##_c2; break; \
|
|
|
|
case 4: filter = SDL_##upordown##_##resampler##_c4; break; \
|
|
|
|
case 6: filter = SDL_##upordown##_##resampler##_c6; break; \
|
|
|
|
case 8: filter = SDL_##upordown##_##resampler##_c8; break; \
|
|
|
|
default: break; \
|
|
|
|
}
|
|
|
|
|
|
|
|
if (upsample) {
|
|
|
|
if (multiple) {
|
|
|
|
PICK_CHANNEL_FILTER(Upsample, Multiple);
|
|
|
|
} else {
|
|
|
|
PICK_CHANNEL_FILTER(Upsample, Arbitrary);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (multiple) {
|
|
|
|
PICK_CHANNEL_FILTER(Downsample, Multiple);
|
2009-01-11 04:46:42 +00:00
|
|
|
} else {
|
2017-01-05 19:12:20 -05:00
|
|
|
PICK_CHANNEL_FILTER(Downsample, Arbitrary);
|
2009-01-11 04:46:42 +00:00
|
|
|
}
|
2017-01-05 19:12:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#undef PICK_CHANNEL_FILTER
|
|
|
|
|
|
|
|
return filter;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, const int dst_channels,
|
|
|
|
const int src_rate, const int dst_rate)
|
|
|
|
{
|
|
|
|
SDL_AudioFilter filter;
|
|
|
|
|
|
|
|
if (src_rate == dst_rate) {
|
|
|
|
return 0; /* no conversion necessary. */
|
|
|
|
}
|
|
|
|
|
|
|
|
filter = ChooseResampler(dst_channels, src_rate, dst_rate);
|
|
|
|
if (filter == NULL) {
|
|
|
|
return SDL_SetError("No conversion available for these rates");
|
|
|
|
}
|
2008-08-25 15:08:59 +00:00
|
|
|
|
2017-01-05 19:12:20 -05:00
|
|
|
/* Update (cvt) with filter details... */
|
|
|
|
cvt->filters[cvt->filter_index++] = filter;
|
|
|
|
if (src_rate < dst_rate) {
|
|
|
|
const double mult = ((double) dst_rate) / ((double) src_rate);
|
|
|
|
cvt->len_mult *= (int) SDL_ceil(mult);
|
|
|
|
cvt->len_ratio *= mult;
|
|
|
|
} else {
|
|
|
|
cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
|
2008-08-25 15:08:59 +00:00
|
|
|
}
|
|
|
|
|
2017-01-05 19:12:20 -05:00
|
|
|
return 1; /* added a converter. */
|
2008-08-25 15:08:59 +00:00
|
|
|
}
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Creates a set of audio filters to convert from one format to another.
|
|
|
|
Returns -1 if the format conversion is not supported, 0 if there's
|
|
|
|
no conversion needed, or 1 if the audio filter is set up.
|
2001-04-26 16:45:43 +00:00
|
|
|
*/
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
|
|
|
|
SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
2013-01-21 09:16:27 -08:00
|
|
|
/* Sanity check target pointer */
|
|
|
|
if (cvt == NULL) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_InvalidParamError("cvt");
|
2013-01-21 09:16:27 -08:00
|
|
|
}
|
2013-05-18 14:17:52 -07:00
|
|
|
|
2009-11-25 06:00:00 +00:00
|
|
|
/* there are no unsigned types over 16 bits, so catch this up front. */
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_SetError("Invalid source format");
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
}
|
|
|
|
if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_SetError("Invalid destination format");
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
}
|
2009-01-11 04:46:42 +00:00
|
|
|
|
|
|
|
/* prevent possible divisions by zero, etc. */
|
2013-01-21 09:16:27 -08:00
|
|
|
if ((src_channels == 0) || (dst_channels == 0)) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_SetError("Source or destination channels is zero");
|
2013-01-21 09:16:27 -08:00
|
|
|
}
|
2009-01-11 04:46:42 +00:00
|
|
|
if ((src_rate == 0) || (dst_rate == 0)) {
|
2013-03-31 12:48:50 -04:00
|
|
|
return SDL_SetError("Source or destination rate is zero");
|
2009-01-11 04:46:42 +00:00
|
|
|
}
|
2016-11-05 01:52:28 -07:00
|
|
|
#if DEBUG_CONVERT
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
|
2006-08-28 03:17:39 +00:00
|
|
|
src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
|
|
|
|
#endif
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
/* Start off with no conversion necessary */
|
2008-12-19 06:43:41 +00:00
|
|
|
SDL_zerop(cvt);
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
cvt->src_format = src_fmt;
|
|
|
|
cvt->dst_format = dst_fmt;
|
2006-07-10 21:04:37 +00:00
|
|
|
cvt->needed = 0;
|
|
|
|
cvt->filter_index = 0;
|
|
|
|
cvt->filters[0] = NULL;
|
|
|
|
cvt->len_mult = 1;
|
|
|
|
cvt->len_ratio = 1.0;
|
2009-01-11 04:46:42 +00:00
|
|
|
cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2016-11-05 02:34:38 -04:00
|
|
|
/* Type conversion goes like this now:
|
|
|
|
- byteswap to CPU native format first if necessary.
|
|
|
|
- convert to native Float32 if necessary.
|
|
|
|
- resample and change channel count if necessary.
|
|
|
|
- convert back to native format.
|
|
|
|
- byteswap back to foreign format if necessary.
|
|
|
|
|
|
|
|
The expectation is we can process data faster in float32
|
|
|
|
(possibly with SIMD), and making several passes over the same
|
2017-01-05 19:12:20 -05:00
|
|
|
buffer is likely to be CPU cache-friendly, avoiding the
|
2016-11-05 02:34:38 -04:00
|
|
|
biggest performance hit in modern times. Previously we had
|
|
|
|
(script-generated) custom converters for every data type and
|
|
|
|
it was a bloat on SDL compile times and final library size. */
|
|
|
|
|
|
|
|
/* see if we can skip float conversion entirely (just a byteswap needed). */
|
|
|
|
if ((src_rate == dst_rate) && (src_channels == dst_channels) &&
|
|
|
|
((src_fmt != dst_fmt) &&
|
|
|
|
((src_fmt & ~SDL_AUDIO_MASK_ENDIAN) == (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN)))) {
|
|
|
|
cvt->filters[cvt->filter_index++] = SDL_Convert_Byteswap;
|
|
|
|
cvt->needed = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
/* Convert data types, if necessary. Updates (cvt). */
|
2016-11-05 02:34:38 -04:00
|
|
|
if (SDL_BuildAudioTypeCVTToFloat(cvt, src_fmt) == -1) {
|
2006-08-28 03:17:39 +00:00
|
|
|
return -1; /* shouldn't happen, but just in case... */
|
2009-01-11 04:46:42 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
First shot at new audio data types (int32 and float32).
Notable changes:
- Converters between types are autogenerated. Instead of making multiple
passes over the data with seperate filters for endianess, size, signedness,
etc, converting between data types is always one specialized filter. This
simplifies SDL_BuildAudioCVT(), which otherwise had a million edge cases
with the new types, and makes the actually conversions more CPU cache
friendly. Left a stub for adding specific optimized versions of these
routines (SSE/MMX/Altivec, assembler, etc)
- Autogenerated converters are built by SDL/src/audio/sdlgenaudiocvt.pl. This
does not need to be run unless tweaking the code, and thus doesn't need
integration into the build system.
- Went through all the drivers and tried to weed out all the "Uint16"
references that are better specified with the new SDL_AudioFormat typedef.
- Cleaned out a bunch of hardcoded bitwise magic numbers and replaced them
with new SDL_AUDIO_* macros.
- Added initial float32 and int32 support code. Theoretically, existing
drivers will push these through converters to get the data they want to
feed to the hardware.
Still TODO:
- Optimize and debug new converters.
- Update the CoreAudio backend to accept float32 data directly.
- Other backends, too?
- SDL_LoadWAV() needs to be updated to support int32 and float32 .wav files
(both of which exist and can be generated by 'sox' for testing purposes).
- Update the mixer to handle new datatypes.
- Optionally update SDL_sound and SDL_mixer, etc.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402029
2006-08-24 12:10:46 +00:00
|
|
|
/* Channel conversion */
|
2006-07-10 21:04:37 +00:00
|
|
|
if (src_channels != dst_channels) {
|
|
|
|
if ((src_channels == 1) && (dst_channels > 1)) {
|
|
|
|
cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
|
|
|
|
cvt->len_mult *= 2;
|
|
|
|
src_channels = 2;
|
|
|
|
cvt->len_ratio *= 2;
|
|
|
|
}
|
|
|
|
if ((src_channels == 2) && (dst_channels == 6)) {
|
|
|
|
cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
|
|
|
|
src_channels = 6;
|
|
|
|
cvt->len_mult *= 3;
|
|
|
|
cvt->len_ratio *= 3;
|
|
|
|
}
|
|
|
|
if ((src_channels == 2) && (dst_channels == 4)) {
|
|
|
|
cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
|
|
|
|
src_channels = 4;
|
|
|
|
cvt->len_mult *= 2;
|
|
|
|
cvt->len_ratio *= 2;
|
|
|
|
}
|
|
|
|
while ((src_channels * 2) <= dst_channels) {
|
|
|
|
cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
|
|
|
|
cvt->len_mult *= 2;
|
|
|
|
src_channels *= 2;
|
|
|
|
cvt->len_ratio *= 2;
|
|
|
|
}
|
|
|
|
if ((src_channels == 6) && (dst_channels <= 2)) {
|
|
|
|
cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
|
|
|
|
src_channels = 2;
|
|
|
|
cvt->len_ratio /= 3;
|
|
|
|
}
|
|
|
|
if ((src_channels == 6) && (dst_channels == 4)) {
|
|
|
|
cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
|
|
|
|
src_channels = 4;
|
|
|
|
cvt->len_ratio /= 2;
|
|
|
|
}
|
|
|
|
/* This assumes that 4 channel audio is in the format:
|
|
|
|
Left {front/back} + Right {front/back}
|
|
|
|
so converting to L/R stereo works properly.
|
|
|
|
*/
|
|
|
|
while (((src_channels % 2) == 0) &&
|
|
|
|
((src_channels / 2) >= dst_channels)) {
|
|
|
|
cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
|
|
|
|
src_channels /= 2;
|
|
|
|
cvt->len_ratio /= 2;
|
|
|
|
}
|
|
|
|
if (src_channels != dst_channels) {
|
|
|
|
/* Uh oh.. */ ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-11 04:46:42 +00:00
|
|
|
/* Do rate conversion, if necessary. Updates (cvt). */
|
2017-01-05 19:12:20 -05:00
|
|
|
if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) == -1) {
|
2009-01-11 04:46:42 +00:00
|
|
|
return -1; /* shouldn't happen, but just in case... */
|
2008-08-25 15:08:59 +00:00
|
|
|
}
|
|
|
|
|
2017-01-05 19:12:20 -05:00
|
|
|
/* Move to final data type. */
|
2016-11-05 02:34:38 -04:00
|
|
|
if (SDL_BuildAudioTypeCVTFromFloat(cvt, dst_fmt) == -1) {
|
|
|
|
return -1; /* shouldn't happen, but just in case... */
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2016-11-05 02:34:38 -04:00
|
|
|
|
|
|
|
cvt->needed = (cvt->filter_index != 0);
|
2006-07-10 21:04:37 +00:00
|
|
|
return (cvt->needed);
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2017-01-05 19:29:38 -05:00
|
|
|
|
|
|
|
struct SDL_AudioStream
|
|
|
|
{
|
|
|
|
SDL_AudioCVT cvt_before_resampling;
|
|
|
|
SDL_AudioCVT cvt_after_resampling;
|
|
|
|
SDL_DataQueue *queue;
|
|
|
|
Uint8 *work_buffer;
|
|
|
|
int work_buffer_len;
|
|
|
|
Uint8 *resample_buffer;
|
|
|
|
int resample_buffer_len;
|
|
|
|
int src_sample_frame_size;
|
|
|
|
SDL_AudioFormat src_format;
|
|
|
|
Uint8 src_channels;
|
|
|
|
int src_rate;
|
|
|
|
int dst_sample_frame_size;
|
|
|
|
SDL_AudioFormat dst_format;
|
|
|
|
Uint8 dst_channels;
|
|
|
|
int dst_rate;
|
|
|
|
double rate_incr;
|
|
|
|
Uint8 pre_resample_channels;
|
|
|
|
SDL_bool resampler_seeded;
|
|
|
|
float resampler_state[8];
|
|
|
|
int packetlen;
|
|
|
|
};
|
|
|
|
|
|
|
|
SDL_AudioStream *SDL_NewAudioStream(const SDL_AudioFormat src_format,
|
|
|
|
const Uint8 src_channels,
|
|
|
|
const int src_rate,
|
|
|
|
const SDL_AudioFormat dst_format,
|
|
|
|
const Uint8 dst_channels,
|
|
|
|
const int dst_rate)
|
|
|
|
{
|
|
|
|
const int packetlen = 4096; /* !!! FIXME: good enough for now. */
|
|
|
|
Uint8 pre_resample_channels;
|
|
|
|
SDL_AudioStream *retval;
|
|
|
|
|
|
|
|
retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream));
|
|
|
|
if (!retval) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If increasing channels, do it after resampling, since we'd just
|
|
|
|
do more work to resample duplicate channels. If we're decreasing, do
|
|
|
|
it first so we resample the interpolated data instead of interpolating
|
|
|
|
the resampled data (!!! FIXME: decide if that works in practice, though!). */
|
|
|
|
pre_resample_channels = SDL_min(src_channels, dst_channels);
|
|
|
|
|
|
|
|
retval->src_sample_frame_size = SDL_AUDIO_BITSIZE(src_format) * src_channels;
|
|
|
|
retval->src_format = src_format;
|
|
|
|
retval->src_channels = src_channels;
|
|
|
|
retval->src_rate = src_rate;
|
|
|
|
retval->dst_sample_frame_size = SDL_AUDIO_BITSIZE(dst_format) * dst_channels;
|
|
|
|
retval->dst_format = dst_format;
|
|
|
|
retval->dst_channels = dst_channels;
|
|
|
|
retval->dst_rate = dst_rate;
|
|
|
|
retval->pre_resample_channels = pre_resample_channels;
|
|
|
|
retval->packetlen = packetlen;
|
|
|
|
retval->rate_incr = ((double) dst_rate) / ((double) src_rate);
|
|
|
|
|
|
|
|
/* Not resampling? It's an easy conversion (and maybe not even that!). */
|
|
|
|
if (src_rate == dst_rate) {
|
|
|
|
retval->cvt_before_resampling.needed = SDL_FALSE;
|
|
|
|
retval->cvt_before_resampling.len_mult = 1;
|
|
|
|
if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, src_format, src_channels, dst_rate, dst_format, dst_channels, dst_rate) == -1) {
|
|
|
|
SDL_free(retval);
|
|
|
|
return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Don't resample at first. Just get us to Float32 format. */
|
|
|
|
/* !!! FIXME: convert to int32 on devices without hardware float. */
|
|
|
|
if (SDL_BuildAudioCVT(&retval->cvt_before_resampling, src_format, src_channels, src_rate, AUDIO_F32SYS, pre_resample_channels, src_rate) == -1) {
|
|
|
|
SDL_free(retval);
|
|
|
|
return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert us to the final format after resampling. */
|
|
|
|
if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, AUDIO_F32SYS, pre_resample_channels, dst_rate, dst_format, dst_channels, dst_rate) == -1) {
|
|
|
|
SDL_free(retval);
|
|
|
|
return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
retval->queue = SDL_NewDataQueue(packetlen, packetlen * 2);
|
|
|
|
if (!retval->queue) {
|
|
|
|
SDL_free(retval);
|
|
|
|
return NULL; /* SDL_NewDataQueue should have called SDL_SetError. */
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
ResampleAudioStream(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
|
|
|
|
{
|
|
|
|
/* !!! FIXME: this resampler sucks, but not much worse than our usual resampler. :) */ /* ... :( */
|
|
|
|
const int chans = (int) stream->pre_resample_channels;
|
|
|
|
const int framelen = chans * sizeof (float);
|
|
|
|
const int total = (inbuflen / framelen);
|
|
|
|
const int finalpos = total - chans;
|
|
|
|
const double src_incr = 1.0 / stream->rate_incr;
|
|
|
|
double idx = 0.0;
|
|
|
|
float *dst = outbuf;
|
|
|
|
float last_sample[SDL_arraysize(stream->resampler_state)];
|
|
|
|
int consumed = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
SDL_assert(chans <= SDL_arraysize(last_sample));
|
|
|
|
SDL_assert((inbuflen % framelen) == 0);
|
|
|
|
|
|
|
|
if (!stream->resampler_seeded) {
|
|
|
|
for (i = 0; i < chans; i++) {
|
|
|
|
stream->resampler_state[i] = inbuf[i];
|
|
|
|
}
|
|
|
|
stream->resampler_seeded = SDL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < chans; i++) {
|
|
|
|
last_sample[i] = stream->resampler_state[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
while (consumed < total) {
|
|
|
|
const int pos = ((int) idx) * chans;
|
|
|
|
const float *src = &inbuf[(pos >= finalpos) ? finalpos : pos];
|
|
|
|
SDL_assert(dst < (outbuf + (outbuflen / framelen)));
|
|
|
|
for (i = 0; i < chans; i++) {
|
|
|
|
const float val = *(src++);
|
|
|
|
*(dst++) = (val + last_sample[i]) * 0.5f;
|
|
|
|
last_sample[i] = val;
|
|
|
|
}
|
|
|
|
consumed = pos + chans;
|
|
|
|
idx += src_incr;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < chans; i++) {
|
|
|
|
stream->resampler_state[i] = last_sample[i];
|
|
|
|
}
|
|
|
|
|
2017-01-05 20:11:19 -05:00
|
|
|
return (int) ((dst - outbuf) * sizeof (float));
|
2017-01-05 19:29:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static Uint8 *
|
|
|
|
EnsureBufferSize(Uint8 **buf, int *len, const int newlen)
|
|
|
|
{
|
|
|
|
if (*len < newlen) {
|
|
|
|
void *ptr = SDL_realloc(*buf, newlen);
|
|
|
|
if (!ptr) {
|
|
|
|
SDL_OutOfMemory();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
*buf = (Uint8 *) ptr;
|
|
|
|
*len = newlen;
|
|
|
|
}
|
|
|
|
return *buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _buflen)
|
|
|
|
{
|
|
|
|
int buflen = (int) _buflen;
|
|
|
|
|
|
|
|
if (!stream) {
|
|
|
|
return SDL_InvalidParamError("stream");
|
|
|
|
} else if (!buf) {
|
|
|
|
return SDL_InvalidParamError("buf");
|
|
|
|
} else if (buflen == 0) {
|
|
|
|
return 0; /* nothing to do. */
|
|
|
|
} else if ((buflen % stream->src_sample_frame_size) != 0) {
|
|
|
|
return SDL_SetError("Can't add partial sample frames");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stream->cvt_before_resampling.needed) {
|
|
|
|
const int workbuflen = buflen * stream->cvt_before_resampling.len_mult; /* will be "* 1" if not needed */
|
|
|
|
Uint8 *workbuf = EnsureBufferSize(&stream->work_buffer, &stream->work_buffer_len, workbuflen);
|
|
|
|
if (workbuf == NULL) {
|
|
|
|
return -1; /* probably out of memory. */
|
|
|
|
}
|
|
|
|
SDL_memcpy(workbuf, buf, buflen);
|
|
|
|
stream->cvt_before_resampling.buf = workbuf;
|
|
|
|
stream->cvt_before_resampling.len = buflen;
|
|
|
|
if (SDL_ConvertAudio(&stream->cvt_before_resampling) == -1) {
|
|
|
|
return -1; /* uhoh! */
|
|
|
|
}
|
|
|
|
buf = workbuf;
|
|
|
|
buflen = stream->cvt_before_resampling.len_cvt;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stream->dst_rate != stream->src_rate) {
|
|
|
|
const int workbuflen = buflen * ((int) SDL_ceil(stream->rate_incr));
|
|
|
|
float *workbuf = (float *) EnsureBufferSize(&stream->resample_buffer, &stream->resample_buffer_len, workbuflen);
|
|
|
|
if (workbuf == NULL) {
|
|
|
|
return -1; /* probably out of memory. */
|
|
|
|
}
|
|
|
|
buflen = ResampleAudioStream(stream, (float *) buf, buflen, workbuf, workbuflen);
|
|
|
|
buf = workbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stream->cvt_after_resampling.needed) {
|
|
|
|
const int workbuflen = buflen * stream->cvt_before_resampling.len_mult; /* will be "* 1" if not needed */
|
|
|
|
Uint8 *workbuf;
|
|
|
|
|
|
|
|
if (buf == stream->resample_buffer) {
|
|
|
|
workbuf = EnsureBufferSize(&stream->resample_buffer, &stream->resample_buffer_len, workbuflen);
|
|
|
|
} else {
|
|
|
|
const int inplace = (buf == stream->work_buffer);
|
|
|
|
workbuf = EnsureBufferSize(&stream->work_buffer, &stream->work_buffer_len, workbuflen);
|
|
|
|
if (workbuf && !inplace) {
|
|
|
|
SDL_memcpy(workbuf, buf, buflen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (workbuf == NULL) {
|
|
|
|
return -1; /* probably out of memory. */
|
|
|
|
}
|
|
|
|
|
|
|
|
stream->cvt_after_resampling.buf = workbuf;
|
|
|
|
stream->cvt_after_resampling.len = buflen;
|
|
|
|
if (SDL_ConvertAudio(&stream->cvt_after_resampling) == -1) {
|
|
|
|
return -1; /* uhoh! */
|
|
|
|
}
|
|
|
|
buf = workbuf;
|
|
|
|
buflen = stream->cvt_after_resampling.len_cvt;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SDL_WriteToDataQueue(stream->queue, buf, buflen);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDL_AudioStreamClear(SDL_AudioStream *stream)
|
|
|
|
{
|
|
|
|
if (!stream) {
|
|
|
|
SDL_InvalidParamError("stream");
|
|
|
|
} else {
|
|
|
|
SDL_ClearDataQueue(stream->queue, stream->packetlen * 2);
|
|
|
|
stream->resampler_seeded = SDL_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* get converted/resampled data from the stream */
|
|
|
|
int
|
|
|
|
SDL_AudioStreamGet(SDL_AudioStream *stream, Uint32 len, void *buf, const Uint32 buflen)
|
|
|
|
{
|
|
|
|
if (!stream) {
|
|
|
|
return SDL_InvalidParamError("stream");
|
|
|
|
} else if (!buf) {
|
|
|
|
return SDL_InvalidParamError("buf");
|
|
|
|
} else if (len == 0) {
|
|
|
|
return 0; /* nothing to do. */
|
|
|
|
} else if ((len % stream->dst_sample_frame_size) != 0) {
|
|
|
|
return SDL_SetError("Can't request partial sample frames");
|
|
|
|
}
|
|
|
|
|
2017-01-05 20:11:19 -05:00
|
|
|
return (int) SDL_ReadFromDataQueue(stream->queue, buf, buflen);
|
2017-01-05 19:29:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* number of converted/resampled bytes available */
|
|
|
|
int
|
|
|
|
SDL_AudioStreamAvailable(SDL_AudioStream *stream)
|
|
|
|
{
|
|
|
|
return stream ? (int) SDL_CountDataQueue(stream->queue) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* dispose of a stream */
|
|
|
|
void
|
|
|
|
SDL_FreeAudioStream(SDL_AudioStream *stream)
|
|
|
|
{
|
|
|
|
if (stream) {
|
|
|
|
SDL_FreeDataQueue(stream->queue);
|
|
|
|
SDL_free(stream->work_buffer);
|
|
|
|
SDL_free(stream->resample_buffer);
|
|
|
|
SDL_free(stream);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|
2016-11-05 02:34:38 -04:00
|
|
|
|