Ticket #8661: ARM_ASM_Sound_Diffs.txt

File ARM_ASM_Sound_Diffs.txt, 44.7 KB (added by SF/robinwatts, 13 years ago)

ARM asm version of sound rate conversion/mixing code v4

Line 
1Index: 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
435Property changes on: sound/rate_arm.cpp
436___________________________________________________________________
437Name: svn:executable
438 + *
439
440Index: 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
1135Property changes on: sound/rate_arm_asm.s
1136___________________________________________________________________
1137Name: svn:executable
1138 + *
1139
1140Index: 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
1167Index: 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