# Ticket #8661: ARM_ASM_Sound_Diffs.txt

File ARM_ASM_Sound_Diffs.txt, 44.7 KB (added by , 14 years ago) |
---|

Line | |
---|---|

1 | Index: sound/rate_arm.cpp |

2 | =================================================================== |

3 | --- sound/rate_arm.cpp (revision 0) |

4 | +++ sound/rate_arm.cpp (revision 0) |

5 | @@ -0,0 +1,428 @@ |

6 | +/* ScummVM - Scumm Interpreter |

7 | + * Copyright (C) 2001-2006 The ScummVM project |

8 | + * |

9 | + * This program is free software; you can redistribute it and/or |

10 | + * modify it under the terms of the GNU General Public License |

11 | + * as published by the Free Software Foundation; either version 2 |

12 | + * of the License, or (at your option) any later version. |

13 | + |

14 | + * This program is distributed in the hope that it will be useful, |

15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |

16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |

17 | + * GNU General Public License for more details. |

18 | + |

19 | + * You should have received a copy of the GNU General Public License |

20 | + * along with this program; if not, write to the Free Software |

21 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |

22 | + * |

23 | + * $URL$ |

24 | + * $Id$ |

25 | + * |

26 | + */ |

27 | + |

28 | +/* |

29 | + * The code in this file, together with the rate_arm_asm.s file offers |

30 | + * an ARM optimised version of the code in rate.cpp. The operation of this |

31 | + * code should be identical to that of rate.cpp, but faster. The heavy |

32 | + * lifting is done in the assembler file. |

33 | + * |

34 | + * To be as portable as possible we implement the core routines with C |

35 | + * linkage in assembly, and implement the C++ routines that call into |

36 | + * the C here. The C++ symbol mangling varies wildly between compilers, |

37 | + * so this is the simplest way to ensure that the C/C++ combination should |

38 | + * work on as many ARM based platforms as possible. |

39 | + * |

40 | + * Essentially the algorithm herein is the same as that in rate.cpp, so |

41 | + * anyone seeking to understand this should attempt to understand that |

42 | + * first. That code was based in turn on code with Copyright 1998 Fabrice |

43 | + * Bellard - part of SoX (http://sox.sourceforge.net). |

44 | + * Max Horn adapted that code to the needs of ScummVM and partially rewrote |

45 | + * it, in the process removing any use of floating point arithmetic. Various |

46 | + * other improvments over the original code were made. |

47 | + */ |

48 | + |

49 | +#include "common/stdafx.h" |

50 | +#include "sound/audiostream.h" |

51 | +#include "sound/rate.h" |

52 | +#include "sound/mixer.h" |

53 | +#include "common/util.h" |

54 | + |

55 | +namespace Audio { |

56 | + |

57 | +/** |

58 | + * The precision of the fractional computations used by the rate converter. |

59 | + * Normally you should never have to modify this value. |

60 | + */ |

61 | +#define FRAC_BITS 16 |

62 | + |

63 | +/** |

64 | + * The size of the intermediate input cache. Bigger values may increase |

65 | + * performance, but only until some point (depends largely on cache size, |

66 | + * target processor and various other factors), at which it will decrease |

67 | + * again. |

68 | + */ |

69 | +#define INTERMEDIATE_BUFFER_SIZE 512 |

70 | + |

71 | + |

72 | +/** |

73 | + * Audio rate converter based on simple resampling. Used when no |

74 | + * interpolation is required. |

75 | + * |

76 | + * Limited to sampling frequency <= 65535 Hz. |

77 | + */ |

78 | +typedef struct { |

79 | + const st_sample_t *inPtr; |

80 | + int inLen; |

81 | + |

82 | + /** position of how far output is ahead of input */ |

83 | + /** Holds what would have been opos-ipos */ |

84 | + long opos; |

85 | + |

86 | + /** fractional position increment in the output stream */ |

87 | + long opos_inc; |

88 | + |

89 | + st_sample_t inBuf[INTERMEDIATE_BUFFER_SIZE]; |

90 | +} SimpleRateDetails; |

91 | + |

92 | +template<bool stereo, bool reverseStereo> |

93 | +class SimpleRateConverter : public RateConverter { |

94 | +protected: |

95 | + SimpleRateDetails sr; |

96 | +public: |

97 | + SimpleRateConverter(st_rate_t inrate, st_rate_t outrate); |

98 | + int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r); |

99 | + int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) { |

100 | + return (ST_SUCCESS); |

101 | + } |

102 | +}; |

103 | + |

104 | + |

105 | +/* |

106 | + * Prepare processing. |

107 | + */ |

108 | +template<bool stereo, bool reverseStereo> |

109 | +SimpleRateConverter<stereo, reverseStereo>::SimpleRateConverter(st_rate_t inrate, st_rate_t outrate) { |

110 | + if (inrate == outrate) { |

111 | + error("Input and Output rates must be different to use rate effect"); |

112 | + } |

113 | + |

114 | + if ((inrate % outrate) != 0) { |

115 | + error("Input rate must be a multiple of Output rate to use rate effect"); |

116 | + } |

117 | + |

118 | + if (inrate >= 65536 || outrate >= 65536) { |

119 | + error("rate effect can only handle rates < 65536"); |

120 | + } |

121 | + |

122 | + sr.opos = 1; |

123 | + |

124 | + /* increment */ |

125 | + sr.opos_inc = inrate / outrate; |

126 | + |

127 | + sr.inLen = 0; |

128 | +} |

129 | + |

130 | +extern "C" void ARM_SimpleRate_M(AudioStream &input, |

131 | + int (*fn)(Audio::AudioStream&,int16*,int), |

132 | + SimpleRateDetails *sr, |

133 | + st_sample_t *obuf, |

134 | + st_size_t osamp, |

135 | + st_volume_t vol_l, |

136 | + st_volume_t vol_r); |

137 | + |

138 | +extern "C" void ARM_SimpleRate_S(AudioStream &input, |

139 | + int (*fn)(Audio::AudioStream&,int16*,int), |

140 | + SimpleRateDetails *sr, |

141 | + st_sample_t *obuf, |

142 | + st_size_t osamp, |

143 | + st_volume_t vol_l, |

144 | + st_volume_t vol_r); |

145 | + |

146 | +extern "C" void ARM_SimpleRate_R(AudioStream &input, |

147 | + int (*fn)(Audio::AudioStream&,int16*,int), |

148 | + SimpleRateDetails *sr, |

149 | + st_sample_t *obuf, |

150 | + st_size_t osamp, |

151 | + st_volume_t vol_l, |

152 | + st_volume_t vol_r); |

153 | + |

154 | +extern "C" int SimpleRate_readFudge(Audio::AudioStream &input, |

155 | + int16 *a, int b) |

156 | +{ |

157 | + return input.readBuffer(a, b); |

158 | +} |

159 | + |

160 | +template<bool stereo, bool reverseStereo> |

161 | +int SimpleRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) { |

162 | + |

163 | +#ifdef DEBUG_RATECONV |

164 | +fprintf(stderr, "Simple st=%d rev=%d\n", stereo, reverseStereo); |

165 | +fflush(stderr); |

166 | +#endif |

167 | + if (!stereo) { |

168 | + ARM_SimpleRate_M(input, |

169 | + &SimpleRate_readFudge, |

170 | + &sr, |

171 | + obuf, osamp, vol_l, vol_r); |

172 | + } else if (reverseStereo) { |

173 | + ARM_SimpleRate_R(input, |

174 | + &SimpleRate_readFudge, |

175 | + &sr, |

176 | + obuf, osamp, vol_l, vol_r); |

177 | + } else { |

178 | + ARM_SimpleRate_S(input, |

179 | + &SimpleRate_readFudge, |

180 | + &sr, |

181 | + obuf, osamp, vol_l, vol_r); |

182 | + } |

183 | + return (ST_SUCCESS); |

184 | +} |

