File: impulsegen.c

package info (click to toggle)
gbsplay 0.0.93-3
  • links: PTS
  • area: main
  • in suites: buster
  • size: 488 kB
  • sloc: ansic: 5,581; sh: 861; makefile: 358
file content (72 lines) | stat: -rw-r--r-- 1,382 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
 * gbsplay is a Gameboy sound player
 *
 * 2003-2006 (C) by Tobias Diedrich <ranma+gbsplay@tdiedrich.de>
 * Licensed under GNU GPL.
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "impulsegen.h"

static double sinc(double x)
{
	double a = M_PI*x;

	if (a == 0.0) return 1.0;

	return sin(a)/a;
}

static double blackman(double n, double m)
{
	return 0.42 - 0.5 * cos(2*n*M_PI/m) + 0.08 * cos(4*n*M_PI/m);
}

short *gen_impulsetab(long w_shift, long n_shift, double cutoff)
{
	long i;
	double j;
	long width = 1 << w_shift;
	long n = 1 << n_shift;
	long m = width/2;
	long size = width*n*sizeof(short);
	short *pulsetab = malloc(size);
	short *ptr = pulsetab;

	if (!pulsetab)
		return NULL;

	for (j=0; j<1.0; j+=1.0/n) {
		long sum=0;
		long corr;
		long n = 0;
		double div = IMPULSE_HEIGHT;
		double dcorr = cutoff;

		do {
			sum = 0;
			for (i=-m+1; i<=m; i++) {
				double xd = dcorr*IMPULSE_HEIGHT*sinc((i-j)*cutoff)*blackman(i-j+width/2,width);
				short x = rint(xd);
				sum += x;
			}
			corr = IMPULSE_HEIGHT - sum;
			dcorr *= 1.0 + corr / div;
			div *= 1.3;
		} while ((corr != 0) && (n++ < 20));

		sum = 0;
		for (i=-m+1; i<=m; i++) {
			double xd = dcorr*IMPULSE_HEIGHT*sinc((i-j)*cutoff)*blackman(i-j+width/2,width);
			short x = rint(xd);
			*(ptr++) = x;
			sum += x;
		}
		*(ptr - m) += IMPULSE_HEIGHT - sum;
	}

	return pulsetab;
}