comparison src/audio/SDL_audiocvt.c @ 3021:f3dcf04412cf

First shot at new audio resampling code.
author Ryan C. Gordon <icculus@icculus.org>
date Sun, 11 Jan 2009 04:46:42 +0000
parents 7e30c2dc7783
children 77c3e67f0740
comparison
equal deleted inserted replaced
3020:70d876a0b90e 3021:f3dcf04412cf
24 /* Functions for audio drivers to perform runtime conversion of audio format */ 24 /* Functions for audio drivers to perform runtime conversion of audio format */
25 25
26 #include "SDL_audio.h" 26 #include "SDL_audio.h"
27 #include "SDL_audio_c.h" 27 #include "SDL_audio_c.h"
28 28
29 //#define DEBUG_CONVERT 29 /* #define DEBUG_CONVERT */
30 30
31 /* These are fractional multiplication routines. That is, their inputs 31 /* !!! FIXME */
32 are two numbers in the range [-1, 1) and the result falls in that 32 #ifndef assert
33 same range. The output is the same size as the inputs, i.e. 33 #define assert(x)
34 32-bit x 32-bit = 32-bit.
35 */
36
37 /* We hope here that the right shift includes sign extension */
38 #ifdef SDL_HAS_64BIT_Type
39 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
40 #else
41 /* If we don't have the 64-bit type, do something more complicated. See http://www.8052.com/mul16.phtml or http://www.cs.uaf.edu/~cs301/notes/Chapter5/node5.html */
42 #define SDL_FixMpy32(a, b) ((((Sint64)a * (Sint64)b) >> 31) & 0xffffffff)
43 #endif 34 #endif
44 #define SDL_FixMpy16(a, b) ((((Sint32)a * (Sint32)b) >> 14) & 0xffff)
45 #define SDL_FixMpy8(a, b) ((((Sint16)a * (Sint16)b) >> 7) & 0xff)
46 /* This macro just makes the floating point filtering code not have to be a special case. */
47 #define SDL_FloatMpy(a, b) (a * b)
48
49 /* These macros take floating point numbers in the range [-1.0f, 1.0f) and
50 represent them as fixed-point numbers in that same range. There's no
51 checking that the floating point argument is inside the appropriate range.
52 */
53
54 #define SDL_Make_1_7(a) (Sint8)(a * 128.0f)
55 #define SDL_Make_1_15(a) (Sint16)(a * 32768.0f)
56 #define SDL_Make_1_31(a) (Sint32)(a * 2147483648.0f)
57 #define SDL_Make_2_6(a) (Sint8)(a * 64.0f)
58 #define SDL_Make_2_14(a) (Sint16)(a * 16384.0f)
59 #define SDL_Make_2_30(a) (Sint32)(a * 1073741824.0f)
60 35
61 /* Effectively mix right and left channels into a single channel */ 36 /* Effectively mix right and left channels into a single channel */
62 static void SDLCALL 37 static void SDLCALL
63 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format) 38 SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
64 { 39 {
796 if (cvt->filters[++cvt->filter_index]) { 771 if (cvt->filters[++cvt->filter_index]) {
797 cvt->filters[cvt->filter_index] (cvt, format); 772 cvt->filters[cvt->filter_index] (cvt, format);
798 } 773 }
799 } 774 }
800 775
801 /* Convert rate up by multiple of 2 */
802 static void SDLCALL
803 SDL_RateMUL2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
804 {
805 int i;
806
807 #ifdef DEBUG_CONVERT
808 fprintf(stderr, "Converting audio rate * 2 (mono)\n");
809 #endif
810
811 #define mul2_mono(type) { \
812 const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
813 type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
814 for (i = cvt->len_cvt / sizeof (type); i; --i) { \
815 src--; \
816 dst[-1] = dst[-2] = src[0]; \
817 dst -= 2; \
818 } \
819 }
820
821 switch (SDL_AUDIO_BITSIZE(format)) {
822 case 8:
823 mul2_mono(Uint8);
824 break;
825 case 16:
826 mul2_mono(Uint16);
827 break;
828 case 32:
829 mul2_mono(Uint32);
830 break;
831 }
832
833 #undef mul2_mono
834
835 cvt->len_cvt *= 2;
836 if (cvt->filters[++cvt->filter_index]) {
837 cvt->filters[cvt->filter_index] (cvt, format);
838 }
839 }
840
841
842 /* Convert rate up by multiple of 2, for stereo */
843 static void SDLCALL
844 SDL_RateMUL2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
845 {
846 int i;
847
848 #ifdef DEBUG_CONVERT
849 fprintf(stderr, "Converting audio rate * 2 (stereo)\n");
850 #endif
851
852 #define mul2_stereo(type) { \
853 const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
854 type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
855 for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
856 const type r = src[-1]; \
857 const type l = src[-2]; \
858 src -= 2; \
859 dst[-1] = r; \
860 dst[-2] = l; \
861 dst[-3] = r; \
862 dst[-4] = l; \
863 dst -= 4; \
864 } \
865 }
866
867 switch (SDL_AUDIO_BITSIZE(format)) {
868 case 8:
869 mul2_stereo(Uint8);
870 break;
871 case 16:
872 mul2_stereo(Uint16);
873 break;
874 case 32:
875 mul2_stereo(Uint32);
876 break;
877 }
878
879 #undef mul2_stereo
880
881 cvt->len_cvt *= 2;
882 if (cvt->filters[++cvt->filter_index]) {
883 cvt->filters[cvt->filter_index] (cvt, format);
884 }
885 }
886
887 /* Convert rate up by multiple of 2, for quad */
888 static void SDLCALL
889 SDL_RateMUL2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
890 {
891 int i;
892
893 #ifdef DEBUG_CONVERT
894 fprintf(stderr, "Converting audio rate * 2 (quad)\n");
895 #endif
896
897 #define mul2_quad(type) { \
898 const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
899 type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
900 for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
901 const type c1 = src[-1]; \
902 const type c2 = src[-2]; \
903 const type c3 = src[-3]; \
904 const type c4 = src[-4]; \
905 src -= 4; \
906 dst[-1] = c1; \
907 dst[-2] = c2; \
908 dst[-3] = c3; \
909 dst[-4] = c4; \
910 dst[-5] = c1; \
911 dst[-6] = c2; \
912 dst[-7] = c3; \
913 dst[-8] = c4; \
914 dst -= 8; \
915 } \
916 }
917
918 switch (SDL_AUDIO_BITSIZE(format)) {
919 case 8:
920 mul2_quad(Uint8);
921 break;
922 case 16:
923 mul2_quad(Uint16);
924 break;
925 case 32:
926 mul2_quad(Uint32);
927 break;
928 }
929
930 #undef mul2_quad
931
932 cvt->len_cvt *= 2;
933 if (cvt->filters[++cvt->filter_index]) {
934 cvt->filters[cvt->filter_index] (cvt, format);
935 }
936 }
937
938
939 /* Convert rate up by multiple of 2, for 5.1 */
940 static void SDLCALL
941 SDL_RateMUL2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
942 {
943 int i;
944
945 #ifdef DEBUG_CONVERT
946 fprintf(stderr, "Converting audio rate * 2 (six channels)\n");
947 #endif
948
949 #define mul2_chansix(type) { \
950 const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
951 type *dst = (type *) (cvt->buf + (cvt->len_cvt * 2)); \
952 for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
953 const type c1 = src[-1]; \
954 const type c2 = src[-2]; \
955 const type c3 = src[-3]; \
956 const type c4 = src[-4]; \
957 const type c5 = src[-5]; \
958 const type c6 = src[-6]; \
959 src -= 6; \
960 dst[-1] = c1; \
961 dst[-2] = c2; \
962 dst[-3] = c3; \
963 dst[-4] = c4; \
964 dst[-5] = c5; \
965 dst[-6] = c6; \
966 dst[-7] = c1; \
967 dst[-8] = c2; \
968 dst[-9] = c3; \
969 dst[-10] = c4; \
970 dst[-11] = c5; \
971 dst[-12] = c6; \
972 dst -= 12; \
973 } \
974 }
975
976 switch (SDL_AUDIO_BITSIZE(format)) {
977 case 8:
978 mul2_chansix(Uint8);
979 break;
980 case 16:
981 mul2_chansix(Uint16);
982 break;
983 case 32:
984 mul2_chansix(Uint32);
985 break;
986 }
987
988 #undef mul2_chansix
989
990 cvt->len_cvt *= 2;
991 if (cvt->filters[++cvt->filter_index]) {
992 cvt->filters[cvt->filter_index] (cvt, format);
993 }
994 }
995
996 /* Convert rate down by multiple of 2 */
997 static void SDLCALL
998 SDL_RateDIV2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
999 {
1000 int i;
1001
1002 #ifdef DEBUG_CONVERT
1003 fprintf(stderr, "Converting audio rate / 2 (mono)\n");
1004 #endif
1005
1006 #define div2_mono(type) { \
1007 const type *src = (const type *) cvt->buf; \
1008 type *dst = (type *) cvt->buf; \
1009 for (i = cvt->len_cvt / (sizeof (type) * 2); i; --i) { \
1010 dst[0] = src[0]; \
1011 src += 2; \
1012 dst++; \
1013 } \
1014 }
1015
1016 switch (SDL_AUDIO_BITSIZE(format)) {
1017 case 8:
1018 div2_mono(Uint8);
1019 break;
1020 case 16:
1021 div2_mono(Uint16);
1022 break;
1023 case 32:
1024 div2_mono(Uint32);
1025 break;
1026 }
1027
1028 #undef div2_mono
1029
1030 cvt->len_cvt /= 2;
1031 if (cvt->filters[++cvt->filter_index]) {
1032 cvt->filters[cvt->filter_index] (cvt, format);
1033 }
1034 }
1035
1036
1037 /* Convert rate down by multiple of 2, for stereo */
1038 static void SDLCALL
1039 SDL_RateDIV2_c2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
1040 {
1041 int i;
1042
1043 #ifdef DEBUG_CONVERT
1044 fprintf(stderr, "Converting audio rate / 2 (stereo)\n");
1045 #endif
1046
1047 #define div2_stereo(type) { \
1048 const type *src = (const type *) cvt->buf; \
1049 type *dst = (type *) cvt->buf; \
1050 for (i = cvt->len_cvt / (sizeof (type) * 4); i; --i) { \
1051 dst[0] = src[0]; \
1052 dst[1] = src[1]; \
1053 src += 4; \
1054 dst += 2; \
1055 } \
1056 }
1057
1058 switch (SDL_AUDIO_BITSIZE(format)) {
1059 case 8:
1060 div2_stereo(Uint8);
1061 break;
1062 case 16:
1063 div2_stereo(Uint16);
1064 break;
1065 case 32:
1066 div2_stereo(Uint32);
1067 break;
1068 }
1069
1070 #undef div2_stereo
1071
1072 cvt->len_cvt /= 2;
1073 if (cvt->filters[++cvt->filter_index]) {
1074 cvt->filters[cvt->filter_index] (cvt, format);
1075 }
1076 }
1077
1078
1079 /* Convert rate down by multiple of 2, for quad */
1080 static void SDLCALL
1081 SDL_RateDIV2_c4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
1082 {
1083 int i;
1084
1085 #ifdef DEBUG_CONVERT
1086 fprintf(stderr, "Converting audio rate / 2 (quad)\n");
1087 #endif
1088
1089 #define div2_quad(type) { \
1090 const type *src = (const type *) cvt->buf; \
1091 type *dst = (type *) cvt->buf; \
1092 for (i = cvt->len_cvt / (sizeof (type) * 8); i; --i) { \
1093 dst[0] = src[0]; \
1094 dst[1] = src[1]; \
1095 dst[2] = src[2]; \
1096 dst[3] = src[3]; \
1097 src += 8; \
1098 dst += 4; \
1099 } \
1100 }
1101
1102 switch (SDL_AUDIO_BITSIZE(format)) {
1103 case 8:
1104 div2_quad(Uint8);
1105 break;
1106 case 16:
1107 div2_quad(Uint16);
1108 break;
1109 case 32:
1110 div2_quad(Uint32);
1111 break;
1112 }
1113
1114 #undef div2_quad
1115
1116 cvt->len_cvt /= 2;
1117 if (cvt->filters[++cvt->filter_index]) {
1118 cvt->filters[cvt->filter_index] (cvt, format);
1119 }
1120 }
1121
1122 /* Convert rate down by multiple of 2, for 5.1 */
1123 static void SDLCALL
1124 SDL_RateDIV2_c6(SDL_AudioCVT * cvt, SDL_AudioFormat format)
1125 {
1126 int i;
1127
1128 #ifdef DEBUG_CONVERT
1129 fprintf(stderr, "Converting audio rate / 2 (six channels)\n");
1130 #endif
1131
1132 #define div2_chansix(type) { \
1133 const type *src = (const type *) cvt->buf; \
1134 type *dst = (type *) cvt->buf; \
1135 for (i = cvt->len_cvt / (sizeof (type) * 12); i; --i) { \
1136 dst[0] = src[0]; \
1137 dst[1] = src[1]; \
1138 dst[2] = src[2]; \
1139 dst[3] = src[3]; \
1140 dst[4] = src[4]; \
1141 dst[5] = src[5]; \
1142 src += 12; \
1143 dst += 6; \
1144 } \
1145 }
1146
1147 switch (SDL_AUDIO_BITSIZE(format)) {
1148 case 8:
1149 div2_chansix(Uint8);
1150 break;
1151 case 16:
1152 div2_chansix(Uint16);
1153 break;
1154 case 32:
1155 div2_chansix(Uint32);
1156 break;
1157 }
1158
1159 #undef div_chansix
1160
1161 cvt->len_cvt /= 2;
1162 if (cvt->filters[++cvt->filter_index]) {
1163 cvt->filters[cvt->filter_index] (cvt, format);
1164 }
1165 }
1166
1167 /* Very slow rate conversion routine */
1168 static void SDLCALL
1169 SDL_RateSLOW(SDL_AudioCVT * cvt, SDL_AudioFormat format)
1170 {
1171 double ipos;
1172 int i, clen;
1173
1174 #ifdef DEBUG_CONVERT
1175 fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0 / cvt->rate_incr);
1176 #endif
1177 clen = (int) ((double) cvt->len_cvt / cvt->rate_incr);
1178 if (cvt->rate_incr > 1.0) {
1179 switch (SDL_AUDIO_BITSIZE(format)) {
1180 case 8:
1181 {
1182 Uint8 *output;
1183
1184 output = cvt->buf;
1185 ipos = 0.0;
1186 for (i = clen; i; --i) {
1187 *output = cvt->buf[(int) ipos];
1188 ipos += cvt->rate_incr;
1189 output += 1;
1190 }
1191 }
1192 break;
1193
1194 case 16:
1195 {
1196 Uint16 *output;
1197
1198 clen &= ~1;
1199 output = (Uint16 *) cvt->buf;
1200 ipos = 0.0;
1201 for (i = clen / 2; i; --i) {
1202 *output = ((Uint16 *) cvt->buf)[(int) ipos];
1203 ipos += cvt->rate_incr;
1204 output += 1;
1205 }
1206 }
1207 break;
1208
1209 case 32:
1210 {
1211 /* !!! FIXME: need 32-bit converter here! */
1212 #ifdef DEBUG_CONVERT
1213 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
1214 #endif
1215 }
1216 }
1217 } else {
1218 switch (SDL_AUDIO_BITSIZE(format)) {
1219 case 8:
1220 {
1221 Uint8 *output;
1222
1223 output = cvt->buf + clen;
1224 ipos = (double) cvt->len_cvt;
1225 for (i = clen; i; --i) {
1226 ipos -= cvt->rate_incr;
1227 output -= 1;
1228 *output = cvt->buf[(int) ipos];
1229 }
1230 }
1231 break;
1232
1233 case 16:
1234 {
1235 Uint16 *output;
1236
1237 clen &= ~1;
1238 output = (Uint16 *) (cvt->buf + clen);
1239 ipos = (double) cvt->len_cvt / 2;
1240 for (i = clen / 2; i; --i) {
1241 ipos -= cvt->rate_incr;
1242 output -= 1;
1243 *output = ((Uint16 *) cvt->buf)[(int) ipos];
1244 }
1245 }
1246 break;
1247
1248 case 32:
1249 {
1250 /* !!! FIXME: need 32-bit converter here! */
1251 #ifdef DEBUG_CONVERT
1252 fprintf(stderr, "FIXME: need 32-bit converter here!\n");
1253 #endif
1254 }
1255 }
1256 }
1257
1258 cvt->len_cvt = clen;
1259 if (cvt->filters[++cvt->filter_index]) {
1260 cvt->filters[cvt->filter_index] (cvt, format);
1261 }
1262 }
1263 776
1264 int 777 int
1265 SDL_ConvertAudio(SDL_AudioCVT * cvt) 778 SDL_ConvertAudio(SDL_AudioCVT * cvt)
1266 { 779 {
780 /* !!! FIXME: (cvt) should be const; stack-copy it here. */
781 /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
782
1267 /* Make sure there's data to convert */ 783 /* Make sure there's data to convert */
1268 if (cvt->buf == NULL) { 784 if (cvt->buf == NULL) {
1269 SDL_SetError("No buffer allocated for conversion"); 785 SDL_SetError("No buffer allocated for conversion");
1270 return (-1); 786 return (-1);
1271 } 787 }
1339 } 855 }
1340 856
1341 return 0; /* no conversion necessary. */ 857 return 0; /* no conversion necessary. */
1342 } 858 }
1343 859
1344 /* Generate the necessary IIR lowpass coefficients for resampling. 860
1345 Assume that the SDL_AudioCVT struct is already set up with 861 static SDL_AudioFilter
1346 the correct values for len_mult and len_div, and use the 862 SDL_HandTunedResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
1347 type of dst_format. Also assume the buffer is allocated. 863 int src_rate, int dst_rate)
1348 Note the buffer needs to be 6 units long. 864 {
1349 For now, use RBJ's cookbook coefficients. It might be more 865 /*
1350 optimal to create a Butterworth filter, but this is more difficult. 866 * Fill in any future conversions that are specialized to a
1351 */ 867 * processor, platform, compiler, or library here.
1352 #if 0 868 */
1353 int 869
1354 SDL_BuildIIRLowpass(SDL_AudioCVT * cvt, SDL_AudioFormat format) 870 return NULL; /* no specialized converter code available. */
1355 { 871 }
1356 float fc; /* cutoff frequency */ 872
1357 float coeff[6]; /* floating point iir coefficients b0, b1, b2, a0, a1, a2 */ 873 static int
1358 float scale; 874 SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
1359 float w0, alpha, cosw0; 875 {
1360 int i; 876 int retval = 0;
1361 877
1362 /* The higher Q is, the higher CUTOFF can be. Need to find a good balance to avoid aliasing */ 878 /* If we only built with the arbitrary resamplers, ignore multiples. */
1363 static const float Q = 5.0f; 879 #if !LESS_RESAMPLERS
1364 static const float CUTOFF = 0.4f; 880 int lo, hi;
1365 881 int div;
1366 fc = (cvt->len_mult > 882
1367 cvt->len_div) ? CUTOFF / (float) cvt->len_mult : CUTOFF / 883 assert(src_rate != 0);
1368 (float) cvt->len_div; 884 assert(dst_rate != 0);
1369 885 assert(src_rate != dst_rate);
1370 w0 = 2.0f * M_PI * fc; 886
1371 cosw0 = cosf(w0); 887 if (src_rate < dst_rate) {
1372 alpha = sinf(w0) / (2.0f * Q); 888 lo = src_rate;
1373 889 hi = dst_rate;
1374 /* Compute coefficients, normalizing by a0 */
1375 scale = 1.0f / (1.0f + alpha);
1376
1377 coeff[0] = (1.0f - cosw0) / 2.0f * scale;
1378 coeff[1] = (1.0f - cosw0) * scale;
1379 coeff[2] = coeff[0];
1380
1381 coeff[3] = 1.0f; /* a0 is normalized to 1 */
1382 coeff[4] = -2.0f * cosw0 * scale;
1383 coeff[5] = (1.0f - alpha) * scale;
1384
1385 /* Copy the coefficients to the struct. If necessary, convert coefficients to fixed point, using the range (-2.0, 2.0) */
1386 #define convert_fixed(type, fix) { \
1387 type *cvt_coeff = (type *)cvt->coeff; \
1388 for(i = 0; i < 6; ++i) { \
1389 cvt_coeff[i] = fix(coeff[i]); \
1390 } \
1391 }
1392
1393 if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
1394 float *cvt_coeff = (float *) cvt->coeff;
1395 for (i = 0; i < 6; ++i) {
1396 cvt_coeff[i] = coeff[i];
1397 }
1398 } else { 890 } else {
1399 switch (SDL_AUDIO_BITSIZE(format)) { 891 lo = dst_rate;
1400 case 8: 892 hi = src_rate;
1401 convert_fixed(Uint8, SDL_Make_2_6); 893 }
1402 break; 894
1403 case 16: 895 /* zero means "not a supported multiple" ... we only do 2x and 4x. */
1404 convert_fixed(Uint16, SDL_Make_2_14); 896 if ((hi % lo) != 0)
1405 break; 897 return 0; /* not a multiple. */
1406 case 32: 898
1407 convert_fixed(Uint32, SDL_Make_2_30); 899 div = hi / lo;
1408 break; 900 retval = ((div == 2) || (div == 4)) ? div : 0;
1409 }
1410 }
1411
1412 #ifdef DEBUG_CONVERT
1413 #define debug_iir(type) { \
1414 type *cvt_coeff = (type *)cvt->coeff; \
1415 for(i = 0; i < 6; ++i) { \
1416 printf("coeff[%u] = %f = 0x%x\n", i, coeff[i], cvt_coeff[i]); \
1417 } \
1418 }
1419 if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
1420 float *cvt_coeff = (float *) cvt->coeff;
1421 for (i = 0; i < 6; ++i) {
1422 printf("coeff[%u] = %f = %f\n", i, coeff[i], cvt_coeff[i]);
1423 }
1424 } else {
1425 switch (SDL_AUDIO_BITSIZE(format)) {
1426 case 8:
1427 debug_iir(Uint8);
1428 break;
1429 case 16:
1430 debug_iir(Uint16);
1431 break;
1432 case 32:
1433 debug_iir(Uint32);
1434 break;
1435 }
1436 }
1437 #undef debug_iir
1438 #endif 901 #endif
1439 902
1440 /* Initialize the state buffer to all zeroes, and set initial position */ 903 return retval;
1441 SDL_memset(cvt->state_buf, 0, 4 * SDL_AUDIO_BITSIZE(format) / 4); 904 }
1442 cvt->state_pos = 0; 905
1443 #undef convert_fixed 906 static int
1444 907 SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
1445 return 0; 908 int src_rate, int dst_rate)
1446 } 909 {
1447 #endif 910 if (src_rate != dst_rate) {
1448 911 SDL_AudioFilter filter = SDL_HandTunedResampleCVT(cvt, dst_channels,
1449 /* Apply the lowpass IIR filter to the given SDL_AudioCVT struct */ 912 src_rate, dst_rate);
1450 /* This was implemented because it would be much faster than the fir filter, 913
1451 but it doesn't seem to have a steep enough cutoff so we'd need several 914 /* No hand-tuned converter? Try the autogenerated ones. */
1452 cascaded biquads, which probably isn't a great idea. Therefore, this 915 if (filter == NULL) {
1453 function can probably be discarded. 916 int i;
1454 */ 917 const int upsample = (src_rate < dst_rate) ? 1 : 0;
1455 static void 918 const int multiple = SDL_FindFrequencyMultiple(src_rate, dst_rate);
1456 SDL_FilterIIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) 919
1457 { 920 for (i = 0; sdl_audio_rate_filters[i].filter != NULL; i++) {
1458 Uint32 i, n; 921 const SDL_AudioRateFilters *filt = &sdl_audio_rate_filters[i];
1459 922 if ((filt->fmt == cvt->dst_format) &&
1460 /* TODO: Check that n is calculated right */ 923 (filt->channels == dst_channels) &&
1461 n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format); 924 (filt->upsample == upsample) &&
1462 925 (filt->multiple == multiple)) {
1463 /* Note that the coefficients are 2_x and the input is 1_x. Do we need to shift left at the end here? The right shift temp = buf[n] >> 1 needs to depend on whether the type is signed or not for sign extension. */ 926 filter = filt->filter;
1464 /* cvt->state_pos = 1: state[0] = x_n-1, state[1] = x_n-2, state[2] = y_n-1, state[3] - y_n-2 */ 927 break;
1465 #define iir_fix(type, mult) {\ 928 }
1466 type *coeff = (type *)cvt->coeff; \ 929 }
1467 type *state = (type *)cvt->state_buf; \ 930
1468 type *buf = (type *)cvt->buf; \ 931 if (filter == NULL) {
1469 type temp; \ 932 return -1; /* Still no matching converter?! */
1470 for(i = 0; i < n; ++i) { \ 933 }
1471 temp = buf[i] >> 1; \ 934 }
1472 if(cvt->state_pos) { \ 935
1473 buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[0]) + mult(coeff[2], state[1]) - mult(coeff[4], state[2]) - mult(coeff[5], state[3]); \ 936 /* Update (cvt) with filter details... */
1474 state[1] = temp; \ 937 cvt->filters[cvt->filter_index++] = filter;
1475 state[3] = buf[i]; \ 938 if (src_rate < dst_rate) {
1476 cvt->state_pos = 0; \ 939 const double mult = ((double) dst_rate) / ((double) src_rate);
1477 } else { \ 940 cvt->len_mult *= (int) ceil(mult); /* !!! FIXME: C runtime dependency. */
1478 buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[1]) + mult(coeff[2], state[0]) - mult(coeff[4], state[3]) - mult(coeff[5], state[2]); \ 941 cvt->len_ratio *= mult;
1479 state[0] = temp; \
1480 state[2] = buf[i]; \
1481 cvt->state_pos = 1; \
1482 } \
1483 } \
1484 }
1485 /* Need to test to see if the previous method or this one is faster */
1486 /*#define iir_fix(type, mult) {\
1487 type *coeff = (type *)cvt->coeff; \
1488 type *state = (type *)cvt->state_buf; \
1489 type *buf = (type *)cvt->buf; \
1490 type temp; \
1491 for(i = 0; i < n; ++i) { \
1492 temp = buf[i] >> 1; \
1493 buf[i] = mult(coeff[0], temp) + mult(coeff[1], state[0]) + mult(coeff[2], state[1]) - mult(coeff[4], state[2]) - mult(coeff[5], state[3]); \
1494 state[1] = state[0]; \
1495 state[0] = temp; \
1496 state[3] = state[2]; \
1497 state[2] = buf[i]; \
1498 } \
1499 }*/
1500
1501 if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
1502 float *coeff = (float *) cvt->coeff;
1503 float *state = (float *) cvt->state_buf;
1504 float *buf = (float *) cvt->buf;
1505 float temp;
1506
1507 for (i = 0; i < n; ++i) {
1508 /* y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a[2] * y[n-2] */
1509 temp = buf[i];
1510 if (cvt->state_pos) {
1511 buf[i] =
1512 coeff[0] * buf[n] + coeff[1] * state[0] +
1513 coeff[2] * state[1] - coeff[4] * state[2] -
1514 coeff[5] * state[3];
1515 state[1] = temp;
1516 state[3] = buf[i];
1517 cvt->state_pos = 0;
1518 } else {
1519 buf[i] =
1520 coeff[0] * buf[n] + coeff[1] * state[1] +
1521 coeff[2] * state[0] - coeff[4] * state[3] -
1522 coeff[5] * state[2];
1523 state[0] = temp;
1524 state[2] = buf[i];
1525 cvt->state_pos = 1;
1526 }
1527 }
1528 } else {
1529 /* Treat everything as signed! */
1530 switch (SDL_AUDIO_BITSIZE(format)) {
1531 case 8:
1532 iir_fix(Sint8, SDL_FixMpy8);
1533 break;
1534 case 16:
1535 iir_fix(Sint16, SDL_FixMpy16);
1536 break;
1537 case 32:
1538 iir_fix(Sint32, SDL_FixMpy32);
1539 break;
1540 }
1541 }
1542 #undef iir_fix
1543 }
1544
1545 /* Apply the windowed sinc FIR filter to the given SDL_AudioCVT struct.
1546 */
1547 static void
1548 SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format)
1549 {
1550 /* !!! FIXME: (n) is incorrect, or my allocation of state_buf is wrong. */
1551 const int n = 8 * cvt->len_cvt / SDL_AUDIO_BITSIZE(format);
1552 int m = cvt->len_sinc;
1553 int i, j;
1554
1555 /*
1556 Note: We can make a big optimization here by taking advantage
1557 of the fact that the signal is zero stuffed, so we can do
1558 significantly fewer multiplications and additions. However, this
1559 depends on the zero stuffing ratio, so it may not pay off. This would
1560 basically be a polyphase filter.
1561 */
1562 /* One other way to do this fast is to look at the fir filter from a different angle:
1563 After we zero stuff, we have input of all zeroes, except for every len_mult
1564 sample. If we choose a sinc length equal to len_mult, then the fir filter becomes
1565 much more simple: we're just taking a windowed sinc, shifting it to start at each
1566 len_mult sample, and scaling it by the value of that sample. If we do this, then
1567 we don't even need to worry about the sample histories, and the inner loop here is
1568 unnecessary. This probably sacrifices some quality but could really speed things up as well.
1569 */
1570 /* We only calculate the values of samples which are 0 (mod len_div) because
1571 those are the only ones used. All the other ones are discarded in the
1572 third step of resampling. This is a huge speedup. As a warning, though,
1573 if for some reason this is used elsewhere where there are no samples discarded,
1574 the output will not be corrrect if len_div is not 1. To make this filter a
1575 generic FIR filter, simply remove the if statement "if(i % cvt->len_div == 0)"
1576 around the inner loop so that every sample is processed.
1577 */
1578 /* This is basically just a FIR filter. i.e. for input x_n and m coefficients,
1579 y_n = x_n*sinc_0 + x_(n-1)*sinc_1 + x_(n-2)*sinc_2 + ... + x_(n-m+1)*sinc_(m-1)
1580 */
1581 #define filter_sinc(type, mult) { \
1582 type *sinc = (type *)cvt->coeff; \
1583 type *state = (type *)cvt->state_buf; \
1584 type *buf = (type *)cvt->buf; \
1585 for(i = 0; i < n; ++i) { \
1586 state[cvt->state_pos] = buf[i]; \
1587 buf[i] = 0; \
1588 if( i % cvt->len_div == 0 ) { \
1589 for(j = 0; j < m; ++j) { \
1590 buf[i] += mult(sinc[j], state[(cvt->state_pos + j) % m]); \
1591 } \
1592 }\
1593 cvt->state_pos = (cvt->state_pos + 1) % m; \
1594 } \
1595 }
1596
1597 if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
1598 filter_sinc(float, SDL_FloatMpy);
1599 } else {
1600 switch (SDL_AUDIO_BITSIZE(format)) {
1601 case 8:
1602 filter_sinc(Sint8, SDL_FixMpy8);
1603 break;
1604 case 16:
1605 filter_sinc(Sint16, SDL_FixMpy16);
1606 break;
1607 case 32:
1608 filter_sinc(Sint32, SDL_FixMpy32);
1609 break;
1610 }
1611 }
1612
1613 #undef filter_sinc
1614
1615 }
1616
1617 /* Generate the necessary windowed sinc filter for resampling.
1618 Assume that the SDL_AudioCVT struct is already set up with
1619 the correct values for len_mult and len_div, and use the
1620 type of dst_format. Also assume the buffer is allocated.
1621 Note the buffer needs to be m+1 units long.
1622 */
1623 int
1624 SDL_BuildWindowedSinc(SDL_AudioCVT * cvt, SDL_AudioFormat format,
1625 unsigned int m)
1626 {
1627 float *fSinc; /* floating point sinc buffer, to be converted to fixed point */
1628 float fc; /* cutoff frequency */
1629 float two_pi_fc, two_pi_over_m, four_pi_over_m, m_over_two;
1630 float norm_sum, norm_fact;
1631 unsigned int i;
1632
1633 /* Set the length */
1634 cvt->len_sinc = m + 1;
1635
1636 /* Allocate the floating point windowed sinc. */
1637 fSinc = SDL_stack_alloc(float, (m + 1));
1638 if (fSinc == NULL) {
1639 return -1;
1640 }
1641
1642 /* Set up the filter parameters */
1643 fc = (cvt->len_mult >
1644 cvt->len_div) ? 0.5f / (float) cvt->len_mult : 0.5f /
1645 (float) cvt->len_div;
1646 #ifdef DEBUG_CONVERT
1647 printf("Lowpass cutoff frequency = %f\n", fc);
1648 #endif
1649 two_pi_fc = 2.0f * M_PI * fc;
1650 two_pi_over_m = 2.0f * M_PI / (float) m;
1651 four_pi_over_m = 2.0f * two_pi_over_m;
1652 m_over_two = (float) m / 2.0f;
1653 norm_sum = 0.0f;
1654
1655 for (i = 0; i <= m; ++i) {
1656 if (i == m / 2) {
1657 fSinc[i] = two_pi_fc;
1658 } else { 942 } else {
1659 fSinc[i] = SDL_sinf(two_pi_fc * ((float) i - m_over_two)) / ((float) i - m_over_two); 943 cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
1660 /* Apply blackman window */ 944 }
1661 fSinc[i] *= 0.42f - 0.5f * SDL_cosf(two_pi_over_m * (float) i) + 0.08f * SDL_cosf(four_pi_over_m * (float) i); 945
1662 } 946 return 1; /* added a converter. */
1663 norm_sum += fSinc[i] < 0 ? -fSinc[i] : fSinc[i]; /* fabs(fSinc[i]); */ 947 }
1664 } 948
1665 949 return 0; /* no conversion necessary. */
1666 norm_fact = 1.0f / norm_sum;
1667
1668 #define convert_fixed(type, fix) { \
1669 type *dst = (type *)cvt->coeff; \
1670 for( i = 0; i <= m; ++i ) { \
1671 dst[i] = fix(fSinc[i] * norm_fact); \
1672 } \
1673 }
1674
1675 /* !!! FIXME: this memory leaks. */
1676 cvt->coeff =
1677 (Uint8 *) SDL_malloc((SDL_AUDIO_BITSIZE(format) / 8) * (m + 1));
1678 if (cvt->coeff == NULL) {
1679 return -1;
1680 }
1681
1682 /* If we're using floating point, we only need to normalize */
1683 if (SDL_AUDIO_ISFLOAT(format) && SDL_AUDIO_BITSIZE(format) == 32) {
1684 float *fDest = (float *) cvt->coeff;
1685 for (i = 0; i <= m; ++i) {
1686 fDest[i] = fSinc[i] * norm_fact;
1687 }
1688 } else {
1689 switch (SDL_AUDIO_BITSIZE(format)) {
1690 case 8:
1691 convert_fixed(Uint8, SDL_Make_1_7);
1692 break;
1693 case 16:
1694 convert_fixed(Uint16, SDL_Make_1_15);
1695 break;
1696 case 32:
1697 convert_fixed(Uint32, SDL_Make_1_31);
1698 break;
1699 }
1700 }
1701
1702 /* Initialize the state buffer to all zeroes, and set initial position */
1703 /* !!! FIXME: this memory leaks. */
1704 cvt->state_buf =
1705 (Uint8 *) SDL_malloc(cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
1706 if (cvt->state_buf == NULL) {
1707 return -1;
1708 }
1709 SDL_memset(cvt->state_buf, 0,
1710 cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
1711 cvt->state_pos = 0;
1712
1713 /* Clean up */
1714 #undef convert_fixed
1715 SDL_stack_free(fSinc);
1716
1717 return 0;
1718 }
1719
1720 /* This is used to reduce the resampling ratio */
1721 static __inline__ int
1722 SDL_GCD(int a, int b)
1723 {
1724 int temp;
1725 while (b != 0) {
1726 temp = a % b;
1727 a = b;
1728 b = temp;
1729 }
1730 return a;
1731 }
1732
1733 /* Perform proper resampling. This is pretty slow but it's the best-sounding method. */
1734 static void SDLCALL
1735 SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format)
1736 {
1737 int i;
1738
1739 #ifdef DEBUG_CONVERT
1740 printf("Converting audio rate via proper resampling (mono)\n");
1741 #endif
1742
1743 #define zerostuff_mono(type) { \
1744 const type *src = (const type *) (cvt->buf + cvt->len); \
1745 type *dst = (type *) (cvt->buf + (cvt->len * cvt->len_mult)); \
1746 for (i = cvt->len / sizeof (type); i; --i) { \
1747 src--; \
1748 dst[-1] = src[0]; \
1749 if (cvt->len_mult > 1) { \
1750 SDL_memset(dst-cvt->len_mult, 0, cvt->len_mult-1); \
1751 } \
1752 dst -= cvt->len_mult; \
1753 } \
1754 }
1755
1756 #define discard_mono(type) { \
1757 const type *src = (const type *) (cvt->buf); \
1758 type *dst = (type *) (cvt->buf); \
1759 for (i = 0; i < (cvt->len_cvt / sizeof(type)) / cvt->len_div; ++i) { \
1760 dst[0] = src[0]; \
1761 src += cvt->len_div; \
1762 ++dst; \
1763 } \
1764 }
1765
1766 /* Step 1: Zero stuff the conversion buffer. This upsamples by a factor of len_mult,
1767 creating aliasing at frequencies above the original nyquist frequency.
1768 */
1769 #ifdef DEBUG_CONVERT
1770 printf("Zero-stuffing by a factor of %u\n", cvt->len_mult);
1771 #endif
1772 switch (SDL_AUDIO_BITSIZE(format)) {
1773 case 8:
1774 zerostuff_mono(Uint8);
1775 break;
1776 case 16:
1777 zerostuff_mono(Uint16);
1778 break;
1779 case 32:
1780 zerostuff_mono(Uint32);
1781 break;
1782 }
1783
1784 cvt->len_cvt *= cvt->len_mult;
1785
1786 /* Step 2: Use a windowed sinc FIR filter (lowpass filter) to remove the alias
1787 frequencies. This is the slow part.
1788 */
1789 SDL_FilterFIR(cvt, format);
1790
1791 /* Step 3: Now downsample by discarding samples. */
1792
1793 #ifdef DEBUG_CONVERT
1794 printf("Discarding samples by a factor of %u\n", cvt->len_div);
1795 #endif
1796 switch (SDL_AUDIO_BITSIZE(format)) {
1797 case 8:
1798 discard_mono(Uint8);
1799 break;
1800 case 16:
1801 discard_mono(Uint16);
1802 break;
1803 case 32:
1804 discard_mono(Uint32);
1805 break;
1806 }
1807
1808 #undef zerostuff_mono
1809 #undef discard_mono
1810
1811 cvt->len_cvt /= cvt->len_div;
1812
1813 if (cvt->filters[++cvt->filter_index]) {
1814 cvt->filters[cvt->filter_index] (cvt, format);
1815 }
1816 } 950 }
1817 951
1818 952
1819 /* Creates a set of audio filters to convert from one format to another. 953 /* Creates a set of audio filters to convert from one format to another.
1820 Returns -1 if the format conversion is not supported, 0 if there's 954 Returns -1 if the format conversion is not supported, 0 if there's
1824 int 958 int
1825 SDL_BuildAudioCVT(SDL_AudioCVT * cvt, 959 SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
1826 SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate, 960 SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
1827 SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate) 961 SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
1828 { 962 {
963 /*
964 * !!! FIXME: reorder filters based on which grow/shrink the buffer.
965 * !!! FIXME: ideally, we should do everything that shrinks the buffer
966 * !!! FIXME: first, so we don't have to process as many bytes in a given
967 * !!! FIXME: filter and abuse the CPU cache less. This might not be as
968 * !!! FIXME: good in practice as it sounds in theory, though.
969 */
970
1829 /* there are no unsigned types over 16 bits, so catch this upfront. */ 971 /* there are no unsigned types over 16 bits, so catch this upfront. */
1830 if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) { 972 if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
1831 return -1; 973 return -1;
1832 } 974 }
1833 if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) { 975 if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
1834 return -1; 976 return -1;
1835 } 977 }
978
979 /* prevent possible divisions by zero, etc. */
980 if ((src_rate == 0) || (dst_rate == 0)) {
981 return -1;
982 }
983
1836 #ifdef DEBUG_CONVERT 984 #ifdef DEBUG_CONVERT
1837 printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n", 985 printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
1838 src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate); 986 src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
1839 #endif 987 #endif
1840 988
1845 cvt->needed = 0; 993 cvt->needed = 0;
1846 cvt->filter_index = 0; 994 cvt->filter_index = 0;
1847 cvt->filters[0] = NULL; 995 cvt->filters[0] = NULL;
1848 cvt->len_mult = 1; 996 cvt->len_mult = 1;
1849 cvt->len_ratio = 1.0; 997 cvt->len_ratio = 1.0;
998 cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
1850 999
1851 /* Convert data types, if necessary. Updates (cvt). */ 1000 /* Convert data types, if necessary. Updates (cvt). */
1852 if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1) 1001 if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1) {
1853 return -1; /* shouldn't happen, but just in case... */ 1002 return -1; /* shouldn't happen, but just in case... */
1003 }
1854 1004
1855 /* Channel conversion */ 1005 /* Channel conversion */
1856 if (src_channels != dst_channels) { 1006 if (src_channels != dst_channels) {
1857 if ((src_channels == 1) && (dst_channels > 1)) { 1007 if ((src_channels == 1) && (dst_channels > 1)) {
1858 cvt->filters[cvt->filter_index++] = SDL_ConvertStereo; 1008 cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
1901 if (src_channels != dst_channels) { 1051 if (src_channels != dst_channels) {
1902 /* Uh oh.. */ ; 1052 /* Uh oh.. */ ;
1903 } 1053 }
1904 } 1054 }
1905 1055
1906 /* Do rate conversion */ 1056 /* Do rate conversion, if necessary. Updates (cvt). */
1907 if (src_rate != dst_rate) { 1057 if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) == -1) {
1908 int rate_gcd; 1058 return -1; /* shouldn't happen, but just in case... */
1909 rate_gcd = SDL_GCD(src_rate, dst_rate); 1059 }
1910 cvt->len_mult = dst_rate / rate_gcd;
1911 cvt->len_div = src_rate / rate_gcd;
1912 cvt->len_ratio = (double) cvt->len_mult / (double) cvt->len_div;
1913 cvt->filters[cvt->filter_index++] = SDL_Resample;
1914 /* !!! FIXME: check return value. */
1915 SDL_BuildWindowedSinc(cvt, dst_fmt, 768);
1916 }
1917
1918 /*
1919 cvt->rate_incr = 0.0;
1920 if ((src_rate / 100) != (dst_rate / 100)) {
1921 Uint32 hi_rate, lo_rate;
1922 int len_mult;
1923 double len_ratio;
1924 SDL_AudioFilter rate_cvt = NULL;
1925
1926 if (src_rate > dst_rate) {
1927 hi_rate = src_rate;
1928 lo_rate = dst_rate;
1929 switch (src_channels) {
1930 case 1:
1931 rate_cvt = SDL_RateDIV2;
1932 break;
1933 case 2:
1934 rate_cvt = SDL_RateDIV2_c2;
1935 break;
1936 case 4:
1937 rate_cvt = SDL_RateDIV2_c4;
1938 break;
1939 case 6:
1940 rate_cvt = SDL_RateDIV2_c6;
1941 break;
1942 default:
1943 return -1;
1944 }
1945 len_mult = 1;
1946 len_ratio = 0.5;
1947 } else {
1948 hi_rate = dst_rate;
1949 lo_rate = src_rate;
1950 switch (src_channels) {
1951 case 1:
1952 rate_cvt = SDL_RateMUL2;
1953 break;
1954 case 2:
1955 rate_cvt = SDL_RateMUL2_c2;
1956 break;
1957 case 4:
1958 rate_cvt = SDL_RateMUL2_c4;
1959 break;
1960 case 6:
1961 rate_cvt = SDL_RateMUL2_c6;
1962 break;
1963 default:
1964 return -1;
1965 }
1966 len_mult = 2;
1967 len_ratio = 2.0;
1968 }*/
1969 /* If hi_rate = lo_rate*2^x then conversion is easy */
1970 /* while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
1971 cvt->filters[cvt->filter_index++] = rate_cvt;
1972 cvt->len_mult *= len_mult;
1973 lo_rate *= 2;
1974 cvt->len_ratio *= len_ratio;
1975 } */
1976 /* We may need a slow conversion here to finish up */
1977 /* if ((lo_rate / 100) != (hi_rate / 100)) {
1978 #if 1 */
1979 /* The problem with this is that if the input buffer is
1980 say 1K, and the conversion rate is say 1.1, then the
1981 output buffer is 1.1K, which may not be an acceptable
1982 buffer size for the audio driver (not a power of 2)
1983 */
1984 /* For now, punt and hope the rate distortion isn't great.
1985 */
1986 /*#else
1987 if (src_rate < dst_rate) {
1988 cvt->rate_incr = (double) lo_rate / hi_rate;
1989 cvt->len_mult *= 2;
1990 cvt->len_ratio /= cvt->rate_incr;
1991 } else {
1992 cvt->rate_incr = (double) hi_rate / lo_rate;
1993 cvt->len_ratio *= cvt->rate_incr;
1994 }
1995 cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
1996 #endif
1997 }
1998 }*/
1999 1060
2000 /* Set up the filter information */ 1061 /* Set up the filter information */
2001 if (cvt->filter_index != 0) { 1062 if (cvt->filter_index != 0) {
2002 cvt->needed = 1; 1063 cvt->needed = 1;
2003 cvt->src_format = src_fmt; 1064 cvt->src_format = src_fmt;
2007 cvt->filters[cvt->filter_index] = NULL; 1068 cvt->filters[cvt->filter_index] = NULL;
2008 } 1069 }
2009 return (cvt->needed); 1070 return (cvt->needed);
2010 } 1071 }
2011 1072
2012 #undef SDL_FixMpy8
2013 #undef SDL_FixMpy16
2014 #undef SDL_FixMpy32
2015 #undef SDL_FloatMpy
2016 #undef SDL_Make_1_7
2017 #undef SDL_Make_1_15
2018 #undef SDL_Make_1_31
2019 #undef SDL_Make_2_6
2020 #undef SDL_Make_2_14
2021 #undef SDL_Make_2_30
2022 1073
2023 /* vi: set ts=4 sw=4 expandtab: */ 1074 /* vi: set ts=4 sw=4 expandtab: */