185 | + |

186 | +/** |

187 | + * Audio rate converter based on simple linear Interpolation. |

188 | + * |

189 | + * The use of fractional increment allows us to use no buffer. It |

190 | + * avoid the problems at the end of the buffer we had with the old |

191 | + * method which stored a possibly big buffer of size |

192 | + * lcm(in_rate,out_rate). |

193 | + * |

194 | + * Limited to sampling frequency <= 65535 Hz. |

195 | + */ |

196 | + |

197 | +typedef struct { |

198 | + const st_sample_t *inPtr; |

199 | + int inLen; |

200 | + |

201 | + /** position of how far output is ahead of input */ |

202 | + /** Holds what would have been opos-ipos */ |

203 | + long opos; |

204 | + |

205 | + /** integer position increment in the output stream */ |

206 | + long opos_inc; |

207 | + |

208 | + /** current sample(s) in the input stream (left/right channel) */ |

209 | + st_sample_t icur[2]; |

210 | + /** last sample(s) in the input stream (left/right channel) */ |

211 | + st_sample_t ilast[2]; |

212 | + |

213 | + /** fractional position in the output stream */ |

214 | + long opos_frac; |

215 | + |

216 | + /** fractional position increment in the output stream */ |

217 | + long opos_inc_frac; |

218 | + |

219 | + st_sample_t inBuf[INTERMEDIATE_BUFFER_SIZE]; |

220 | +} LinearRateDetails; |

221 | + |

222 | +extern "C" void ARM_LinearRate_M(AudioStream &input, |

223 | + int (*fn)(Audio::AudioStream&,int16*,int), |

224 | + LinearRateDetails *lr, |

225 | + st_sample_t *obuf, |

226 | + st_size_t osamp, |

227 | + st_volume_t vol_l, |

228 | + st_volume_t vol_r); |

229 | + |

230 | +extern "C" void ARM_LinearRate_S(AudioStream &input, |

231 | + int (*fn)(Audio::AudioStream&,int16*,int), |

232 | + LinearRateDetails *lr, |

233 | + st_sample_t *obuf, |

234 | + st_size_t osamp, |

235 | + st_volume_t vol_l, |

236 | + st_volume_t vol_r); |

237 | + |

238 | +extern "C" void ARM_LinearRate_R(AudioStream &input, |

239 | + int (*fn)(Audio::AudioStream&,int16*,int), |

240 | + LinearRateDetails *lr, |

241 | + st_sample_t *obuf, |

242 | + st_size_t osamp, |

243 | + st_volume_t vol_l, |

244 | + st_volume_t vol_r); |

245 | + |

246 | +template<bool stereo, bool reverseStereo> |

247 | +class LinearRateConverter : public RateConverter { |

248 | +protected: |

249 | + LinearRateDetails lr; |

250 | + |

251 | +public: |

252 | + LinearRateConverter(st_rate_t inrate, st_rate_t outrate); |

253 | + int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r); |

254 | + int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) { |

255 | + return (ST_SUCCESS); |

256 | + } |

257 | +}; |

258 | + |

259 | + |

260 | +/* |

261 | + * Prepare processing. |

262 | + */ |

263 | +template<bool stereo, bool reverseStereo> |

264 | +LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate, st_rate_t outrate) { |

265 | + unsigned long incr; |

266 | + |

267 | + if (inrate == outrate) { |

268 | + error("Input and Output rates must be different to use rate effect"); |

269 | + } |

270 | + |

271 | + if (inrate >= 65536 || outrate >= 65536) { |

272 | + error("rate effect can only handle rates < 65536"); |

273 | + } |

274 | + |

275 | + lr.opos_frac = 0; |

276 | + lr.opos = 1; |

277 | + |

278 | + /* increment */ |

279 | + incr = (inrate << FRAC_BITS) / outrate; |

280 | + |

281 | + lr.opos_inc_frac = incr & ((1UL << FRAC_BITS) - 1); |

282 | + lr.opos_inc = incr >> FRAC_BITS; |

283 | + |

284 | + lr.ilast[0] = lr.ilast[1] = 0; |

285 | + lr.icur[0] = lr.icur[1] = 0; |

286 | + |

287 | + lr.inLen = 0; |

288 | +} |

289 | + |

290 | +/* |

291 | + * Processed signed long samples from ibuf to obuf. |

292 | + * Return number of samples processed. |

293 | + */ |

294 | +template<bool stereo, bool reverseStereo> |

295 | +int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) { |

296 | + |

297 | +#ifdef DEBUG_RATECONV |

298 | +fprintf(stderr, "Linear st=%d rev=%d\n", stereo, reverseStereo); |

299 | +fflush(stderr); |

300 | +#endif |

301 | + if (!stereo) { |

302 | + ARM_LinearRate_M(input, |

303 | + &SimpleRate_readFudge, |

304 | + &lr, |

305 | + obuf, osamp, vol_l, vol_r); |

306 | + } else if (reverseStereo) { |

307 | + ARM_LinearRate_R(input, |

308 | + &SimpleRate_readFudge, |

309 | + &lr, |

310 | + obuf, osamp, vol_l, vol_r); |

311 | + } else { |

312 | + ARM_LinearRate_S(input, |

313 | + &SimpleRate_readFudge, |

314 | + &lr, |

315 | + obuf, osamp, vol_l, vol_r); |

316 | + } |

317 | + return (ST_SUCCESS); |

318 | +} |

319 | + |

320 | + |

321 | +#pragma mark - |

322 | + |

323 | + |

324 | +/** |

325 | + * Simple audio rate converter for the case that the inrate equals the outrate. |

326 | + */ |

327 | +extern "C" void ARM_CopyRate_M(st_size_t len, |

328 | + st_sample_t *obuf, |

329 | + st_volume_t vol_l, |

330 | + st_volume_t vol_r, |

331 | + st_sample_t *_buffer); |

332 | + |

333 | +extern "C" void ARM_CopyRate_S(st_size_t len, |

334 | + st_sample_t *obuf, |

335 | + st_volume_t vol_l, |

336 | + st_volume_t vol_r, |

337 | + st_sample_t *_buffer); |

338 | + |

339 | +extern "C" void ARM_CopyRate_R(st_size_t len, |

340 | + st_sample_t *obuf, |

341 | + st_volume_t vol_l, |

342 | + st_volume_t vol_r, |

343 | + st_sample_t *_buffer); |

344 | + |

345 | + |

346 | +template<bool stereo, bool reverseStereo> |

347 | +class CopyRateConverter : public RateConverter { |

348 | + st_sample_t *_buffer; |

349 | + st_size_t _bufferSize; |

350 | +public: |

351 | + CopyRateConverter() : _buffer(0), _bufferSize(0) {} |

352 | + ~CopyRateConverter() { |

353 | + free(_buffer); |

354 | + } |

355 | + |

356 | + virtual int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) { |

357 | + assert(input.isStereo() == stereo); |

358 | + |

359 | +#ifdef DEBUG_RATECONV |

360 | +fprintf(stderr, "Copy st=%d rev=%d\n", stereo, reverseStereo); |

361 | +fflush(stderr); |

362 | +#endif |

363 | + st_sample_t *ptr; |

364 | + st_size_t len; |

365 | + |

366 | + if (stereo) |

367 | + osamp *= 2; |

368 | + |

369 | + // Reallocate temp buffer, if necessary |

370 | + if (osamp > _bufferSize) { |

371 | + free(_buffer); |

372 | + _buffer = (st_sample_t *)malloc(osamp * 2); |

373 | + _bufferSize = osamp; |

374 | + } |

375 | + |

376 | + // Read up to 'osamp' samples into our temporary buffer |

377 | + len = input.readBuffer(_buffer, osamp); |

378 | + if (len <= 0) |

379 | + return (ST_SUCCESS); |

380 | + |

381 | + // Mix the data into the output buffer |

382 | + if (stereo && reverseStereo) |

383 | + ARM_CopyRate_R(len, obuf, vol_l, vol_r, _buffer); |

384 | + else if (stereo) |

385 | + ARM_CopyRate_S(len, obuf, vol_l, vol_r, _buffer); |

386 | + else |

387 | + ARM_CopyRate_M(len, obuf, vol_l, vol_r, _buffer); |

388 | + |

389 | + return (ST_SUCCESS); |

390 | + } |

