1 #ifndef CYD_H
2 #define CYD_H
3 
4 /*
5 Copyright (c) 2009-2010 Tero Lindeman (kometbomb)
6 
7 Permission is hereby granted, free of charge, to any person
8 obtaining a copy of this software and associated documentation
9 files (the "Software"), to deal in the Software without
10 restriction, including without limitation the rights to use,
11 copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the
13 Software is furnished to do so, subject to the following
14 conditions:
15 
16 The above copyright notice and this permission notice shall be
17 included in all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 OTHER DEALINGS IN THE SOFTWARE.
27 */
28 
29 #include <signal.h>
30 #include "cydtypes.h"
31 #include "cydflt.h"
32 #include "cydfx.h"
33 #include "cydentry.h"
34 #include "cyddefs.h"
35 #include "cydadsr.h"
36 #include "cydfm.h"
37 #include "cydwave.h"
38 
39 typedef struct
40 {
41 	Uint32 frequency;
42 	Uint32 accumulator;
43 	Uint32 random; // random lfsr
44 	Uint32 lfsr, lfsr_period, lfsr_ctr, lfsr_acc; // lfsr state
45 	Uint32 reg4, reg5, reg9; // "pokey" lfsr registers
46 	CydWaveState wave;
47 } CydOscState;
48 
49 typedef struct
50 {
51 	// ---- interface
52 	Uint32 flags;
53 	Uint16 pw; // 0-2047
54 	Uint8 sync_source, ring_mod; // channel
55 	Uint8 flttype;
56 	CydAdsr adsr;
57 	Uint8 ym_env_shape;
58 #ifdef STEREOOUTPUT
59 	Uint8 panning; // 0-128, 64 = center
60 	Sint32 gain_left, gain_right;
61 #endif
62 	// ---- internal
63 	Uint32 sync_bit;
64 	Uint32 lfsr_type;
65 	const CydWavetableEntry *wave_entry;
66 	CydOscState subosc[CYD_SUB_OSCS];
67 	CydFilter flt;
68 	int fx_bus;
69 #ifndef CYD_DISABLE_FM
70 	CydFm fm;
71 #endif
72 } CydChannel;
73 
74 enum
75 {
76 	FLT_LP,
77 	FLT_HP,
78 	FLT_BP,
79 	FLT_TYPES
80 };
81 
82 enum
83 {
84 	CYD_CHN_ENABLE_NOISE = 1,
85 	CYD_CHN_ENABLE_PULSE = 2,
86 	CYD_CHN_ENABLE_TRIANGLE = 4,
87 	CYD_CHN_ENABLE_SAW = 8,
88 	CYD_CHN_ENABLE_SYNC = 16,
89 	CYD_CHN_ENABLE_GATE = 32,
90 	CYD_CHN_ENABLE_KEY_SYNC = 64,
91 	CYD_CHN_ENABLE_METAL = 128,
92 	CYD_CHN_ENABLE_RING_MODULATION = 256,
93 	CYD_CHN_ENABLE_FILTER = 512,
94 	CYD_CHN_ENABLE_FX = 1024,
95 	CYD_CHN_ENABLE_YM_ENV = 2048,
96 	CYD_CHN_ENABLE_WAVE = 4096,
97 	CYD_CHN_WAVE_OVERRIDE_ENV = 8192,
98 	CYD_CHN_ENABLE_LFSR = 16384,
99 	CYD_CHN_ENABLE_FM = 32768
100 };
101 
102 enum
103 {
104 	CYD_FM_ENABLE_WAVE = CYD_CHN_ENABLE_WAVE,
105 	CYD_FM_ENABLE_TRIANGLE = CYD_CHN_ENABLE_TRIANGLE,
106 	CYD_FM_ENABLE_PULSE = CYD_CHN_ENABLE_PULSE,
107 	CYD_FM_ENABLE_SAW = CYD_CHN_ENABLE_SAW
108 };
109 
110 enum {
111 	ATTACK,
112 	DECAY,
113 	SUSTAIN,
114 	RELEASE,
115 	DONE
116 };
117 
118 enum
119 {
120 	CYD_LOCK_REQUEST=1,
121 	CYD_LOCK_LOCKED=2,
122 	CYD_LOCK_CALLBACK=4
123 
124 };
125 
126 #define WAVEFORMS (CYD_CHN_ENABLE_NOISE|CYD_CHN_ENABLE_PULSE|CYD_CHN_ENABLE_TRIANGLE|CYD_CHN_ENABLE_SAW|CYD_CHN_ENABLE_WAVE|CYD_CHN_ENABLE_LFSR)
127 
128 #define LUT_SIZE 1024
129 #define YM_LUT_SIZE 16
130 
131 #define CYD_NUM_WO_BUFFER_SIZE 2000
132 #define CYD_NUM_WO_BUFFERS 4
133 
134 #define CYD_NUM_LFSR 16
135 
136 typedef struct CydEngine_t
137 {
138 	CydChannel *channel;
139 	int n_channels;
140 	Uint32 sample_rate;
141 	// ----- internal
142 	volatile Uint32 flags;
143 	int (*callback)(void*);
144 	void *callback_parameter;
145 	volatile Uint32 callback_period, callback_counter;
146 	Uint16 *lookup_table, *lookup_table_ym;
147 	CydFx fx[CYD_MAX_FX_CHANNELS];
148 #ifdef USESDLMUTEXES
149 	CydMutex mutex;
150 #else
151 	volatile sig_atomic_t lock_request;
152 	volatile sig_atomic_t lock_locked;
153 #endif
154 	size_t samples_output; // bytes in last cyd_output_buffer
155 	CydWavetableEntry *wavetable_entries;
156 #ifdef USENATIVEAPIS
157 # ifdef WIN32
158 	BOOL thread_running;
159 	DWORD thread_handle, cb_handle;
160 	CRITICAL_SECTION thread_lock;
161 	int buffers_available;
162 	int waveout_hdr_idx;
163 	HWAVEOUT hWaveOut;
164 	WAVEHDR waveout_hdr[CYD_NUM_WO_BUFFERS];
165 # endif
166 #endif
167 	Uint64 samples_played;
168 	int oversample;
169 } CydEngine;
170 
171 enum
172 {
173 	CYD_PAUSED = 1,
174 	CYD_CLIPPING = 2,
175 	CYD_SINGLE_THREAD = 8,
176 };
177 
178 // YM2149 envelope shape flags, CONT is assumed to be always set
179 
180 enum { CYD_YM_ENV_ATT = 1, CYD_YM_ENV_ALT = 2};
181 
182 /////////////////777
183 
184 void cyd_init(CydEngine *cyd, Uint16 sample_rate, int initial_channels);
185 void cyd_set_oversampling(CydEngine *cyd, int oversampling);
186 void cyd_reserve_channels(CydEngine *cyd, int channels);
187 void cyd_deinit(CydEngine *cyd);
188 void cyd_reset(CydEngine *cyd);
189 void cyd_set_frequency(CydEngine *cyd, CydChannel *chn, int subosc, Uint16 frequency);
190 void cyd_set_wavetable_frequency(CydEngine *cyd, CydChannel *chn, int subosc, Uint16 frequency);
191 void cyd_reset_wavetable(CydEngine *cyd);
192 void cyd_set_wavetable_offset(CydChannel *chn, Uint16 offset /* 0..0x1000 = 0-100% */);
193 void cyd_set_env_frequency(CydEngine *cyd, CydChannel *chn, Uint16 frequency);
194 void cyd_set_env_shape(CydChannel *chn, Uint8 shape);
195 void cyd_enable_gate(CydEngine *cyd, CydChannel *chn, Uint8 enable);
196 void cyd_set_waveform(CydChannel *chn, Uint32 wave);
197 void cyd_set_wave_entry(CydChannel *chn, const CydWavetableEntry * entry);
198 void cyd_set_filter_coeffs(CydEngine * cyd, CydChannel *chn, Uint16 cutoff, Uint8 resonance);
199 void cyd_pause(CydEngine *cyd, Uint8 enable);
200 void cyd_set_callback(CydEngine *cyd, int (*callback)(void*), void*param, Uint16 period);
201 void cyd_set_callback_rate(CydEngine *cyd, Uint16 period);
202 #ifdef NOSDL_MIXER
203 int cyd_register(CydEngine * cyd, int buffer_length);
204 #else
205 int cyd_register(CydEngine * cyd);
206 #endif
207 int cyd_unregister(CydEngine * cyd);
208 void cyd_lock(CydEngine *cyd, Uint8 enable);
209 #ifdef ENABLEAUDIODUMP
210 void cyd_enable_audio_dump(CydEngine *cyd);
211 void cyd_disable_audio_dump(CydEngine *cyd);
212 #endif
213 #ifdef STEREOOUTPUT
214 void cyd_set_panning(CydEngine *cyd, CydChannel *chn, Uint8 panning);
215 #endif
216 
217 #ifdef NOSDL_MIXER
218 void cyd_output_buffer_stereo(void *udata, Uint8 *_stream, int len);
219 #else
220 void cyd_output_buffer_stereo(int chan, void *_stream, int len, void *udata);
221 #endif
222 
223 Sint32 cyd_env_output(const CydEngine *cyd, Uint32 channel_flags, const CydAdsr *adsr, Sint32 input);
224 Uint32 cyd_cycle_adsr(const CydEngine *eng, Uint32 flags, Uint32 ym_env_shape, CydAdsr *adsr);
225 
226 #endif
227