/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1992-2001 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This is a impementation of sampling rate conversion for low-passed signals.
*
* To convert the input signal of sampling rate of fi to another rate of fo,
* the least common multiple of fi and fo is derived first:
* fm = L * fi = M * fo.
* Then the input signal is up-sampled to fm by inserting (L -1) zero valued
* samples after each input sample, low-pass filtered, and down-smapled by
* saving one sample for every M samples. The implementation takes advantages
* of the (L - 1) zero values in the filter input and the (M - 1) output
* samples to be disregarded.
*
* If L = 1 or M = 1, a simpler decimation or interpolation is used.
*/
#include <memory.h>
#include <math.h>
#include <Resample.h>
extern "C" {
char *bcopy(char *, char *, int);
char *memmove(char *, char *, int);
}
// convolve(), short2double() and double2short() are defined in Fir.cc.
extern double convolve(double *, double *, int);
extern void short2double(double *, short *, int);
extern short double2short(double);
// generate truncated ideal LPF
int order, // LP FIR filter order
double *coef) // filter coefficients
{
int i;
float alpha;
for (i = 0; i <= half; i++) {
}
} else { // order is even, center = half
for (i = 0; i < half; i++) {
}
}
for (; i <= order; i++) // symmetric FIR
}
/*
* poly_conv() = coef[0] * data[length - 1] +
* coef[inc_coef] * data[length - 2] +
* ...
* coef[(length - 1) * inc_coef] * data[0] +
*
* convolution of coef[order + 1] and data[length] up-sampled by a factor
* of inc_coef. The terms of coef[1, 2, ... inc_coef - 1] multiplying 0
* are ignored.
*/
// polyphase filter convolution
double
int order, // filter order
int inc_coef, // 1-to-L up-sample for data[length]
double *data, // data array
int length) // data array length
{
return (0.0);
else {
}
return (sum);
}
}
int
{
int remainder = a % b;
}
void ResampleFilter::
double *in,
int size)
{
if (up <= 1)
num_state * sizeof (double));
else {
old * sizeof (double));
}
}
ResampleFilter:: // constructor
int rate_in, // sampling rate of input signal
int rate_out) // sampling rate of output signal
{
// filter sampling rate = common multiple of rate_in and rate_out
for (int i = 0; i < num_state; i++) // reset states
state[i] = 0.0;
} else {
resetState();
}
down_offset = 0;
up_offset = 0;
}
// down-to-1 decimation
int ResampleFilter::
int size,
short *out)
{
int i;
if (size <= 0)
return (0);
down_offset -= size;
return (0);
}
// filter and decimate and output
order + 1));
down_offset = i - size;
delete in_buf;
}
// decimate with group delay adjusted to 0
int ResampleFilter::
int size,
short *out)
{
if (delay <= 0)
return (0);
} else {
delay = 0;
}
}
// flush decimate filter
int ResampleFilter::
{
delete in;
return (num_out);
}
// 1-to-up interpolation
int ResampleFilter::
int size,
short *out)
{
int i, j;
if (size <= 0)
return (0);
// befor the 1st input sample, generate "-up_offset" output samples
for (j = up_offset; j < 0; j++) {
coef_offset++;
}
// for each of the rest input samples, generate up output samples
for (i = 1; i < size; i++) {
for (j = 0; j < up; j++) {
num_state)));
coef_offset++;
}
}
// for the last input samples, generate "up_offset + up" output samples
num_state)));
coef_offset++;
}
delete in_buf;
}
// flush interpolate filter
int ResampleFilter::
{
delete in;
return (out_num);
}
// interpolate with delay adjusted
int ResampleFilter::
int size,
short *out)
{
if (size <= 0)
return (interpolate_flush(out));
else if (delay <= 0)
else {
delete in_buf;
}
}
int ResampleFilter::
int size,
short *out)
{
int i, j;
if (size <= 0)
return (0);
else if (up <= 1)
else if (down <= 1)
/*
* before the 1st input sample,
* start from "up_offset + down_offset"th up-sampled sample
*/
coef_offset += down;
}
// process the input samples until the last one
for (i = 1; i < size; i++) {
num_state)));
coef_offset += down;
}
j -= up;
}
// for the last input sample, end at the "up + up_offset"th
coef_offset += down;
}
delete in_buf;
}
int ResampleFilter::
getFlushSize(void)
{
}
int ResampleFilter::
{
if (down <= 1)
return (interpolate_flush(out));
else if (up <= 1)
return (decimate_flush(out));
delete in;
return (out_num);
}
/*
* sampling rate conversion with filter delay adjusted
*/
int ResampleFilter::
short *in,
int size,
short *out)
{
if (size <= 0)
else if (up <= 1)
else if (down <= 1)
else if (delay <= 0)
else {
delete in_buf;
if (delay <= 0) {
down_offset = 0;
}
}
}