391 | + virtual int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) { |

392 | + return (ST_SUCCESS); |

393 | + } |

394 | +}; |

395 | + |

396 | + |

397 | +#pragma mark - |

398 | + |

399 | + |

400 | +/** |

401 | + * Create and return a RateConverter object for the specified input and output rates. |

402 | + */ |

403 | +RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) { |

404 | + if (inrate != outrate) { |

405 | + if ((inrate % outrate) == 0) { |

406 | + if (stereo) { |

407 | + if (reverseStereo) |

408 | + return new SimpleRateConverter<true, true>(inrate, outrate); |

409 | + else |

410 | + return new SimpleRateConverter<true, false>(inrate, outrate); |

411 | + } else |

412 | + return new SimpleRateConverter<false, false>(inrate, outrate); |

413 | + } else { |

414 | + if (stereo) { |

415 | + if (reverseStereo) |

416 | + return new LinearRateConverter<true, true>(inrate, outrate); |

417 | + else |

418 | + return new LinearRateConverter<true, false>(inrate, outrate); |

419 | + } else |

420 | + return new LinearRateConverter<false, false>(inrate, outrate); |

421 | + } |

422 | + } else { |

423 | + if (stereo) { |

424 | + if (reverseStereo) |

425 | + return new CopyRateConverter<true, true>(); |

426 | + else |

427 | + return new CopyRateConverter<true, false>(); |

428 | + } else |

429 | + return new CopyRateConverter<false, false>(); |

430 | + } |

431 | +} |

432 | + |

433 | +} // End of namespace Audio |

434 | |

435 | Property changes on: sound/rate_arm.cpp |

436 | ___________________________________________________________________ |

437 | Name: svn:executable |

438 | + * |

439 | |

440 | Index: sound/rate_arm_asm.s |

441 | =================================================================== |

442 | --- sound/rate_arm_asm.s (revision 0) |

443 | +++ sound/rate_arm_asm.s (revision 0) |

444 | @@ -0,0 +1,689 @@ |

445 | +@ ScummVM Scumm Interpreter |

446 | +@ Copyright (C) 2007 The ScummVM project |

447 | +@ |

448 | +@ This program is free software@ you can redistribute it and/or |

449 | +@ modify it under the terms of the GNU General Public License |

450 | +@ as published by the Free Software Foundation@ either version 2 |

451 | +@ of the License, or (at your option) any later version. |

452 | +@ |

453 | +@ This program is distributed in the hope that it will be useful, |

454 | +@ but WITHOUT ANY WARRANTY@ without even the implied warranty of |

455 | +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |

456 | +@ GNU General Public License for more details. |

457 | +@ |

458 | +@ You should have received a copy of the GNU General Public License |

459 | +@ along with this program@ if not, write to the Free Software |

460 | +@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |

461 | +@ |

462 | +@ $URL: $ |

463 | +@ $Id: $ |

464 | +@ |

465 | +@ @author Robin Watts (robin@wss.co.uk) |

466 | +@ |

467 | +@ This file, together with rate_arm.cpp, provides an ARM optimised version |

468 | +@ of rate.cpp. The algorithm is essentially the same as that within rate.cpp |

469 | +@ so to understand this file you should understand rate.cpp first. |

470 | + |

471 | + .text |

472 | + |

473 | + .global ARM_CopyRate_M |

474 | + .global ARM_CopyRate_S |

475 | + .global ARM_CopyRate_R |

476 | + .global ARM_SimpleRate_M |

477 | + .global ARM_SimpleRate_S |

478 | + .global ARM_SimpleRate_R |

479 | + .global ARM_LinearRate_M |

480 | + .global ARM_LinearRate_S |

481 | + .global ARM_LinearRate_R |

482 | + |

483 | +ARM_CopyRate_M: |

484 | + @ r0 = len |

485 | + @ r1 = obuf |

486 | + @ r2 = vol_l |

487 | + @ r3 = vol_r |

488 | + @ <> = ptr |

489 | + LDR r12,[r13] |

490 | + STMFD r13!,{r4-r7,r14} |

491 | + |

492 | + MOV r14,#0 @ r14= 0 |

493 | + ORR r2, r2, r2, LSL #8 @ r2 = vol_l as 16 bits |

494 | + ORR r3, r3, r3, LSL #8 @ r3 = vol_r as 16 bits |

495 | +CopyRate_M_loop: |

496 | + LDRSH r5, [r12], #2 @ r5 = tmp0 = tmp1 = *ptr++ |

497 | + LDRSH r6, [r1] @ r6 = obuf[0] |

