More resampler cleanups.

This commit is contained in:
Gregory Maxwell 2011-09-28 12:40:06 -04:00
parent 96739ad35e
commit 744e59ef01
10 changed files with 14 additions and 222 deletions

View file

@ -74,16 +74,6 @@ opus_int silk_resampler(
opus_int32 inLen /* I: Number of input samples */
);
/*!
Upsample 2x, low quality
*/
void silk_resampler_up2(
opus_int32 *S, /* I/O: State vector [ 2 ] */
opus_int16 *out, /* O: Output signal [ 2 * len ] */
const opus_int16 *in, /* I: Input signal [ len ] */
opus_int32 len /* I: Number of input samples */
);
/*!
* Downsample 2x, mediocre quality
*/
@ -94,7 +84,6 @@ void silk_resampler_down2(
opus_int32 inLen /* I: Number of input samples */
);
/*!
* Downsample by a factor 2/3, low quality
*/

View file

@ -30,16 +30,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
/* Matrix of resampling methods used:
* Fs_out (kHz)
* 8 12 16 24 32 44.1 48
* Fs_out (kHz)
* 8 12 16 24 48
*
* 8 C UF U UF UF UF UF
* 12 AF C UF U UF UF UF
* 16 D AF C UF U UF UF
* Fs_in (kHz) 24 AIF D AF C UF UF U
* 32 UF AF D AF C UF UF
* 44.1 AMI AMI AMI AMI AMI C UF
* 48 DAF DAF AF D AF UF C
* 8 C UF U UF UF
* 12 AF C UF U UF
* Fs_in (kHz) 16 D AF C UF UF
* 24 AIF D AF C U
* 48 DAF DAF AF D C
*
* default method: UF
*
@ -48,30 +46,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* U -> Allpass-based 2x upsampling
* DAF -> Allpass-based 2x downsampling followed by AR2 filter followed by FIR interpolation
* UF -> Allpass-based 2x upsampling followed by FIR interpolation
* AMI -> ARMA4 filter followed by FIR interpolation
* AF -> AR2 filter followed by FIR interpolation
*
* Input signals sampled above 48 kHz are first downsampled to at most 48 kHz.
* Output signals sampled above 48 kHz are upsampled from at most 48 kHz.
* Signals sampled above 48 kHz are not supported.
*/
#include "resampler_private.h"
/* Greatest common divisor */
static opus_int32 gcd(
opus_int32 a,
opus_int32 b
)
{
opus_int32 tmp;
while( b > 0 ) {
tmp = a - b * silk_DIV32( a, b );
a = b;
b = tmp;
}
return a;
}
#define USE_silk_resampler_copy (0)
#define USE_silk_resampler_private_up2_HQ_wrapper (1)
#define USE_silk_resampler_private_IIR_FIR (2)
@ -84,33 +65,20 @@ opus_int silk_resampler_init(
opus_int32 Fs_Hz_out /* I: Output sampling rate (Hz) */
)
{
opus_int32 cycleLen, cyclesPerBatch, up2 = 0, down2 = 0;
opus_int32 up2 = 0, down2 = 0;
/* Clear state */
silk_memset( S, 0, sizeof( silk_resampler_state_struct ) );
/* Input checking */
if( Fs_Hz_in < 8000 || Fs_Hz_in > 48000 || Fs_Hz_out < 8000 || Fs_Hz_out > 48000 ) {
if( (Fs_Hz_in!=8000 && Fs_Hz_in!=12000 && Fs_Hz_in!=16000 && Fs_Hz_in!=24000 && Fs_Hz_in!=48000) ||
(Fs_Hz_out!=8000 && Fs_Hz_out!=12000 && Fs_Hz_out!=16000 && Fs_Hz_out!=24000 && Fs_Hz_out!=48000) ) {
silk_assert( 0 );
return -1;
}
/* Number of samples processed per batch */
/* First, try 10 ms frames */
S->batchSize = silk_DIV32_16( Fs_Hz_in, 100 );
if( ( silk_MUL( S->batchSize, 100 ) != Fs_Hz_in ) || ( Fs_Hz_in % 100 != 0 ) ) {
/* No integer number of input or output samples with 10 ms frames, use greatest common divisor */
cycleLen = silk_DIV32( Fs_Hz_in, gcd( Fs_Hz_in, Fs_Hz_out ) );
cyclesPerBatch = silk_DIV32( RESAMPLER_MAX_BATCH_SIZE_IN, cycleLen );
if( cyclesPerBatch == 0 ) {
/* cycleLen too big, let's just use the maximum batch size. Some distortion will result. */
S->batchSize = RESAMPLER_MAX_BATCH_SIZE_IN;
silk_assert( 0 );
} else {
S->batchSize = silk_MUL( cyclesPerBatch, cycleLen );
}
}
/* Find resampler with the right sampling ratio */
if( Fs_Hz_out > Fs_Hz_in ) {
@ -122,7 +90,6 @@ opus_int silk_resampler_init(
/* Default resampler */
S->resampler_function = USE_silk_resampler_private_IIR_FIR;
up2 = 1;
S->up2_hq = Fs_Hz_in <= 24000;
}
} else if ( Fs_Hz_out < Fs_Hz_in ) {
/* Downsample */
@ -138,10 +105,6 @@ opus_int silk_resampler_init(
S->FIR_Fracs = 1;
S->Coefs = silk_Resampler_1_2_COEFS;
S->resampler_function = USE_silk_resampler_private_down_FIR;
} else if( silk_MUL( Fs_Hz_out, 8 ) == silk_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 8 */
S->FIR_Fracs = 3;
S->Coefs = silk_Resampler_3_8_COEFS;
S->resampler_function = USE_silk_resampler_private_down_FIR;
} else if( silk_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 3 */
S->FIR_Fracs = 1;
S->Coefs = silk_Resampler_1_3_COEFS;
@ -156,26 +119,10 @@ opus_int silk_resampler_init(
down2 = 1;
S->Coefs = silk_Resampler_1_3_COEFS;
S->resampler_function = USE_silk_resampler_private_down_FIR;
} else if( silk_MUL( Fs_Hz_out, 441 ) == silk_MUL( Fs_Hz_in, 80 ) ) { /* Fs_out : Fs_in = 80 : 441 */
S->Coefs = silk_Resampler_80_441_ARMA4_COEFS;
S->resampler_function = USE_silk_resampler_private_IIR_FIR;
} else if( silk_MUL( Fs_Hz_out, 441 ) == silk_MUL( Fs_Hz_in, 120 ) ) { /* Fs_out : Fs_in = 120 : 441 */
S->Coefs = silk_Resampler_120_441_ARMA4_COEFS;
S->resampler_function = USE_silk_resampler_private_IIR_FIR;
} else if( silk_MUL( Fs_Hz_out, 441 ) == silk_MUL( Fs_Hz_in, 160 ) ) { /* Fs_out : Fs_in = 160 : 441 */
S->Coefs = silk_Resampler_160_441_ARMA4_COEFS;
S->resampler_function = USE_silk_resampler_private_IIR_FIR;
} else if( silk_MUL( Fs_Hz_out, 441 ) == silk_MUL( Fs_Hz_in, 240 ) ) { /* Fs_out : Fs_in = 240 : 441 */
S->Coefs = silk_Resampler_240_441_ARMA4_COEFS;
S->resampler_function = USE_silk_resampler_private_IIR_FIR;
} else if( silk_MUL( Fs_Hz_out, 441 ) == silk_MUL( Fs_Hz_in, 320 ) ) { /* Fs_out : Fs_in = 320 : 441 */
S->Coefs = silk_Resampler_320_441_ARMA4_COEFS;
S->resampler_function = USE_silk_resampler_private_IIR_FIR;
} else {
/* Default resampler */
S->resampler_function = USE_silk_resampler_private_IIR_FIR;
up2 = 1;
S->up2_hq = Fs_Hz_in <= 24000;
/* None available */
silk_assert( 0 );
return -1;
}
} else {
/* Input and output sampling rates are equal: copy */
@ -191,8 +138,6 @@ opus_int silk_resampler_init(
S->invRatio_Q16++;
}
S->magic_number = 123456789;
return 0;
}
@ -216,12 +161,6 @@ opus_int silk_resampler(
opus_int32 inLen /* I: Number of input samples */
)
{
/* Verify that state was initialized and has not been corrupted */
if( S->magic_number != 123456789 ) {
silk_assert( 0 );
return -1;
}
/* Input and output sampling rate are at most 48000 Hz */
switch(S->resampler_function) {
case USE_silk_resampler_private_up2_HQ_wrapper:
@ -236,6 +175,5 @@ opus_int silk_resampler(
default:
silk_memcpy( out, in, inLen * sizeof( opus_int16 ) );
}
return 0;
}

View file

@ -76,11 +76,7 @@ void silk_resampler_private_IIR_FIR(
if( S->input2x == 1 ) {
/* Upsample 2x */
if (S->up2_hq) {
silk_resampler_private_up2_HQ( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, nSamplesIn );
} else {
silk_resampler_up2( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, nSamplesIn );
}
} else {
/* Fourth-order ARMA filter */
silk_resampler_private_ARMA4( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, S->Coefs, nSamplesIn );

View file

@ -38,10 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
const opus_int16 silk_resampler_down2_0 = 9872;
const opus_int16 silk_resampler_down2_1 = 39809 - 65536;
/* Tables for 2x upsampler, low quality */
const opus_int16 silk_resampler_up2_lq_0 = 8102;
const opus_int16 silk_resampler_up2_lq_1 = 36783 - 65536;
/* Tables for 2x upsampler, high quality */
const opus_int16 silk_resampler_up2_hq_0[ 2 ] = { 4280, 33727 - 65536 };
const opus_int16 silk_resampler_up2_hq_1[ 2 ] = { 16295, 54015 - 65536 };
@ -66,13 +62,6 @@ silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_O
-91, 162, 169, -342, -505, 1332, 5281, 8742,
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_8_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = {
12634, -14550,
246, -175, -326, -113, 764, 2209, 3664, 4402,
171, 3, -301, -258, 391, 1693, 3227, 4272,
88, 138, -236, -327, 95, 1203, 2733, 4022,
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ] = {
16306, -14409,
99, -201, -220, -16, 572, 1483, 2433, 3043,
@ -84,35 +73,6 @@ silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = {
1567, 8276,
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS_LQ[ 2 + 3 ] = {
16777, -9792,
890, 1614, 2148,
};
/* Tables with coefficients for 4th order ARMA filter (35 Words), in a packed format: */
/* { B1_Q14[1], B2_Q14[1], -A1_Q14[1], -A1_Q14[2], -A2_Q14[1], -A2_Q14[2], gain_Q16 } */
/* where it is assumed that B*_Q14[0], B*_Q14[2], A*_Q14[0] are all 16384 */
silk_DWORD_ALIGN const opus_int16 silk_Resampler_320_441_ARMA4_COEFS[ 7 ] = {
31454, 24746, -9706, -3386, -17911, -13243, 24797
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_240_441_ARMA4_COEFS[ 7 ] = {
28721, 11254, 3189, -2546, -1495, -12618, 11562
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_160_441_ARMA4_COEFS[ 7 ] = {
23492, -6457, 14358, -4856, 14654, -13008, 4456
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_120_441_ARMA4_COEFS[ 7 ] = {
19311, -15569, 19489, -6950, 21441, -13559, 2370
};
silk_DWORD_ALIGN const opus_int16 silk_Resampler_80_441_ARMA4_COEFS[ 7 ] = {
13248, -23849, 24126, -9486, 26806, -14286, 1065
};
/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */
silk_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ] = {
{ -25, 58, 32526},

View file

@ -44,10 +44,6 @@ extern "C"
extern const opus_int16 silk_resampler_down2_0;
extern const opus_int16 silk_resampler_down2_1;
/* Tables for 2x upsampler, low quality. Values above 32767 intentionally wrap to a negative value. */
extern const opus_int16 silk_resampler_up2_lq_0;
extern const opus_int16 silk_resampler_up2_lq_1;
/* Tables for 2x upsampler, high quality. Values above 32767 intentionally wrap to a negative value. */
extern const opus_int16 silk_resampler_up2_hq_0[ 2 ];
extern const opus_int16 silk_resampler_up2_hq_1[ 2 ];
@ -57,17 +53,8 @@ extern const opus_int16 silk_resampler_up2_hq_notch[ 4 ];
extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ];
extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR / 2 ];
extern const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ];
extern const opus_int16 silk_Resampler_3_8_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ];
extern const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ];
extern const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ];
extern const opus_int16 silk_Resampler_1_3_COEFS_LQ[ 2 + 3 ];
/* Tables with coefficients for 4th order ARMA filter */
extern const opus_int16 silk_Resampler_320_441_ARMA4_COEFS[ 7 ];
extern const opus_int16 silk_Resampler_240_441_ARMA4_COEFS[ 7 ];
extern const opus_int16 silk_Resampler_160_441_ARMA4_COEFS[ 7 ];
extern const opus_int16 silk_Resampler_120_441_ARMA4_COEFS[ 7 ];
extern const opus_int16 silk_Resampler_80_441_ARMA4_COEFS[ 7 ];
/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */
extern const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ];

View file

@ -42,13 +42,11 @@ typedef struct _silk_resampler_state_struct{
opus_int32 sFIR[ SILK_RESAMPLER_MAX_FIR_ORDER ];
opus_int32 sDown2[ 2 ];
opus_int32 resampler_function;
opus_int32 up2_hq;
opus_int32 batchSize;
opus_int32 invRatio_Q16;
opus_int32 FIR_Fracs;
opus_int32 input2x;
const opus_int16 *Coefs;
opus_int32 magic_number;
} silk_resampler_state_struct;
#ifdef __cplusplus

View file

@ -1,71 +0,0 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "SigProc_FIX.h"
#include "resampler_rom.h"
/* Upsample by a factor 2, low quality */
void silk_resampler_up2(
opus_int32 *S, /* I/O: State vector [ 2 ] */
opus_int16 *out, /* O: Output signal [ 2 * len ] */
const opus_int16 *in, /* I: Input signal [ len ] */
opus_int32 len /* I: Number of input samples */
)
{
opus_int32 k;
opus_int32 in32, out32, Y, X;
silk_assert( silk_resampler_up2_lq_0 > 0 );
silk_assert( silk_resampler_up2_lq_1 < 0 );
/* Internal variables and state are in Q10 format */
for( k = 0; k < len; k++ ) {
/* Convert to Q10 */
in32 = silk_LSHIFT( (opus_int32)in[ k ], 10 );
/* All-pass section for even output sample */
Y = silk_SUB32( in32, S[ 0 ] );
X = silk_SMULWB( Y, silk_resampler_up2_lq_0 );
out32 = silk_ADD32( S[ 0 ], X );
S[ 0 ] = silk_ADD32( in32, X );
/* Convert back to int16 and store to output */
out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32, 10 ) );
/* All-pass section for odd output sample */
Y = silk_SUB32( in32, S[ 1 ] );
X = silk_SMLAWB( Y, Y, silk_resampler_up2_lq_1 );
out32 = silk_ADD32( S[ 1 ], X );
S[ 1 ] = silk_ADD32( in32, X );
/* Convert back to int16 and store to output */
out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32, 10 ) );
}
}

View file

@ -151,7 +151,6 @@
<ClCompile Include="resampler_private_IIR_FIR.c" />
<ClCompile Include="resampler_private_up2_HQ.c" />
<ClCompile Include="resampler_rom.c" />
<ClCompile Include="resampler_up2.c" />
<ClCompile Include="scale_copy_vector16.c" />
<ClCompile Include="scale_vector.c" />
<ClCompile Include="schur.c" />

View file

@ -213,9 +213,6 @@
<ClCompile Include="resampler_rom.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="resampler_up2.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="scale_copy_vector16.c">
<Filter>Source Files</Filter>
</ClCompile>

View file

@ -76,7 +76,6 @@ silk/resampler_private_down_FIR.c \
silk/resampler_private_IIR_FIR.c \
silk/resampler_private_up2_HQ.c \
silk/resampler_rom.c \
silk/resampler_up2.c \
silk/scale_copy_vector16.c \
silk/scale_vector.c \
silk/schur64.c \