sdlgenaudiocvt.pl 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. #!/usr/bin/perl -w
  2. use warnings;
  3. use strict;
  4. my @audiotypes = qw(
  5. U8
  6. S8
  7. U16LSB
  8. S16LSB
  9. U16MSB
  10. S16MSB
  11. S32LSB
  12. S32MSB
  13. F32LSB
  14. F32MSB
  15. );
  16. my @channels = ( 1, 2, 4, 6, 8 );
  17. my %funcs;
  18. my $custom_converters = 0;
  19. sub getTypeConvertHashId {
  20. my ($from, $to) = @_;
  21. return "TYPECONVERTER $from/$to";
  22. }
  23. sub getResamplerHashId {
  24. my ($from, $channels, $upsample, $multiple) = @_;
  25. return "RESAMPLER $from/$channels/$upsample/$multiple";
  26. }
  27. sub outputHeader {
  28. print <<EOF;
  29. /* DO NOT EDIT! This file is generated by sdlgenaudiocvt.pl */
  30. /*
  31. Simple DirectMedia Layer
  32. Copyright (C) 1997-2014 Sam Lantinga <slouken\@libsdl.org>
  33. This software is provided 'as-is', without any express or implied
  34. warranty. In no event will the authors be held liable for any damages
  35. arising from the use of this software.
  36. Permission is granted to anyone to use this software for any purpose,
  37. including commercial applications, and to alter it and redistribute it
  38. freely, subject to the following restrictions:
  39. 1. The origin of this software must not be misrepresented; you must not
  40. claim that you wrote the original software. If you use this software
  41. in a product, an acknowledgment in the product documentation would be
  42. appreciated but is not required.
  43. 2. Altered source versions must be plainly marked as such, and must not be
  44. misrepresented as being the original software.
  45. 3. This notice may not be removed or altered from any source distribution.
  46. */
  47. #include "../SDL_internal.h"
  48. #include "SDL_audio.h"
  49. #include "SDL_audio_c.h"
  50. #ifndef DEBUG_CONVERT
  51. #define DEBUG_CONVERT 0
  52. #endif
  53. /* If you can guarantee your data and need space, you can eliminate code... */
  54. /* Just build the arbitrary resamplers if you're saving code space. */
  55. #ifndef LESS_RESAMPLERS
  56. #define LESS_RESAMPLERS 0
  57. #endif
  58. /* Don't build any resamplers if you're REALLY saving code space. */
  59. #ifndef NO_RESAMPLERS
  60. #define NO_RESAMPLERS 0
  61. #endif
  62. /* Don't build any type converters if you're saving code space. */
  63. #ifndef NO_CONVERTERS
  64. #define NO_CONVERTERS 0
  65. #endif
  66. /* *INDENT-OFF* */
  67. EOF
  68. my @vals = ( 127, 32767, 2147483647 );
  69. foreach (@vals) {
  70. my $val = $_;
  71. my $fval = 1.0 / $val;
  72. print("#define DIVBY${val} ${fval}f\n");
  73. }
  74. print("\n");
  75. }
  76. sub outputFooter {
  77. print <<EOF;
  78. /* $custom_converters converters generated. */
  79. /* *INDENT-ON* */
  80. /* vi: set ts=4 sw=4 expandtab: */
  81. EOF
  82. }
  83. sub splittype {
  84. my $t = shift;
  85. my ($signed, $size, $endian) = $t =~ /([USF])(\d+)([LM]SB|)/;
  86. my $float = ($signed eq 'F') ? 1 : 0;
  87. $signed = (($float) or ($signed eq 'S')) ? 1 : 0;
  88. $endian = 'NONE' if ($endian eq '');
  89. my $ctype = '';
  90. if ($float) {
  91. $ctype = (($size == 32) ? 'float' : 'double');
  92. } else {
  93. $ctype = (($signed) ? 'S' : 'U') . "int${size}";
  94. }
  95. return ($signed, $float, $size, $endian, $ctype);
  96. }
  97. sub getSwapFunc {
  98. my ($size, $signed, $float, $endian, $val) = @_;
  99. my $BEorLE = (($endian eq 'MSB') ? 'BE' : 'LE');
  100. my $code = '';
  101. if ($float) {
  102. $code = "SDL_SwapFloat${BEorLE}($val)";
  103. } else {
  104. if ($size > 8) {
  105. $code = "SDL_Swap${BEorLE}${size}($val)";
  106. } else {
  107. $code = $val;
  108. }
  109. if (($signed) and (!$float)) {
  110. $code = "((Sint${size}) $code)";
  111. }
  112. }
  113. return "${code}";
  114. }
  115. sub maxIntVal {
  116. my $size = shift;
  117. if ($size == 8) {
  118. return 0x7F;
  119. } elsif ($size == 16) {
  120. return 0x7FFF;
  121. } elsif ($size == 32) {
  122. return 0x7FFFFFFF;
  123. }
  124. die("bug in script.\n");
  125. }
  126. sub getFloatToIntMult {
  127. my $size = shift;
  128. my $val = maxIntVal($size) . '.0';
  129. $val .= 'f' if ($size < 32);
  130. return $val;
  131. }
  132. sub getIntToFloatDivBy {
  133. my $size = shift;
  134. return 'DIVBY' . maxIntVal($size);
  135. }
  136. sub getSignFlipVal {
  137. my $size = shift;
  138. if ($size == 8) {
  139. return '0x80';
  140. } elsif ($size == 16) {
  141. return '0x8000';
  142. } elsif ($size == 32) {
  143. return '0x80000000';
  144. }
  145. die("bug in script.\n");
  146. }
  147. sub buildCvtFunc {
  148. my ($from, $to) = @_;
  149. my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
  150. my ($tsigned, $tfloat, $tsize, $tendian, $tctype) = splittype($to);
  151. my $diffs = 0;
  152. $diffs++ if ($fsize != $tsize);
  153. $diffs++ if ($fsigned != $tsigned);
  154. $diffs++ if ($ffloat != $tfloat);
  155. $diffs++ if ($fendian ne $tendian);
  156. return if ($diffs == 0);
  157. my $hashid = getTypeConvertHashId($from, $to);
  158. if (1) { # !!! FIXME: if ($diffs > 1) {
  159. my $sym = "SDL_Convert_${from}_to_${to}";
  160. $funcs{$hashid} = $sym;
  161. $custom_converters++;
  162. # Always unsigned for ints, for possible byteswaps.
  163. my $srctype = (($ffloat) ? 'float' : "Uint${fsize}");
  164. print <<EOF;
  165. static void SDLCALL
  166. ${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  167. {
  168. int i;
  169. const $srctype *src;
  170. $tctype *dst;
  171. #if DEBUG_CONVERT
  172. fprintf(stderr, "Converting AUDIO_${from} to AUDIO_${to}.\\n");
  173. #endif
  174. EOF
  175. if ($fsize < $tsize) {
  176. my $mult = $tsize / $fsize;
  177. print <<EOF;
  178. src = ((const $srctype *) (cvt->buf + cvt->len_cvt)) - 1;
  179. dst = (($tctype *) (cvt->buf + cvt->len_cvt * $mult)) - 1;
  180. for (i = cvt->len_cvt / sizeof ($srctype); i; --i, --src, --dst) {
  181. EOF
  182. } else {
  183. print <<EOF;
  184. src = (const $srctype *) cvt->buf;
  185. dst = ($tctype *) cvt->buf;
  186. for (i = cvt->len_cvt / sizeof ($srctype); i; --i, ++src, ++dst) {
  187. EOF
  188. }
  189. # Have to convert to/from float/int.
  190. # !!! FIXME: cast through double for int32<->float?
  191. my $code = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, '*src');
  192. if ($ffloat != $tfloat) {
  193. if ($ffloat) {
  194. my $mult = getFloatToIntMult($tsize);
  195. if (!$tsigned) { # bump from -1.0f/1.0f to 0.0f/2.0f
  196. $code = "($code + 1.0f)";
  197. }
  198. $code = "(($tctype) ($code * $mult))";
  199. } else {
  200. # $divby will be the reciprocal, to avoid pipeline stalls
  201. # from floating point division...so multiply it.
  202. my $divby = getIntToFloatDivBy($fsize);
  203. $code = "(((float) $code) * $divby)";
  204. if (!$fsigned) { # bump from 0.0f/2.0f to -1.0f/1.0f.
  205. $code = "($code - 1.0f)";
  206. }
  207. }
  208. } else {
  209. # All integer conversions here.
  210. if ($fsigned != $tsigned) {
  211. my $signflipval = getSignFlipVal($fsize);
  212. $code = "(($code) ^ $signflipval)";
  213. }
  214. my $shiftval = abs($fsize - $tsize);
  215. if ($fsize < $tsize) {
  216. $code = "((($tctype) $code) << $shiftval)";
  217. } elsif ($fsize > $tsize) {
  218. $code = "(($tctype) ($code >> $shiftval))";
  219. }
  220. }
  221. my $swap = getSwapFunc($tsize, $tsigned, $tfloat, $tendian, 'val');
  222. print <<EOF;
  223. const $tctype val = $code;
  224. *dst = ${swap};
  225. }
  226. EOF
  227. if ($fsize > $tsize) {
  228. my $divby = $fsize / $tsize;
  229. print(" cvt->len_cvt /= $divby;\n");
  230. } elsif ($fsize < $tsize) {
  231. my $mult = $tsize / $fsize;
  232. print(" cvt->len_cvt *= $mult;\n");
  233. }
  234. print <<EOF;
  235. if (cvt->filters[++cvt->filter_index]) {
  236. cvt->filters[cvt->filter_index] (cvt, AUDIO_$to);
  237. }
  238. }
  239. EOF
  240. } else {
  241. if ($fsigned != $tsigned) {
  242. $funcs{$hashid} = 'SDL_ConvertSigned';
  243. } elsif ($ffloat != $tfloat) {
  244. $funcs{$hashid} = 'SDL_ConvertFloat';
  245. } elsif ($fsize != $tsize) {
  246. $funcs{$hashid} = 'SDL_ConvertSize';
  247. } elsif ($fendian ne $tendian) {
  248. $funcs{$hashid} = 'SDL_ConvertEndian';
  249. } else {
  250. die("error in script.\n");
  251. }
  252. }
  253. }
  254. sub buildTypeConverters {
  255. print "#if !NO_CONVERTERS\n\n";
  256. foreach (@audiotypes) {
  257. my $from = $_;
  258. foreach (@audiotypes) {
  259. my $to = $_;
  260. buildCvtFunc($from, $to);
  261. }
  262. }
  263. print "#endif /* !NO_CONVERTERS */\n\n\n";
  264. print "const SDL_AudioTypeFilters sdl_audio_type_filters[] =\n{\n";
  265. print "#if !NO_CONVERTERS\n";
  266. foreach (@audiotypes) {
  267. my $from = $_;
  268. foreach (@audiotypes) {
  269. my $to = $_;
  270. if ($from ne $to) {
  271. my $hashid = getTypeConvertHashId($from, $to);
  272. my $sym = $funcs{$hashid};
  273. print(" { AUDIO_$from, AUDIO_$to, $sym },\n");
  274. }
  275. }
  276. }
  277. print "#endif /* !NO_CONVERTERS */\n";
  278. print(" { 0, 0, NULL }\n");
  279. print "};\n\n\n";
  280. }
  281. sub getBiggerCtype {
  282. my ($isfloat, $size) = @_;
  283. if ($isfloat) {
  284. if ($size == 32) {
  285. return 'double';
  286. }
  287. die("bug in script.\n");
  288. }
  289. if ($size == 8) {
  290. return 'Sint16';
  291. } elsif ($size == 16) {
  292. return 'Sint32'
  293. } elsif ($size == 32) {
  294. return 'Sint64'
  295. }
  296. die("bug in script.\n");
  297. }
  298. # These handle arbitrary resamples...44100Hz to 48000Hz, for example.
  299. # Man, this code is skanky.
  300. sub buildArbitraryResampleFunc {
  301. # !!! FIXME: we do a lot of unnecessary and ugly casting in here, due to getSwapFunc().
  302. my ($from, $channels, $upsample) = @_;
  303. my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
  304. my $bigger = getBiggerCtype($ffloat, $fsize);
  305. my $interp = ($ffloat) ? '* 0.5' : '>> 1';
  306. my $resample = ($upsample) ? 'Upsample' : 'Downsample';
  307. my $hashid = getResamplerHashId($from, $channels, $upsample, 0);
  308. my $sym = "SDL_${resample}_${from}_${channels}c";
  309. $funcs{$hashid} = $sym;
  310. $custom_converters++;
  311. my $fudge = $fsize * $channels * 2; # !!! FIXME
  312. my $eps_adjust = ($upsample) ? 'dstsize' : 'srcsize';
  313. my $incr = '';
  314. my $incr2 = '';
  315. # !!! FIXME: DEBUG_CONVERT should report frequencies.
  316. print <<EOF;
  317. static void SDLCALL
  318. ${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  319. {
  320. #if DEBUG_CONVERT
  321. fprintf(stderr, "$resample arbitrary (x%f) AUDIO_${from}, ${channels} channels.\\n", cvt->rate_incr);
  322. #endif
  323. const int srcsize = cvt->len_cvt - $fudge;
  324. const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
  325. register int eps = 0;
  326. EOF
  327. my $endcomparison = '!=';
  328. # Upsampling (growing the buffer) needs to work backwards, since we
  329. # overwrite the buffer as we go.
  330. if ($upsample) {
  331. $endcomparison = '>='; # dst > target
  332. print <<EOF;
  333. $fctype *dst = (($fctype *) (cvt->buf + dstsize)) - $channels;
  334. const $fctype *src = (($fctype *) (cvt->buf + cvt->len_cvt)) - $channels;
  335. const $fctype *target = ((const $fctype *) cvt->buf);
  336. EOF
  337. } else {
  338. $endcomparison = '<'; # dst < target
  339. print <<EOF;
  340. $fctype *dst = ($fctype *) cvt->buf;
  341. const $fctype *src = ($fctype *) cvt->buf;
  342. const $fctype *target = (const $fctype *) (cvt->buf + dstsize);
  343. EOF
  344. }
  345. for (my $i = 0; $i < $channels; $i++) {
  346. my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
  347. my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
  348. print <<EOF;
  349. $fctype sample${idx} = $val;
  350. EOF
  351. }
  352. for (my $i = 0; $i < $channels; $i++) {
  353. my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
  354. print <<EOF;
  355. $fctype last_sample${idx} = sample${idx};
  356. EOF
  357. }
  358. print <<EOF;
  359. while (dst $endcomparison target) {
  360. EOF
  361. if ($upsample) {
  362. for (my $i = 0; $i < $channels; $i++) {
  363. # !!! FIXME: don't do this swap every write, just when the samples change.
  364. my $idx = (($channels - $i) - 1);
  365. my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "sample${idx}");
  366. print <<EOF;
  367. dst[$idx] = $val;
  368. EOF
  369. }
  370. $incr = ($channels == 1) ? 'dst--' : "dst -= $channels";
  371. $incr2 = ($channels == 1) ? 'src--' : "src -= $channels";
  372. print <<EOF;
  373. $incr;
  374. eps += srcsize;
  375. if ((eps << 1) >= dstsize) {
  376. $incr2;
  377. EOF
  378. } else { # downsample.
  379. $incr = ($channels == 1) ? 'src++' : "src += $channels";
  380. print <<EOF;
  381. $incr;
  382. eps += dstsize;
  383. if ((eps << 1) >= srcsize) {
  384. EOF
  385. for (my $i = 0; $i < $channels; $i++) {
  386. my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "sample${i}");
  387. print <<EOF;
  388. dst[$i] = $val;
  389. EOF
  390. }
  391. $incr = ($channels == 1) ? 'dst++' : "dst += $channels";
  392. print <<EOF;
  393. $incr;
  394. EOF
  395. }
  396. for (my $i = 0; $i < $channels; $i++) {
  397. my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
  398. my $swapped = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
  399. print <<EOF;
  400. sample${idx} = ($fctype) (((($bigger) $swapped) + (($bigger) last_sample${idx})) $interp);
  401. EOF
  402. }
  403. for (my $i = 0; $i < $channels; $i++) {
  404. my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
  405. print <<EOF;
  406. last_sample${idx} = sample${idx};
  407. EOF
  408. }
  409. print <<EOF;
  410. eps -= $eps_adjust;
  411. }
  412. }
  413. EOF
  414. print <<EOF;
  415. cvt->len_cvt = dstsize;
  416. if (cvt->filters[++cvt->filter_index]) {
  417. cvt->filters[cvt->filter_index] (cvt, format);
  418. }
  419. }
  420. EOF
  421. }
  422. # These handle clean resamples...doubling and quadrupling the sample rate, etc.
  423. sub buildMultipleResampleFunc {
  424. # !!! FIXME: we do a lot of unnecessary and ugly casting in here, due to getSwapFunc().
  425. my ($from, $channels, $upsample, $multiple) = @_;
  426. my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
  427. my $bigger = getBiggerCtype($ffloat, $fsize);
  428. my $interp = ($ffloat) ? '* 0.5' : '>> 1';
  429. my $interp2 = ($ffloat) ? '* 0.25' : '>> 2';
  430. my $mult3 = ($ffloat) ? '3.0' : '3';
  431. my $lencvtop = ($upsample) ? '*' : '/';
  432. my $resample = ($upsample) ? 'Upsample' : 'Downsample';
  433. my $hashid = getResamplerHashId($from, $channels, $upsample, $multiple);
  434. my $sym = "SDL_${resample}_${from}_${channels}c_x${multiple}";
  435. $funcs{$hashid} = $sym;
  436. $custom_converters++;
  437. # !!! FIXME: DEBUG_CONVERT should report frequencies.
  438. print <<EOF;
  439. static void SDLCALL
  440. ${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
  441. {
  442. #if DEBUG_CONVERT
  443. fprintf(stderr, "$resample (x${multiple}) AUDIO_${from}, ${channels} channels.\\n");
  444. #endif
  445. const int dstsize = cvt->len_cvt $lencvtop $multiple;
  446. EOF
  447. my $endcomparison = '!=';
  448. # Upsampling (growing the buffer) needs to work backwards, since we
  449. # overwrite the buffer as we go.
  450. if ($upsample) {
  451. $endcomparison = '>='; # dst > target
  452. print <<EOF;
  453. $fctype *dst = (($fctype *) (cvt->buf + dstsize)) - $channels * $multiple;
  454. const $fctype *src = (($fctype *) (cvt->buf + cvt->len_cvt)) - $channels;
  455. const $fctype *target = ((const $fctype *) cvt->buf);
  456. EOF
  457. } else {
  458. $endcomparison = '<'; # dst < target
  459. print <<EOF;
  460. $fctype *dst = ($fctype *) cvt->buf;
  461. const $fctype *src = ($fctype *) cvt->buf;
  462. const $fctype *target = (const $fctype *) (cvt->buf + dstsize);
  463. EOF
  464. }
  465. for (my $i = 0; $i < $channels; $i++) {
  466. my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
  467. my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
  468. print <<EOF;
  469. $bigger last_sample${idx} = ($bigger) $val;
  470. EOF
  471. }
  472. print <<EOF;
  473. while (dst $endcomparison target) {
  474. EOF
  475. for (my $i = 0; $i < $channels; $i++) {
  476. my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
  477. my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
  478. print <<EOF;
  479. const $bigger sample${idx} = ($bigger) $val;
  480. EOF
  481. }
  482. my $incr = '';
  483. if ($upsample) {
  484. $incr = ($channels == 1) ? 'src--' : "src -= $channels";
  485. } else {
  486. my $amount = $channels * $multiple;
  487. $incr = "src += $amount"; # can't ever be 1, so no "++" version.
  488. }
  489. print <<EOF;
  490. $incr;
  491. EOF
  492. # !!! FIXME: This really begs for some Altivec or SSE, etc.
  493. if ($upsample) {
  494. if ($multiple == 2) {
  495. for (my $i = $channels-1; $i >= 0; $i--) {
  496. my $dsti = $i + $channels;
  497. print <<EOF;
  498. dst[$dsti] = ($fctype) ((sample${i} + last_sample${i}) $interp);
  499. EOF
  500. }
  501. for (my $i = $channels-1; $i >= 0; $i--) {
  502. my $dsti = $i;
  503. print <<EOF;
  504. dst[$dsti] = ($fctype) sample${i};
  505. EOF
  506. }
  507. } elsif ($multiple == 4) {
  508. for (my $i = $channels-1; $i >= 0; $i--) {
  509. my $dsti = $i + ($channels * 3);
  510. print <<EOF;
  511. dst[$dsti] = ($fctype) ((sample${i} + ($mult3 * last_sample${i})) $interp2);
  512. EOF
  513. }
  514. for (my $i = $channels-1; $i >= 0; $i--) {
  515. my $dsti = $i + ($channels * 2);
  516. print <<EOF;
  517. dst[$dsti] = ($fctype) ((sample${i} + last_sample${i}) $interp);
  518. EOF
  519. }
  520. for (my $i = $channels-1; $i >= 0; $i--) {
  521. my $dsti = $i + ($channels * 1);
  522. print <<EOF;
  523. dst[$dsti] = ($fctype) ((($mult3 * sample${i}) + last_sample${i}) $interp2);
  524. EOF
  525. }
  526. for (my $i = $channels-1; $i >= 0; $i--) {
  527. my $dsti = $i + ($channels * 0);
  528. print <<EOF;
  529. dst[$dsti] = ($fctype) sample${i};
  530. EOF
  531. }
  532. } else {
  533. die('bug in program.'); # we only handle x2 and x4.
  534. }
  535. } else { # downsample.
  536. if ($multiple == 2) {
  537. for (my $i = 0; $i < $channels; $i++) {
  538. print <<EOF;
  539. dst[$i] = ($fctype) ((sample${i} + last_sample${i}) $interp);
  540. EOF
  541. }
  542. } elsif ($multiple == 4) {
  543. # !!! FIXME: interpolate all 4 samples?
  544. for (my $i = 0; $i < $channels; $i++) {
  545. print <<EOF;
  546. dst[$i] = ($fctype) ((sample${i} + last_sample${i}) $interp);
  547. EOF
  548. }
  549. } else {
  550. die('bug in program.'); # we only handle x2 and x4.
  551. }
  552. }
  553. for (my $i = 0; $i < $channels; $i++) {
  554. my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
  555. print <<EOF;
  556. last_sample${idx} = sample${idx};
  557. EOF
  558. }
  559. if ($upsample) {
  560. my $amount = $channels * $multiple;
  561. $incr = "dst -= $amount"; # can't ever be 1, so no "--" version.
  562. } else {
  563. $incr = ($channels == 1) ? 'dst++' : "dst += $channels";
  564. }
  565. print <<EOF;
  566. $incr;
  567. }
  568. cvt->len_cvt = dstsize;
  569. if (cvt->filters[++cvt->filter_index]) {
  570. cvt->filters[cvt->filter_index] (cvt, format);
  571. }
  572. }
  573. EOF
  574. }
  575. sub buildResamplers {
  576. print "#if !NO_RESAMPLERS\n\n";
  577. foreach (@audiotypes) {
  578. my $from = $_;
  579. foreach (@channels) {
  580. my $channel = $_;
  581. buildArbitraryResampleFunc($from, $channel, 1);
  582. buildArbitraryResampleFunc($from, $channel, 0);
  583. }
  584. }
  585. print "\n#if !LESS_RESAMPLERS\n\n";
  586. foreach (@audiotypes) {
  587. my $from = $_;
  588. foreach (@channels) {
  589. my $channel = $_;
  590. for (my $multiple = 2; $multiple <= 4; $multiple += 2) {
  591. buildMultipleResampleFunc($from, $channel, 1, $multiple);
  592. buildMultipleResampleFunc($from, $channel, 0, $multiple);
  593. }
  594. }
  595. }
  596. print "#endif /* !LESS_RESAMPLERS */\n";
  597. print "#endif /* !NO_RESAMPLERS */\n\n\n";
  598. print "const SDL_AudioRateFilters sdl_audio_rate_filters[] =\n{\n";
  599. print "#if !NO_RESAMPLERS\n";
  600. foreach (@audiotypes) {
  601. my $from = $_;
  602. foreach (@channels) {
  603. my $channel = $_;
  604. for (my $upsample = 0; $upsample <= 1; $upsample++) {
  605. my $hashid = getResamplerHashId($from, $channel, $upsample, 0);
  606. my $sym = $funcs{$hashid};
  607. print(" { AUDIO_$from, $channel, $upsample, 0, $sym },\n");
  608. }
  609. }
  610. }
  611. print "#if !LESS_RESAMPLERS\n";
  612. foreach (@audiotypes) {
  613. my $from = $_;
  614. foreach (@channels) {
  615. my $channel = $_;
  616. for (my $multiple = 2; $multiple <= 4; $multiple += 2) {
  617. for (my $upsample = 0; $upsample <= 1; $upsample++) {
  618. my $hashid = getResamplerHashId($from, $channel, $upsample, $multiple);
  619. my $sym = $funcs{$hashid};
  620. print(" { AUDIO_$from, $channel, $upsample, $multiple, $sym },\n");
  621. }
  622. }
  623. }
  624. }
  625. print "#endif /* !LESS_RESAMPLERS */\n";
  626. print "#endif /* !NO_RESAMPLERS */\n";
  627. print(" { 0, 0, 0, 0, NULL }\n");
  628. print "};\n\n";
  629. }
  630. # mainline ...
  631. outputHeader();
  632. buildTypeConverters();
  633. buildResamplers();
  634. outputFooter();
  635. exit 0;
  636. # end of sdlgenaudiocvt.pl ...