498 | + LDRSH r7, [r1, #2] @ r7 = obuf[1] |

499 | + MUL r4, r2, r5 @ r4 = tmp0*vol_l |

500 | + MUL r5, r3, r5 @ r5 = tmp1*vol_r |

501 | + |

502 | + ADDS r6, r4, r6, LSL #16 @ r6 = obuf[0]<<16 + tmp0*vol_l |

503 | + RSCVS r6, r14,#1<<31 @ Clamp r6 |

504 | + ADDS r7, r5, r7, LSL #16 @ r7 = obuf[1]<<16 + tmp1*vol_r |

505 | + RSCVS r7, r14,#1<<31 @ Clamp r7 |

506 | + |

507 | + MOV r6, r6, LSR #16 @ Shift back to halfword |

508 | + MOV r7, r7, LSR #16 @ Shift back to halfword |

509 | + |

510 | + STRH r6, [r1], #2 @ Store output value |

511 | + STRH r7, [r1], #2 @ Store output value |

512 | + |

513 | + SUBS r0,r0,#1 @ len-- |

514 | + BGT CopyRate_M_loop @ and loop |

515 | + |

516 | + LDMFD r13!,{r4-r7,PC} |

517 | + |

518 | +ARM_CopyRate_S: |

519 | + @ r0 = len |

520 | + @ r1 = obuf |

521 | + @ r2 = vol_l |

522 | + @ r3 = vol_r |

523 | + @ <> = ptr |

524 | + LDR r12,[r13] |

525 | + STMFD r13!,{r4-r7,r14} |

526 | + |

527 | + MOV r14,#0 @ r14= 0 |

528 | + ORR r2, r2, r2, LSL #8 @ r2 = vol_l as 16 bits |

529 | + ORR r3, r3, r3, LSL #8 @ r3 = vol_r as 16 bits |

530 | +CopyRate_S_loop: |

531 | + LDRSH r4, [r12],#2 @ r4 = tmp0 = *ptr++ |

532 | + LDRSH r5, [r12],#2 @ r5 = tmp1 = *ptr++ |

533 | + LDRSH r6, [r1] @ r6 = obuf[0] |

534 | + LDRSH r7, [r1,#2] @ r7 = obuf[1] |

535 | + MUL r4, r2, r4 @ r5 = tmp0*vol_l |

536 | + MUL r5, r3, r5 @ r6 = tmp1*vol_r |

537 | + |

538 | + ADDS r6, r4, r6, LSL #16 @ r6 = obuf[0]<<16 + tmp0*vol_l |

539 | + RSCVS r6, r14,#1<<31 @ Clamp r6 |

540 | + ADDS r7, r5, r7, LSL #16 @ r7 = obuf[1]<<16 + tmp1*vol_r |

541 | + RSCVS r7, r14,#1<<31 @ Clamp r7 |

542 | + |

543 | + MOV r6, r6, LSR #16 @ Shift back to halfword |

544 | + MOV r7, r7, LSR #16 @ Shift back to halfword |

545 | + |

546 | + STRH r6, [r1],#2 @ Store output value |

547 | + STRH r7, [r1],#2 @ Store output value |

548 | + |

549 | + SUBS r0,r0,#2 @ len -= 2 |

550 | + BGT CopyRate_S_loop @ and loop |

551 | + |

552 | + LDMFD r13!,{r4-r7,PC} |

553 | + |

554 | +ARM_CopyRate_R: |

555 | + @ r0 = len |

556 | + @ r1 = obuf |

557 | + @ r2 = vol_l |

558 | + @ r3 = vol_r |

559 | + @ <> = ptr |

560 | + LDR r12,[r13] |

561 | + STMFD r13!,{r4-r7,r14} |

562 | + |

563 | + MOV r14,#0 @ r14= 0 |

564 | + ORR r2, r2, r2, LSL #8 @ r2 = vol_l as 16 bits |

565 | + ORR r3, r3, r3, LSL #8 @ r3 = vol_r as 16 bits |

566 | +CopyRate_R_loop: |

567 | + LDRSH r5, [r12],#2 @ r5 = tmp1 = *ptr++ |

568 | + LDRSH r4, [r12],#2 @ r4 = tmp0 = *ptr++ |

569 | + LDRSH r6, [r1] @ r6 = obuf[0] |

570 | + LDRSH r7, [r1,#2] @ r7 = obuf[1] |

571 | + MUL r4, r2, r4 @ r4 = tmp0*vol_l |

572 | + MUL r5, r3, r5 @ r5 = tmp1*vol_r |

573 | + |

574 | + ADDS r6, r4, r6, LSL #16 @ r6 = obuf[0]<<16 + tmp0*vol_l |

575 | + RSCVS r6, r14,#1<<31 @ Clamp r6 |

576 | + ADDS r7, r5, r7, LSL #16 @ r7 = obuf[1]<<16 + tmp1*vol_r |

577 | + RSCVS r7, r14,#1<<31 @ Clamp r7 |

578 | + |

579 | + MOV r6, r6, LSR #16 @ Shift back to halfword |

580 | + MOV r7, r7, LSR #16 @ Shift back to halfword |

581 | + |

582 | + STRH r6, [r1],#2 @ Store output value |

583 | + STRH r7, [r1],#2 @ Store output value |

584 | + |

585 | + SUBS r0,r0,#2 @ len -= 2 |

586 | + BGT CopyRate_R_loop @ and loop |

587 | + |

588 | + LDMFD r13!,{r4-r7,PC} |

589 | + |

590 | +ARM_SimpleRate_M: |

591 | + @ r0 = AudioStream &input |

592 | + @ r1 = input.readBuffer |

593 | + @ r2 = input->sr |

594 | + @ r3 = obuf |

595 | + @ <> = osamp |

596 | + @ <> = vol_l |

597 | + @ <> = vol_r |

598 | + MOV r12,r13 |

599 | + STMFD r13!,{r0-r2,r4-r8,r10-r11,r14} |

600 | + LDMFD r12,{r11,r12,r14} @ r11= osamp |

601 | + @ r12= vol_l |

602 | + @ r14= vol_r |

603 | + LDMIA r2,{r0,r1,r2,r8} @ r0 = inPtr |

604 | + @ r1 = inLen |

605 | + @ r2 = opos |

606 | + @ r8 = opos_inc |

607 | + CMP r11,#0 @ if (osamp <= 0) |

608 | + BLE SimpleRate_M_end @ bale |

609 | + MOV r10,#0 |

610 | + ORR r12,r12,r12,LSL #8 @ r12= vol_l as 16 bits |

611 | + ORR r14,r14,r14,LSL #8 @ r14= vol_r as 16 bits |

612 | +SimpleRate_M_loop: |

613 | + SUBS r1, r1, #1 @ r1 = inLen -= 1 |

614 | + BLT SimpleRate_M_read |

615 | + SUBS r2, r2, #1 @ r2 = opos-- |

616 | + ADDGE r0, r0, #2 @ if (r2 >= 0) { sr.inPtr++ |

617 | + BGE SimpleRate_M_loop @ and loop } |

618 | +SimpleRate_M_read_return: |

619 | + LDRSH r5, [r0],#2 @ r5 = tmp1 = *inPtr++ |

620 | + LDRSH r6, [r3] @ r6 = obuf[0] |

621 | + LDRSH r7, [r3,#2] @ r7 = obuf[1] |

622 | + ADD r2, r2, r8 @ r2 = opos += opos_inc |

623 | + MUL r4, r12,r5 @ r4 = tmp0*vol_l |

624 | + MUL r5, r14,r5 @ r5 = tmp1*vol_r |

625 | + |

626 | + ADDS r6, r4, r6, LSL #16 @ r6 = obuf[0]<<16 + tmp0*vol_l |

627 | + RSCVS r6, r10,#1<<31 @ Clamp r6 |

628 | + ADDS r7, r5, r7, LSL #16 @ r7 = obuf[1]<<16 + tmp1*vol_r |

629 | + RSCVS r7, r10,#1<<31 @ Clamp r7 |

630 | + |

631 | + MOV r6, r6, LSR #16 @ Shift back to halfword |

632 | + MOV r7, r7, LSR #16 @ Shift back to halfword |

633 | + |

634 | + STRH r6, [r3],#2 @ Store output value |

635 | + STRH r7, [r3],#2 @ Store output value |

636 | + |

637 | + SUBS r11,r11,#1 @ len-- |

638 | + BGT SimpleRate_M_loop @ and loop |

639 | +SimpleRate_M_end: |

640 | + LDR r14,[r13,#8] @ r14 = sr |

641 | + ADD r13,r13,#12 @ Skip over r0-r2 on stack |

642 | + STMIA r14,{r0,r1,r2} @ Store back updated values |

643 | + LDMFD r13!,{r4-r8,r10-r11,PC} |

644 | +SimpleRate_M_read: |

645 | + LDR r0, [r13,#4*2] @ r0 = sr |

646 | + ADD r0, r0, #16 @ r0 = inPtr = inBuf |

647 | + STMFD r13!,{r0,r2-r3,r12,r14} |

648 | + |

649 | + MOV r1, r0 @ r1 = inBuf |

650 | + LDR r0, [r13,#4*5] @ r0 = AudioStream & input |

651 | + MOV r2, #512 @ r2 = ARRAYSIZE(inBuf) |

652 | + |

653 | + @ Calling back into C++ here. WinCE is fairly easy about such things |

654 | + @ but other OS are more awkward. r9 is preserved for Symbian, and |

655 | + @ we have 3+8+5 = 16 things on the stack (an even number). |

656 | + MOV r14,PC |

657 | + LDR PC,[r13,#4*6] @ inLen = input.readBuffer(inBuf,512) |

658 | + SUBS r1, r0, #1 @ r1 = inLen-1 |

659 | + LDMFD r13!,{r0,r2-r3,r12,r14} |

660 | + BLT SimpleRate_M_end |

661 | + SUBS r2, r2, #1 @ r2 = opos-- |

662 | + ADDGE r0, r0, #2 @ if (r2 >= 0) { sr.inPtr++ |

663 | + BGE SimpleRate_M_loop @ and loop } |

664 | + B SimpleRate_M_read_return |

665 | + |

666 | + |

667 | +ARM_SimpleRate_S: |

668 | + @ r0 = AudioStream &input |

669 | + @ r1 = input.readBuffer |

670 | + @ r2 = input->sr |

671 | + @ r3 = obuf |

672 | + @ <> = osamp |

673 | + @ <> = vol_l |

674 | + @ <> = vol_r |

675 | + MOV r12,r13 |

676 | + STMFD r13!,{r0-r2,r4-r8,r10-r11,r14} |

677 | + LDMFD r12,{r11,r12,r14} @ r11= osamp |

678 | + @ r12= vol_l |

679 | + @ r14= vol_r |

680 | + LDMIA r2,{r0,r1,r2,r8} @ r0 = inPtr |

681 | + @ r1 = inLen |

682 | + @ r2 = opos |

683 | + @ r8 = opos_inc |

684 | + CMP r11,#0 @ if (osamp <= 0) |

685 | + BLE SimpleRate_S_end @ bale |

686 | + MOV r10,#0 |

687 | + ORR r12,r12,r12,LSL #8 @ r12= vol_l as 16 bits |

688 | + ORR r14,r14,r14,LSL #8 @ r14= vol_r as 16 bits |

689 | +SimpleRate_S_loop: |

690 | + SUBS r1, r1, #2 @ r1 = inLen -= 2 |

691 | + BLT SimpleRate_S_read |

692 | + SUBS r2, r2, #1 @ r2 = opos-- |

693 | + ADDGE r0, r0, #4 @ if (r2 >= 0) { sr.inPtr += 2 |

694 | + BGE SimpleRate_S_loop @ and loop } |

695 | +SimpleRate_S_read_return: |

696 | + LDRSH r4, [r0],#2 @ r4 = tmp0 = *inPtr++ |

697 | + LDRSH r5, [r0],#2 @ r5 = tmp1 = *inPtr++ |

698 | + LDRSH r6, [r3] @ r6 = obuf[0] |

699 | + LDRSH r7, [r3,#2] @ r7 = obuf[1] |

700 | + ADD r2, r2, r8 @ r2 = opos += opos_inc |

701 | + MUL r4, r12,r4 @ r5 = tmp0*vol_l |

702 | + MUL r5, r14,r5 @ r6 = tmp1*vol_r |

703 | + |

704 | + ADDS r6, r4, r6, LSL #16 @ r6 = obuf[0]<<16 + tmp0*vol_l |

705 | + RSCVS r6, r10,#1<<31 @ Clamp r6 |

706 | + ADDS r7, r5, r7, LSL #16 @ r7 = obuf[1]<<16 + tmp1*vol_r |

707 | + RSCVS r7, r10,#1<<31 @ Clamp r7 |

708 | + |

709 | + MOV r6, r6, LSR #16 @ Shift back to halfword |

710 | + MOV r7, r7, LSR #16 @ Shift back to halfword |

711 | + |

712 | + STRH r6, [r3],#2 @ Store output value |

713 | + STRH r7, [r3],#2 @ Store output value |

714 | + |

715 | + SUBS r11,r11,#1 @ osamp-- |

716 | + BGT SimpleRate_S_loop @ and loop |

717 | +SimpleRate_S_end: |

718 | + LDR r14,[r13,#8] @ r14 = sr |

719 | + ADD r13,r13,#12 @ skip over r0-r2 on stack |

720 | + STMIA r14,{r0,r1,r2} @ store back updated values |

721 | + LDMFD r13!,{r4-r8,r10-r11,PC} |

722 | +SimpleRate_S_read: |

723 | + LDR r0, [r13,#4*2] @ r0 = sr |

724 | + ADD r0, r0, #16 @ r0 = inPtr = inBuf |

725 | + STMFD r13!,{r0,r2-r3,r12,r14} |

726 | + |

727 | + MOV r1, r0 @ r1 = inBuf |

728 | + LDR r0, [r13,#4*5] @ r0 = AudioStream & input |

729 | + MOV r2, #512 @ r2 = ARRAYSIZE(inBuf) |

730 | + |

731 | + @ Calling back into C++ here. WinCE is fairly easy about such things |

732 | + @ but other OS are more awkward. r9 is preserved for Symbian, and |

733 | + @ we have 3+8+5 = 16 things on the stack (an even number). |

734 | + MOV r14,PC |

735 | + LDR PC,[r13,#4*6] @ inLen = input.readBuffer(inBuf,512) |

736 | + SUBS r1, r0, #2 @ r1 = inLen-2 |

737 | + LDMFD r13!,{r0,r2-r3,r12,r14} |

738 | + BLT SimpleRate_S_end |

739 | + SUBS r2, r2, #1 @ r2 = opos-- |

740 | + ADDGE r0, r0, #4 @ if (r2 >= 0) { sr.inPtr += 2 |

741 | + BGE SimpleRate_S_loop @ and loop } |

742 | + B SimpleRate_S_read_return |

743 | + |

744 | + |

745 | + |

746 | +ARM_SimpleRate_R: |

747 | + @ r0 = AudioStream &input |

748 | + @ r1 = input.readBuffer |

749 | + @ r2 = input->sr |

750 | + @ r3 = obuf |

751 | + @ <> = osamp |

752 | + @ <> = vol_l |

753 | + @ <> = vol_r |

754 | + MOV r12,r13 |

755 | + STMFD r13!,{r0-r2,r4-r8,r10-r11,r14} |

756 | + LDMFD r12,{r11,r12,r14} @ r11= osamp |

757 | + @ r12= vol_l |

758 | + @ r14= vol_r |

759 | + LDMIA r2,{r0,r1,r2,r8} @ r0 = inPtr |

760 | + @ r1 = inLen |

761 | + @ r2 = opos |

762 | + @ r8 = opos_inc |

763 | + CMP r11,#0 @ if (osamp <= 0) |

764 | + BLE SimpleRate_R_end @ bale |

765 | + MOV r10,#0 |

766 | + ORR r12,r12,r12,LSL #8 @ r12= vol_l as 16 bits |

767 | + ORR r14,r14,r14,LSL #8 @ r14= vol_r as 16 bits |

768 | +SimpleRate_R_loop: |

769 | + SUBS r1, r1, #2 @ r1 = inLen -= 2 |

770 | + BLT SimpleRate_R_read |

771 | + SUBS r2, r2, #1 @ r2 = opos-- |

772 | + ADDGE r0, r0, #4 @ if (r2 >= 0) { sr.inPtr += 2 |

773 | + BGE SimpleRate_R_loop @ and loop } |

774 | +SimpleRate_R_read_return: |

775 | + LDRSH r5, [r0],#2 @ r5 = tmp0 = *inPtr++ |

776 | + LDRSH r4, [r0],#2 @ r4 = tmp1 = *inPtr++ |

777 | + LDRSH r6, [r3] @ r6 = obuf[0] |

778 | + LDRSH r7, [r3,#2] @ r7 = obuf[1] |

779 | + ADD r2, r2, r8 @ r2 = opos += opos_inc |

780 | + MUL r4, r12,r4 @ r5 = tmp0*vol_l |

781 | + MUL r5, r14,r5 @ r6 = tmp1*vol_r |

782 | + |

783 | + ADDS r6, r4, r6, LSL #16 @ r6 = obuf[0]<<16 + tmp0*vol_l |

784 | + RSCVS r6, r10,#1<<31 @ Clamp r6 |

785 | + ADDS r7, r5, r7, LSL #16 @ r7 = obuf[1]<<16 + tmp1*vol_r |

786 | + RSCVS r7, r10,#1<<31 @ Clamp r7 |

787 | + |

788 | + MOV r6, r6, LSR #16 @ Shift back to halfword |

789 | + MOV r7, r7, LSR #16 @ Shift back to halfword |

790 | + |

791 | + STRH r6, [r3],#2 @ Store output value |

792 | + STRH r7, [r3],#2 @ Store output value |

793 | + |

794 | + SUBS r11,r11,#1 @ osamp-- |

795 | + BGT SimpleRate_R_loop @ and loop |

796 | +SimpleRate_R_end: |

797 | + LDR r14,[r13,#8] @ r14 = sr |

798 | + ADD r13,r13,#12 @ Skip over r0-r2 on stack |

799 | + STMIA r14,{r0,r1,r2} @ Store back updated values |

800 | + LDMFD r13!,{r4-r8,r10-r11,PC} |

801 | +SimpleRate_R_read: |

802 | + LDR r0, [r13,#4*2] @ r0 = sr |

803 | + ADD r0, r0, #16 @ r0 = inPtr = inBuf |

804 | + STMFD r13!,{r0,r2-r3,r12,r14} |

805 | + |

806 | + MOV r1, r0 @ r1 = inBuf |

807 | + LDR r0, [r13,#4*5] @ r0 = AudioStream & input |

808 | + MOV r2, #512 @ r2 = ARRAYSIZE(inBuf) |

809 | + |

810 | + @ Calling back into C++ here. WinCE is fairly easy about such things |

811 | + @ but other OS are more awkward. r9 is preserved for Symbian, and |

812 | + @ we have 3+8+5 = 16 things on the stack (an even number). |

813 | + MOV r14,PC |

814 | + LDR PC,[r13,#4*6] @ inLen = input.readBuffer(inBuf,512) |

815 | + SUBS r1, r0, #2 @ r1 = inLen-2 |

816 | + LDMFD r13!,{r0,r2-r3,r12,r14} |

817 | + BLT SimpleRate_R_end |

818 | + SUBS r2, r2, #1 @ r2 = opos-- |

819 | + ADDGE r0, r0, #4 @ if (r2 >= 0) { sr.inPtr += 2 |

820 | + BGE SimpleRate_R_loop @ and loop } |

821 | + B SimpleRate_R_read_return |

822 | + |

823 | + |

824 | +ARM_LinearRate_M: |

825 | + @ r0 = AudioStream &input |

826 | + @ r1 = input.readBuffer |

827 | + @ r2 = input->sr |

828 | + @ r3 = obuf |

829 | + @ <> = osamp |

830 | + @ <> = vol_l |

831 | + @ <> = vol_r |

832 | + MOV r12,r13 |

833 | + STMFD r13!,{r0-r1,r4-r11,r14} |

834 | + LDMFD r12,{r11,r12,r14} @ r11= osamp |

835 | + @ r12= vol_l |

836 | + @ r14= vol_r |

837 | + LDMIA r2,{r0,r1,r8} @ r0 = inPtr |

838 | + @ r1 = inLen |

839 | + @ r8 = opos |

840 | + CMP r11,#0 @ if (osamp <= 0) |

841 | + BLE LinearRate_M_end @ bale |

842 | + ORR r12,r12,r12,LSL #8 @ r12= vol_l as 16 bits |

843 | + ORR r14,r14,r14,LSL #8 @ r14= vol_r as 16 bits |

844 | + CMP r1,#0 |

845 | + BGT LinearRate_M_part2 |

846 | + |

847 | + @ part1 - read input samples |

848 | +LinearRate_M_loop: |

849 | + SUBS r1, r1, #1 @ r1 = inLen -= 1 |

850 | + BLT LinearRate_M_read |

851 | +LinearRate_M_read_return: |

852 | + LDR r10,[r2, #16] @ r10= icur[0,1] |

853 | + LDRSH r5, [r0],#2 @ r5 = tmp1 = *inPtr++ |

854 | + SUBS r8, r8, #1 @ r8 = opos-- |

855 | + STR r10,[r2,#20] @ ilast[0,1] = icur[0,1] |

856 | + STRH r5, [r2,#16] @ icur[0] = tmp1 |

857 | + BGE LinearRate_M_loop |

858 | + |

859 | + @ part2 - form output samples |

860 | +LinearRate_M_part2: |

861 | + @ We are guaranteed that opos < 0 here |

862 | + LDRSH r6, [r2,#20] @ r6 = ilast[0] |

863 | + LDRSH r5, [r2,#16] @ r5 = icur[0] |

864 | + LDRH r4, [r2,#24] @ r4 = opos_frac |

865 | + LDR r10,[r2,#28] @ r10= opos_frac_inc |

866 | + MOV r6, r6, LSL #16 @ r6 = ilast[0]<<16 |

867 | + SUB r5, r5, r6, ASR #16 @ r5 = icur[0] - ilast[0] |

868 | + ADD r6, r6, #1<<15 @ r6 = ilast[0]+1<<(FRAC_BITS-1) |

869 | + MLA r6, r4, r5, r6 @ r6 = (icur[0]-ilast[0])*opos_frac+ilast[0] |

870 | + |

871 | + ADD r4, r4, r10 @ r4 = tmp = opos_frac+opos_inc_frac |

872 | + STRH r4,[r2,#24] @ opos_frac &= 65535 |

873 | + ADD r8, r8, r4, LSR #16 @ opos += (tmp>>FRAC_BITS) |

874 | + |

875 | + LDRSH r4, [r3] @ r4 = obuf[0] |

876 | + LDRSH r5, [r3,#2] @ r5 = obuf[1] |

877 | + MOV r6, r6, ASR #16 @ r6 = tmp0 = tmp1 >>= 16 |

878 | + MUL r7, r12,r6 @ r7 = tmp0*vol_l |

879 | + MUL r6, r14,r6 @ r6 = tmp1*vol_r |

880 | + |

881 | + ADDS r7, r7, r4, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l |

882 | + MOV r4, #0 |

883 | + RSCVS r7, r4, #1<<31 @ Clamp r7 |

884 | + ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r |

885 | + RSCVS r6, r4, #1<<31 @ Clamp r6 |

886 | + |

887 | + MOV r7, r7, LSR #16 @ Shift back to halfword |

888 | + MOV r6, r6, LSR #16 @ Shift back to halfword |

889 | + |

890 | + LDR r5, [r2,#12] @ r5 = opos_inc |

891 | + STRH r7, [r3],#2 @ Store output value |

892 | + STRH r6, [r3],#2 @ Store output value |

893 | + SUBS r11, r11,#1 @ opos-- |

894 | + BLE LinearRate_M_end @ end if needed |

895 | + |

896 | + ADDS r8, r8, r5 @ r8 = opos += opos_inc |

897 | + BLT LinearRate_M_part2 |

898 | + B LinearRate_M_loop |

899 | +LinearRate_M_end: |

900 | + ADD r13,r13,#8 |

901 | + STMIA r2,{r0,r1,r8} |

902 | + LDMFD r13!,{r4-r11,PC} |

903 | +LinearRate_M_read: |

904 | + ADD r0, r2, #32 @ r0 = inPtr = inBuf |

905 | + STMFD r13!,{r0,r2-r3,r12,r14} |

906 | + |

907 | + MOV r1, r0 @ r1 = inBuf |

908 | + LDR r0, [r13,#4*5] @ r0 = AudioStream & input |

909 | + MOV r2, #512 @ r2 = ARRAYSIZE(inBuf) |

910 | + |

911 | + @ Calling back into C++ here. WinCE is fairly easy about such things |

912 | + @ but other OS are more awkward. r9 is preserved for Symbian, and |

913 | + @ we have 2+9+5 = 16 things on the stack (an even number). |

914 | + MOV r14,PC |

915 | + LDR PC,[r13,#4*6] @ inLen = input.readBuffer(inBuf,512) |

916 | + SUBS r1, r0, #1 @ r1 = inLen-1 |

917 | + LDMFD r13!,{r0,r2-r3,r12,r14} |

918 | + BLT LinearRate_M_end |

919 | + B LinearRate_M_read_return |

920 | + |

921 | +ARM_LinearRate_S: |

922 | + @ r0 = AudioStream &input |

923 | + @ r1 = input.readBuffer |

924 | + @ r2 = input->sr |

925 | + @ r3 = obuf |

926 | + @ <> = osamp |

927 | + @ <> = vol_l |

928 | + @ <> = vol_r |

929 | + MOV r12,r13 |

930 | + STMFD r13!,{r0-r1,r4-r11,r14} |

931 | + LDMFD r12,{r11,r12,r14} @ r11= osamp |

932 | + @ r12= vol_l |

933 | + @ r14= vol_r |

934 | + LDMIA r2,{r0,r1,r8} @ r0 = inPtr |

935 | + @ r1 = inLen |

936 | + @ r8 = opos |

937 | + CMP r11,#0 @ if (osamp <= 0) |

938 | + BLE LinearRate_S_end @ bale |

939 | + ORR r12,r12,r12,LSL #8 @ r12= vol_l as 16 bits |

940 | + ORR r14,r14,r14,LSL #8 @ r14= vol_r as 16 bits |

941 | + CMP r1,#0 |

942 | + BGT LinearRate_S_part2 |

943 | + |

944 | + @ part1 - read input samples |

945 | +LinearRate_S_loop: |

946 | + SUBS r1, r1, #2 @ r1 = inLen -= 2 |

947 | + BLT LinearRate_S_read |

948 | +LinearRate_S_read_return: |

949 | + LDR r10,[r2, #16] @ r10= icur[0,1] |

950 | + LDRSH r5, [r0],#2 @ r5 = tmp0 = *inPtr++ |

951 | + LDRSH r6, [r0],#2 @ r5 = tmp1 = *inPtr++ |

952 | + SUBS r8, r8, #1 @ r8 = opos-- |

953 | + STR r10,[r2,#20] @ ilast[0,1] = icur[0,1] |

954 | + STRH r5, [r2,#16] @ icur[0] = tmp0 |

955 | + STRH r6, [r2,#16] @ icur[1] = tmp1 |

956 | + BGE LinearRate_S_loop |

957 | + |

958 | + @ part2 - form output samples |

959 | +LinearRate_S_part2: |

960 | + @ We are guaranteed that opos < 0 here |

961 | + LDRSH r6, [r2,#20] @ r6 = ilast[0] |

962 | + LDRSH r5, [r2,#16] @ r5 = icur[0] |

963 | + LDRH r4, [r2,#24] @ r4 = opos_frac |

964 | + MOV r6, r6, LSL #16 @ r6 = ilast[0]<<16 |

965 | + SUB r5, r5, r6, ASR #16 @ r5 = icur[0] - ilast[0] |

966 | + ADD r6, r6, #1<<15 @ r6 = ilast[0]+1<<(FRAC_BITS-1) |

967 | + MLA r6, r4, r5, r6 @ r6 = (icur[0]-ilast[0])*opos_frac+ilast[0] |

968 | + |

969 | + LDRSH r7, [r2,#22] @ r6 = ilast[1] |

970 | + LDRSH r5, [r2,#18] @ r5 = icur[1] |

971 | + LDR r10,[r2,#28] @ r10= opos_frac_inc |

972 | + MOV r7, r7, LSL #16 @ r7 = ilast[1]<<16 |

973 | + SUB r5, r5, r7, ASR #16 @ r5 = icur[1] - ilast[1] |

974 | + ADD r7, r7, #1<<15 @ r6 = ilast[1]+1<<(FRAC_BITS-1) |

975 | + MLA r7, r4, r5, r7 @ r6 = (icur[1]-ilast[1])*opos_frac+ilast[1] |

976 | + |

977 | + ADD r4, r4, r10 @ r4 = tmp = opos_frac+opos_inc_frac |

978 | + STRH r4,[r2,#24] @ opos_frac &= 65535 |

979 | + ADD r8, r8, r4, LSR #16 @ opos += (tmp>>FRAC_BITS) |

980 | + |

981 | + LDRSH r4, [r3] @ r4 = obuf[0] |

982 | + LDRSH r5, [r3,#2] @ r5 = obuf[1] |

983 | + MOV r7, r7, ASR #16 @ r7 = tmp0 >>= 16 |

984 | + MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16 |

985 | + MUL r7, r12,r7 @ r7 = tmp0*vol_l |

986 | + MUL r6, r14,r6 @ r6 = tmp1*vol_r |

987 | + |

988 | + ADDS r7, r7, r4, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l |

989 | + MOV r4, #0 |

990 | + RSCVS r7, r4, #1<<31 @ Clamp r7 |

991 | + ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r |

992 | + RSCVS r6, r4, #1<<31 @ Clamp r6 |

993 | + |

994 | + MOV r7, r7, LSR #16 @ Shift back to halfword |

995 | + MOV r6, r6, LSR #16 @ Shift back to halfword |

996 | + |

997 | + LDR r5, [r2,#12] @ r5 = opos_inc |

998 | + STRH r7, [r3],#2 @ Store output value |

999 | + STRH r6, [r3],#2 @ Store output value |

1000 | + SUBS r11, r11,#1 @ opos-- |

1001 | + BLE LinearRate_S_end @ and loop |

1002 | + |

1003 | + ADDS r8, r8, r5 @ r8 = opos += opos_inc |

1004 | + BLT LinearRate_S_part2 |

1005 | + B LinearRate_S_loop |

1006 | +LinearRate_S_end: |

1007 | + ADD r13,r13,#8 |

1008 | + STMIA r2,{r0,r1,r8} |

1009 | + LDMFD r13!,{r4-r11,PC} |

1010 | +LinearRate_S_read: |

1011 | + ADD r0, r2, #32 @ r0 = inPtr = inBuf |

1012 | + STMFD r13!,{r0,r2-r3,r12,r14} |

1013 | + |

1014 | + MOV r1, r0 @ r1 = inBuf |

1015 | + LDR r0, [r13,#4*5] @ r0 = AudioStream & input |

1016 | + MOV r2, #512 @ r2 = ARRAYSIZE(inBuf) |

1017 | + |

1018 | + @ Calling back into C++ here. WinCE is fairly easy about such things |

1019 | + @ but other OS are more awkward. r9 is preserved for Symbian, and |

1020 | + @ we have 2+9+5 = 16 things on the stack (an even number). |

1021 | + MOV r14,PC |

1022 | + LDR PC,[r13,#4*6] @ inLen = input.readBuffer(inBuf,512) |

1023 | + SUBS r1, r0, #2 @ r1 = inLen-2 |

1024 | + LDMFD r13!,{r0,r2-r3,r12,r14} |

1025 | + BLT LinearRate_S_end |

1026 | + B LinearRate_S_read_return |

1027 | + |

1028 | +ARM_LinearRate_R: |

1029 | + @ r0 = AudioStream &input |

1030 | + @ r1 = input.readBuffer |

1031 | + @ r2 = input->sr |

1032 | + @ r3 = obuf |

1033 | + @ <> = osamp |

1034 | + @ <> = vol_l |

1035 | + @ <> = vol_r |

1036 | + MOV r12,r13 |

1037 | + STMFD r13!,{r0-r1,r4-r11,r14} |

1038 | + LDMFD r12,{r11,r12,r14} @ r11= osamp |

1039 | + @ r12= vol_l |

1040 | + @ r14= vol_r |

1041 | + LDMIA r2,{r0,r1,r8} @ r0 = inPtr |

1042 | + @ r1 = inLen |

1043 | + @ r8 = opos |

1044 | + CMP r11,#0 @ if (osamp <= 0) |

1045 | + BLE LinearRate_R_end @ bale |

1046 | + ORR r12,r12,r12,LSL #8 @ r12= vol_l as 16 bits |

1047 | + ORR r14,r14,r14,LSL #8 @ r14= vol_r as 16 bits |

1048 | + CMP r1,#0 |

1049 | + BGT LinearRate_R_part2 |

1050 | + |

1051 | + @ part1 - read input samples |

1052 | +LinearRate_R_loop: |

1053 | + SUBS r1, r1, #2 @ r1 = inLen -= 2 |

1054 | + BLT LinearRate_R_read |

1055 | +LinearRate_R_read_return: |

1056 | + LDR r10,[r2, #16] @ r10= icur[0,1] |

1057 | + LDRSH r5, [r0],#2 @ r5 = tmp0 = *inPtr++ |

1058 | + LDRSH r6, [r0],#2 @ r5 = tmp1 = *inPtr++ |

1059 | + SUBS r8, r8, #1 @ r8 = opos-- |

1060 | + STR r10,[r2,#20] @ ilast[0,1] = icur[0,1] |

1061 | + STRH r5, [r2,#16] @ icur[0] = tmp0 |

1062 | + STRH r6, [r2,#16] @ icur[1] = tmp1 |

1063 | + BGE LinearRate_R_loop |

1064 | + |

1065 | + @ part2 - form output samples |

1066 | +LinearRate_R_part2: |

1067 | + @ We are guaranteed that opos < 0 here |

1068 | + LDRSH r6, [r2,#20] @ r6 = ilast[0] |

1069 | + LDRSH r5, [r2,#16] @ r5 = icur[0] |

1070 | + LDRH r4, [r2,#24] @ r4 = opos_frac |

1071 | + MOV r6, r6, LSL #16 @ r6 = ilast[0]<<16 |

1072 | + SUB r5, r5, r6, ASR #16 @ r5 = icur[0] - ilast[0] |

1073 | + ADD r6, r6, #1<<15 @ r6 = ilast[0]+1<<(FRAC_BITS-1) |

1074 | + MLA r6, r4, r5, r6 @ r6 = (icur[0]-ilast[0])*opos_frac+ilast[0] |

1075 | + |

1076 | + LDRSH r7, [r2,#22] @ r6 = ilast[1] |

1077 | + LDRSH r5, [r2,#18] @ r5 = icur[1] |

1078 | + LDR r10,[r2,#28] @ r10= opos_frac_inc |

1079 | + MOV r7, r7, LSL #16 @ r7 = ilast[1]<<16 |

1080 | + SUB r5, r5, r7, ASR #16 @ r5 = icur[1] - ilast[1] |

1081 | + ADD r7, r7, #1<<15 @ r6 = ilast[1]+1<<(FRAC_BITS-1) |

1082 | + MLA r7, r4, r5, r7 @ r6 = (icur[1]-ilast[1])*opos_frac+ilast[1] |

1083 | + |

1084 | + ADD r4, r4, r10 @ r4 = tmp = opos_frac+opos_inc_frac |

1085 | + STRH r4,[r2,#24] @ opos_frac &= 65535 |

1086 | + ADD r8, r8, r4, LSR #16 @ opos += (tmp>>FRAC_BITS) |

1087 | + |

1088 | + LDRSH r4, [r3] @ r4 = obuf[0] |

1089 | + LDRSH r5, [r3,#2] @ r5 = obuf[1] |

1090 | + MOV r7, r7, ASR #16 @ r7 = tmp0 >>= 16 |

1091 | + MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16 |

1092 | + MUL r7, r12,r7 @ r7 = tmp0*vol_l |

1093 | + MUL r6, r14,r6 @ r6 = tmp1*vol_r |

1094 | + |

1095 | + ADDS r7, r7, r4, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l |

1096 | + MOV r4, #0 |

1097 | + RSCVS r7, r4, #1<<31 @ Clamp r7 |

1098 | + ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r |

1099 | + RSCVS r6, r4, #1<<31 @ Clamp r6 |

1100 | + |

1101 | + MOV r7, r7, LSR #16 @ Shift back to halfword |

1102 | + MOV r6, r6, LSR #16 @ Shift back to halfword |

1103 | + |

1104 | + LDR r5, [r2,#12] @ r5 = opos_inc |

1105 | + STRH r6, [r3],#2 @ Store output value |

1106 | + STRH r7, [r3],#2 @ Store output value |

1107 | + SUBS r11, r11,#1 @ opos-- |

1108 | + BLE LinearRate_R_end @ and loop |

1109 | + |

1110 | + ADDS r8, r8, r5 @ r8 = opos += opos_inc |

1111 | + BLT LinearRate_R_part2 |

1112 | + B LinearRate_R_loop |

1113 | +LinearRate_R_end: |

1114 | + ADD r13,r13,#8 |

1115 | + STMIA r2,{r0,r1,r8} |

1116 | + LDMFD r13!,{r4-r11,PC} |

1117 | +LinearRate_R_read: |

1118 | + ADD r0, r2, #32 @ r0 = inPtr = inBuf |

1119 | + STMFD r13!,{r0,r2-r3,r12,r14} |

1120 | + |

1121 | + MOV r1, r0 @ r1 = inBuf |

1122 | + LDR r0, [r13,#4*5] @ r0 = AudioStream & input |

1123 | + MOV r2, #512 @ r2 = ARRAYSIZE(inBuf) |

1124 | + |

1125 | + @ Calling back into C++ here. WinCE is fairly easy about such things |

1126 | + @ but other OS are more awkward. r9 is preserved for Symbian, and |

1127 | + @ we have 2+9+5 = 16 things on the stack (an even number). |

1128 | + MOV r14,PC |

1129 | + LDR PC,[r13,#4*6] @ inLen = input.readBuffer(inBuf,512) |

1130 | + SUBS r1, r0, #2 @ r1 = inLen-2 |

1131 | + LDMFD r13!,{r0,r2-r3,r12,r14} |

1132 | + BLT LinearRate_R_end |

1133 | + B LinearRate_R_read_return |

1134 | |

1135 | Property changes on: sound/rate_arm_asm.s |

1136 | ___________________________________________________________________ |

1137 | Name: svn:executable |

1138 | + * |

1139 | |

1140 | Index: sound/module.mk |

1141 | =================================================================== |

1142 | --- sound/module.mk (revision 27465) |

1143 | +++ sound/module.mk (working copy) |

1144 | @@ -16,7 +16,6 @@ |

1145 | mp3.o \ |

1146 | mpu401.o \ |

1147 | null.o \ |

1148 | - rate.o \ |

1149 | voc.o \ |

1150 | vorbis.o \ |

1151 | wave.o \ |

1152 | @@ -31,5 +30,14 @@ |

1153 | softsynth/fluidsynth.o \ |

1154 | softsynth/mt32.o \ |

1155 | |

1156 | +ifndef USE_ARM_SOUND_ASM |

1157 | +MODULE_OBJS += \ |

1158 | + rate.o |

1159 | +else |

1160 | +MODULE_OBJS += \ |

1161 | + rate_arm.o \ |

1162 | + rate_arm_asm.o |

1163 | +endif |

1164 | + |

1165 | # Include common rules |

1166 | include $(srcdir)/rules.mk |

1167 | Index: backends/platform/wince/Makefile |

1168 | =================================================================== |

1169 | --- backends/platform/wince/Makefile (revision 27465) |

1170 | +++ backends/platform/wince/Makefile (working copy) |

1171 | @@ -25,6 +25,8 @@ |

1172 | |

1173 | #DISABLE_HQ_SCALERS = 1 |

1174 | |

1175 | +USE_ARM_SOUND_ASM = 1 |

1176 | + |

1177 | CXX = arm-wince-pe-g++ |

1178 | LD = arm-wince-pe-g++ |

1179 | AR = arm-wince-pe-ar cru |