-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathnewsnd.c
161 lines (131 loc) · 3.92 KB
/
newsnd.c
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* Digger Remastered
Copyright (c) Andrew Jenner 1998-2004 */
#include <stdlib.h>
#include "def.h"
#include "device.h"
#include "hardware.h"
#include "digger.h"
#if !defined(newsnd_test)
#include "sound.h"
#endif
#include "newsnd.h"
#define PIT_FREQ 0x1234ddul
/* The function which empties the circular buffer should get samples from
buffer[firsts] and then do firsts=(firsts+1)&(size-1); This function is
responsible for incrementing first samprate times per second (on average)
(if it's a little out, the sound will simply run too fast or too slow). It
must not take more than (last-firsts-1)&(size-1) samples at once, or the
sound will break up.
If DMA is used, doubling the buffer so the data is always continguous, and
giving half of the buffer at once to the DMA driver may be a good idea. */
static uint16_t t0rate;
#if !defined(newsnd_test)
extern int16_t spkrmode,pulsewidth;
#else
static int16_t spkrmode=0,pulsewidth=1;
#endif
/* Initialise circular buffer and PC speaker emulator
bufsize = buffer size in samples
samprate = play rate in Hz
samprate is directly proportional to the sound quality. This should be the
highest value the hardware can support without slowing down the program too
much. Ensure 0x1234<samprate<=0x1234dd and that samprate is a factor of
0x1234dd (or you won't get the rate you want). For example, a value of
44100 equates to about 44192Hz (a .2% difference - negligable unless you're
trying to harmonize with a computer running at a different rate, or another
musical instrument...)
The lag time is bufsize/samprate seconds. This should be the smallest value
which does not make the sound break up. There may also be DMA considerations
to take into account. bufsize should also be a power of 2.
*/
#include <assert.h>
#include <math.h>
#include "soundgen.h"
static struct sgen_state *ssp;
static unsigned int intmod;
int16_t getsample(void)
{
if ((sgen_getstep(ssp) + 1) % intmod == 0)
soundint();
return (sgen_getsample(ssp));
}
void soundinitglob(uint16_t bufsize,uint16_t samprate)
{
ssp = sgen_ctor(samprate, 2);
assert(ssp != NULL);
intmod = round(samprate / 72.8);
#if !defined(newsnd_test)
setsounddevice(samprate,bufsize);
#endif
}
void s1setupsound(void)
{
#if !defined(newsnd_test)
inittimer();
soundint();
initsounddevice();
#endif
}
void s1killsound(void)
{
#if !defined(newsnd_test)
setsoundt2();
timer2(40, false);
pausesounddevice(true);
#endif
}
/* WARNING: Read only code ahead. Unless you're seriously into how the PC
speaker and Digger's original low-level sound routines work, you shouldn't
try to mess with, or even understand, the following. I don't understand most
of it myself, and I wrote it. */
#define T0_BND 0
#define T2_BND 1
void s1timer2(uint16_t t2, bool mode)
{
double rphase;
if (t2 > 40 && t2 < 0x4000) {
rphase = sgen_getphase(ssp, T2_BND);
if (!mode) {
sgen_setband(ssp, T2_BND, PIT_FREQ / t2, 1.0);
} else {
double frq;
frq = (double)(PIT_FREQ / t2) - (double)(PIT_FREQ / t0rate);
sgen_setband_mod(ssp, T2_BND, frq, 1.0, 0.0);
if (sgen_setmuteband(ssp, T2_BND, 0))
rphase = 0.0;
}
sgen_setphase(ssp, T2_BND, rphase);
} else {
sgen_setband(ssp, T2_BND, 0.0, 0.0);
}
}
void s1soundoff(void)
{
sgen_setmuteband(ssp, 0, 1);
sgen_setmuteband(ssp, 1, 1);
}
void s1setspkrt2(void)
{
if (spkrmode == 0) {
sgen_setmuteband(ssp, 0, 1);
sgen_setmuteband(ssp, 1, 0);
} else if (spkrmode == 1) {
sgen_setmuteband(ssp, 0, 0);
sgen_setmuteband(ssp, 1, 1);
} else {
sgen_setmuteband(ssp, 0, 1);
sgen_setmuteband(ssp, 1, 1);
}
}
void s1timer0(uint16_t t0)
{
double rphase;
if (t0 > 40 && t0 < 0x4000) {
rphase = sgen_getphase(ssp, 0);
sgen_setband(ssp, 0, PIT_FREQ / t0, (pulsewidth - 1) / 49.0);
sgen_setphase(ssp, 0, rphase);
} else {
sgen_setband(ssp, 0, 0.0, 0.0);
}
t0rate=t0;
}