aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Sandulenko2015-11-09 16:39:17 +0100
committerEugene Sandulenko2015-11-09 16:39:17 +0100
commit82c98e98033eafa2ed04febe2607f09636e7e6a5 (patch)
tree450e3e543c839c6b89aedf1a1e329fd9072d51ee
parent30b6682130e5aefe1e019eb37c0cd25b5831d225 (diff)
parent9003ce517ff9906b0288f9f7c02197fd091d4554 (diff)
downloadscummvm-rg350-82c98e98033eafa2ed04febe2607f09636e7e6a5.tar.gz
scummvm-rg350-82c98e98033eafa2ed04febe2607f09636e7e6a5.tar.bz2
scummvm-rg350-82c98e98033eafa2ed04febe2607f09636e7e6a5.zip
Merge pull request #625 from digitall/rate-hack
AUDIO: Add support for sample rates >65kHz.
-rw-r--r--audio/rate.cpp32
-rw-r--r--audio/rate_arm.cpp21
-rw-r--r--audio/rate_arm_asm.s34
3 files changed, 54 insertions, 33 deletions
diff --git a/audio/rate.cpp b/audio/rate.cpp
index 19d9c8c61e..6264465e19 100644
--- a/audio/rate.cpp
+++ b/audio/rate.cpp
@@ -46,6 +46,16 @@ namespace Audio {
*/
#define INTERMEDIATE_BUFFER_SIZE 512
+/**
+ * The default fractional type in frac.h (with 16 fractional bits) limits
+ * the rate conversion code to 65536Hz audio: we need to able to handle
+ * 96kHz audio, so we use fewer fractional bits in this code.
+ */
+enum {
+ FRAC_BITS_LOW = 15,
+ FRAC_ONE_LOW = (1L << FRAC_BITS_LOW),
+ FRAC_HALF_LOW = (1L << (FRAC_BITS_LOW-1))
+};
/**
* Audio rate converter based on simple resampling. Used when no
@@ -187,18 +197,18 @@ public:
*/
template<bool stereo, bool reverseStereo>
LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate, st_rate_t outrate) {
- if (inrate >= 65536 || outrate >= 65536) {
- error("rate effect can only handle rates < 65536");
+ if (inrate >= 131072 || outrate >= 131072) {
+ error("rate effect can only handle rates < 131072");
}
- opos = FRAC_ONE;
+ opos = FRAC_ONE_LOW;
// Compute the linear interpolation increment.
- // This will overflow if inrate >= 2^16, and underflow if outrate >= 2^16.
+ // This will overflow if inrate >= 2^17, and underflow if outrate >= 2^17.
// Also, if the quotient of the two rate becomes too small / too big, that
// would cause problems, but since we rarely scale from 1 to 65536 Hz or vice
// versa, I think we can live with that limitation ;-).
- opos_inc = (inrate << FRAC_BITS) / outrate;
+ opos_inc = (inrate << FRAC_BITS_LOW) / outrate;
ilast0 = ilast1 = 0;
icur0 = icur1 = 0;
@@ -220,7 +230,7 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
while (obuf < oend) {
// read enough input samples so that opos < 0
- while ((frac_t)FRAC_ONE <= opos) {
+ while ((frac_t)FRAC_ONE_LOW <= opos) {
// Check if we have to refill the buffer
if (inLen == 0) {
inPtr = inBuf;
@@ -235,17 +245,17 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
ilast1 = icur1;
icur1 = *inPtr++;
}
- opos -= FRAC_ONE;
+ opos -= FRAC_ONE_LOW;
}
// Loop as long as the outpos trails behind, and as long as there is
// still space in the output buffer.
- while (opos < (frac_t)FRAC_ONE && obuf < oend) {
+ while (opos < (frac_t)FRAC_ONE_LOW && obuf < oend) {
// interpolate
st_sample_t out0, out1;
- out0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * opos + FRAC_HALF) >> FRAC_BITS));
+ out0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * opos + FRAC_HALF_LOW) >> FRAC_BITS_LOW));
out1 = (stereo ?
- (st_sample_t)(ilast1 + (((icur1 - ilast1) * opos + FRAC_HALF) >> FRAC_BITS)) :
+ (st_sample_t)(ilast1 + (((icur1 - ilast1) * opos + FRAC_HALF_LOW) >> FRAC_BITS_LOW)) :
out0);
// output left channel
@@ -333,7 +343,7 @@ public:
template<bool stereo, bool reverseStereo>
RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate) {
if (inrate != outrate) {
- if ((inrate % outrate) == 0) {
+ if ((inrate % outrate) == 0 && (inrate < 65536)) {
return new SimpleRateConverter<stereo, reverseStereo>(inrate, outrate);
} else {
return new LinearRateConverter<stereo, reverseStereo>(inrate, outrate);
diff --git a/audio/rate_arm.cpp b/audio/rate_arm.cpp
index 4ad8d71a34..7765266673 100644
--- a/audio/rate_arm.cpp
+++ b/audio/rate_arm.cpp
@@ -68,6 +68,16 @@ namespace Audio {
*/
#define INTERMEDIATE_BUFFER_SIZE 512
+/**
+ * The default fractional type in frac.h (with 16 fractional bits) limits
+ * the rate conversion code to 65536Hz audio: we need to able to handle
+ * 96kHz audio, so we use fewer fractional bits in this code.
+ */
+enum {
+ FRAC_BITS_LOW = 15,
+ FRAC_ONE_LOW = (1L << FRAC_BITS_LOW),
+ FRAC_HALF_LOW = (1L << (FRAC_BITS_LOW-1))
+};
/**
* Audio rate converter based on simple resampling. Used when no
@@ -287,17 +297,18 @@ LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate
error("Input and Output rates must be different to use rate effect");
}
- if (inrate >= 65536 || outrate >= 65536) {
- error("rate effect can only handle rates < 65536");
+ if (inrate >= 131072 || outrate >= 131072) {
+ error("rate effect can only handle rates < 131072");
}
- lr.opos = FRAC_ONE;
+ lr.opos = FRAC_ONE_LOW;
/* increment */
- incr = (inrate << FRAC_BITS) / outrate;
+ incr = (inrate << FRAC_BITS_LOW) / outrate;
lr.opos_inc = incr;
+ // FIXME: Does 32768 here need changing to 65536 or 0? Compare to rate.cpp code...
lr.ilast[0] = lr.ilast[1] = 32768;
lr.icur[0] = lr.icur[1] = 0;
@@ -438,7 +449,7 @@ public:
*/
RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) {
if (inrate != outrate) {
- if ((inrate % outrate) == 0) {
+ if ((inrate % outrate) == 0 && (inrate < 65536)) {
if (stereo) {
if (reverseStereo)
return new SimpleRateConverter<true, true>(inrate, outrate);
diff --git a/audio/rate_arm_asm.s b/audio/rate_arm_asm.s
index a727209d39..bb01c614c2 100644
--- a/audio/rate_arm_asm.s
+++ b/audio/rate_arm_asm.s
@@ -441,17 +441,17 @@ LinearRate_M_part2:
LDRSH r4, [r3] @ r4 = obuf[0]
LDRSH r5, [r3,#2] @ r5 = obuf[1]
- MOV r6, r6, ASR #16 @ r6 = tmp0 = tmp1 >>= 16
+ MOV r6, r6, ASR #15 @ r6 = tmp0 = tmp1 >>= 15
MUL r7, r12,r6 @ r7 = tmp0*vol_l
MUL r6, r14,r6 @ r6 = tmp1*vol_r
- ADDS r7, r7, r4, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l
+ ADDS r7, r7, r4, LSL #15 @ r7 = obuf[0]<<15 + tmp0*vol_l
RSCVS r7, r10, #0x80000000 @ Clamp r7
- ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r
+ ADDS r6, r6, r5, LSL #15 @ r6 = obuf[1]<<15 + tmp1*vol_r
RSCVS r6, r10, #0x80000000 @ Clamp r6
- MOV r7, r7, LSR #16 @ Shift back to halfword
- MOV r6, r6, LSR #16 @ Shift back to halfword
+ MOV r7, r7, LSR #15 @ Shift back to halfword
+ MOV r6, r6, LSR #15 @ Shift back to halfword
LDR r5, [r2,#12] @ r5 = opos_inc
STRH r7, [r3],#2 @ Store output value
@@ -538,23 +538,23 @@ LinearRate_S_part2:
LDR r7, [r2,#24] @ r7 = ilast[1]<<16 + 32768
LDRSH r5, [r2,#18] @ r5 = icur[1]
LDRSH r10,[r3] @ r10= obuf[0]
- MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16
+ MOV r6, r6, ASR #15 @ r6 = tmp1 >>= 15
SUB r5, r5, r7, ASR #16 @ r5 = icur[1] - ilast[1]
MLA r7, r4, r5, r7 @ r7 = (icur[1]-ilast[1])*opos_frac+ilast[1]
LDRSH r5, [r3,#2] @ r5 = obuf[1]
- MOV r7, r7, ASR #16 @ r7 = tmp0 >>= 16
+ MOV r7, r7, ASR #15 @ r7 = tmp0 >>= 15
MUL r7, r12,r7 @ r7 = tmp0*vol_l
MUL r6, r14,r6 @ r6 = tmp1*vol_r
- ADDS r7, r7, r10, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l
+ ADDS r7, r7, r10, LSL #15 @ r7 = obuf[0]<<15 + tmp0*vol_l
MOV r4, #0
RSCVS r7, r4, #0x80000000 @ Clamp r7
- ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r
+ ADDS r6, r6, r5, LSL #15 @ r6 = obuf[1]<<15 + tmp1*vol_r
RSCVS r6, r4, #0x80000000 @ Clamp r6
- MOV r7, r7, LSR #16 @ Shift back to halfword
- MOV r6, r6, LSR #16 @ Shift back to halfword
+ MOV r7, r7, LSR #15 @ Shift back to halfword
+ MOV r6, r6, LSR #15 @ Shift back to halfword
LDR r5, [r2,#12] @ r5 = opos_inc
STRH r7, [r3],#2 @ Store output value
@@ -641,23 +641,23 @@ LinearRate_R_part2:
LDR r7, [r2,#24] @ r7 = ilast[1]<<16 + 32768
LDRSH r5, [r2,#18] @ r5 = icur[1]
LDRSH r10,[r3,#2] @ r10= obuf[1]
- MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16
+ MOV r6, r6, ASR #15 @ r6 = tmp1 >>= 15
SUB r5, r5, r7, ASR #16 @ r5 = icur[1] - ilast[1]
MLA r7, r4, r5, r7 @ r7 = (icur[1]-ilast[1])*opos_frac+ilast[1]
LDRSH r5, [r3] @ r5 = obuf[0]
- MOV r7, r7, ASR #16 @ r7 = tmp0 >>= 16
+ MOV r7, r7, ASR #15 @ r7 = tmp0 >>= 15
MUL r7, r12,r7 @ r7 = tmp0*vol_l
MUL r6, r14,r6 @ r6 = tmp1*vol_r
- ADDS r7, r7, r10, LSL #16 @ r7 = obuf[1]<<16 + tmp0*vol_l
+ ADDS r7, r7, r10, LSL #15 @ r7 = obuf[1]<<15 + tmp0*vol_l
MOV r4, #0
RSCVS r7, r4, #0x80000000 @ Clamp r7
- ADDS r6, r6, r5, LSL #16 @ r6 = obuf[0]<<16 + tmp1*vol_r
+ ADDS r6, r6, r5, LSL #15 @ r6 = obuf[0]<<15 + tmp1*vol_r
RSCVS r6, r4, #0x80000000 @ Clamp r6
- MOV r7, r7, LSR #16 @ Shift back to halfword
- MOV r6, r6, LSR #16 @ Shift back to halfword
+ MOV r7, r7, LSR #15 @ Shift back to halfword
+ MOV r6, r6, LSR #15 @ Shift back to halfword
LDR r5, [r2,#12] @ r5 = opos_inc
STRH r6, [r3],#2 @ Store output value