diff options
| author | Eugene Sandulenko | 2015-11-09 16:39:17 +0100 | 
|---|---|---|
| committer | Eugene Sandulenko | 2015-11-09 16:39:17 +0100 | 
| commit | 82c98e98033eafa2ed04febe2607f09636e7e6a5 (patch) | |
| tree | 450e3e543c839c6b89aedf1a1e329fd9072d51ee | |
| parent | 30b6682130e5aefe1e019eb37c0cd25b5831d225 (diff) | |
| parent | 9003ce517ff9906b0288f9f7c02197fd091d4554 (diff) | |
| download | scummvm-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.cpp | 32 | ||||
| -rw-r--r-- | audio/rate_arm.cpp | 21 | ||||
| -rw-r--r-- | audio/rate_arm_asm.s | 34 | 
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  | 
