Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
The windowed sinc filter generation code seems to be working fine. Th…
Browse files Browse the repository at this point in the history
…e FIR filtering code is also now working reasonably well. Occasionally the FIR filter will pop, but setting the normalization factor lower seems to help this. I suspect the problem is in the fixed point multiply/add. I also have a hunch the zero stuffing/sample discarding code is not correct, and I'll look at that soon to get it sorted out.
  • Loading branch information
schnarf committed Jul 2, 2008
1 parent a828ffa commit b96e3dd
Showing 1 changed file with 20 additions and 20 deletions.
40 changes: 20 additions & 20 deletions src/audio/SDL_audiocvt.c
Expand Up @@ -1530,23 +1530,23 @@ static void SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) {
int m = cvt->len_sinc;
int i, j;

/* Note: this makes use of the symmetry of the sinc filter.
We can also make a big optimization here by taking advantage
/*
Note: We can make a big optimization here by taking advantage
of the fact that the signal is zero stuffed, so we can do
significantly fewer multiplications and additions.
significantly fewer multiplications and additions. However, this
depends on the zero stuffing ratio, so it may not pay off.
*/
#define filter_sinc(type, mult) { \
type *sinc = (type *)cvt->coeff; \
type *state = (type *)cvt->state_buf; \
type *buf = (type *)cvt->buf; \
for(i = 0; i < n; ++i) { \
cvt->state_pos++; \
if(cvt->state_pos >= m) cvt->state_pos = 0; \
state[cvt->state_pos] = buf[i]; \
buf[i] = 0; \
for(j = 0; j < m; ++j) { \
buf[i] += mult(state[(cvt->state_pos - j) % m], sinc[j]); \
buf[i] += mult(sinc[j], state[(cvt->state_pos + j) % m]); \
} \
cvt->state_pos = (cvt->state_pos + 1) % m; \
} \
}

Expand All @@ -1557,12 +1557,12 @@ static void SDL_FilterFIR(SDL_AudioCVT * cvt, SDL_AudioFormat format) {
float *buf = (float *)cvt->buf;

for(i = 0; i < n; ++i) {
state[cvt->state_pos++] = buf[i];
if(cvt->state_pos == m) cvt->state_pos = 0;
state[cvt->state_pos] = buf[i];
buf[i] = 0.0f;
for(j = 0; j < m; ++j) {
buf[i] += state[(cvt->state_pos - j) % m] * sinc[j];
buf[i] += sinc[j] * state[(cvt->state_pos + j) % m];
}
cvt->state_pos = (cvt->state_pos + 1) % m;
}
} else {
switch (SDL_AUDIO_BITSIZE(format)) {
Expand Down Expand Up @@ -1613,7 +1613,10 @@ SDL_BuildWindowedSinc(SDL_AudioCVT * cvt, SDL_AudioFormat format, unsigned int m

/* Set up the filter parameters */
fc = (cvt->len_mult > cvt->len_div) ? 0.5f / (float)cvt->len_mult : 0.5f / (float)cvt->len_div;
fc = 0.04f;
#ifdef DEBUG_CONVERT
printf("Lowpass cutoff frequency = %f\n", fc);
#endif
// fc = 0.02f;
two_pi_fc = 2.0f * M_PI * fc;
two_pi_over_m = 2.0f * M_PI / (float)m;
four_pi_over_m = 2.0f * two_pi_over_m;
Expand All @@ -1628,17 +1631,14 @@ SDL_BuildWindowedSinc(SDL_AudioCVT * cvt, SDL_AudioFormat format, unsigned int m
/* Apply blackman window */
fSinc[i] *= 0.42f - 0.5f * cosf(two_pi_over_m * (float)i) + 0.08f * cosf(four_pi_over_m * (float)i);
}
fSinc[i] = 0.0f;
norm_sum += fabs(fSinc[i]);
printf("%f\n", fSinc[i]);
}

#define convert_fixed(type, fix) { \
norm_fact = 0.8f / norm_sum; \
norm_fact = 0.7f / norm_sum; \
type *dst = (type *)cvt->coeff; \
for( i = 0; i <= m; ++i ) { \
dst[i] = fix(fSinc[i] * norm_fact); \
printf("%f = 0x%x\n", fSinc[i] * norm_fact, dst[i]); \
} \
}

Expand All @@ -1664,7 +1664,7 @@ SDL_BuildWindowedSinc(SDL_AudioCVT * cvt, SDL_AudioFormat format, unsigned int m
}

/* Initialize the state buffer to all zeroes, and set initial position */
//memset(cvt->state_buf, 0, cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
memset(cvt->state_buf, 0, cvt->len_sinc * SDL_AUDIO_BITSIZE(format) / 4);
cvt->state_pos = 0;

/* Clean up */
Expand Down Expand Up @@ -1717,7 +1717,7 @@ SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format)
}

// Step 1: Zero stuff the conversion buffer
/*#ifdef DEBUG_CONVERT
#ifdef DEBUG_CONVERT
printf("Zero-stuffing by a factor of %u\n", cvt->len_mult);
#endif
switch (SDL_AUDIO_BITSIZE(format)) {
Expand All @@ -1732,13 +1732,13 @@ SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format)
break;
}

cvt->len_cvt *= cvt->len_mult;*/
cvt->len_cvt *= cvt->len_mult;

// Step 2: Use either a windowed sinc FIR filter or IIR lowpass filter to remove all alias frequencies
SDL_FilterFIR( cvt, format );

// Step 3: Discard unnecessary samples
/*#ifdef DEBUG_CONVERT
#ifdef DEBUG_CONVERT
printf("Discarding samples by a factor of %u\n", cvt->len_div);
#endif
switch (SDL_AUDIO_BITSIZE(format)) {
Expand All @@ -1756,7 +1756,7 @@ SDL_Resample(SDL_AudioCVT * cvt, SDL_AudioFormat format)
#undef zerostuff_mono
#undef discard_mono

cvt->len_cvt /= cvt->len_div;*/
cvt->len_cvt /= cvt->len_div;

if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index] (cvt, format);
Expand Down Expand Up @@ -1859,7 +1859,7 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
cvt->len_ratio = (double)cvt->len_mult / (double)cvt->len_div;
cvt->filters[cvt->filter_index++] = SDL_Resample;
//SDL_BuildIIRLowpass(cvt, dst_fmt);
SDL_BuildWindowedSinc(cvt, dst_fmt, 12);
SDL_BuildWindowedSinc(cvt, dst_fmt, 20);

/*cvt->rate_incr = 0.0;
if ((src_rate / 100) != (dst_rate / 100)) {
Expand Down

0 comments on commit b96e3dd

Please sign in to comment.