Mercurial > sdl-ios-xcode
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: */ |