sunvox_sys/lib.rs
1//! # sunvox-sys
2//!
3//! FFI bindings to the Sunvox library (http://warmplace.ru/soft/sunvox).
4
5
6// --- Crate attributes --- //
7#![allow(non_camel_case_types)]
8// --- ==== --- //
9
10
11// --- External crates --- //
12extern crate libc;
13// --- ==== --- //
14
15
16// --- Use --- //
17use libc::{c_void, c_int, c_uint, c_char, c_uchar, c_short, c_ushort};
18// --- ==== --- //
19
20
21/// Single note off.
22pub const NOTECMD_NOTE_OFF: c_int = 128;
23
24/// Notes of all synths off.
25pub const NOTECMD_ALL_NOTES_OFF: c_int = 129;
26
27/// Stop and clean all synths.
28pub const NOTECMD_CLEAN_SYNTHS: c_int = 130;
29
30pub const NOTECMD_STOP: c_int = 131;
31pub const NOTECMD_PLAY: c_int = 132;
32
33// I can't find these in the official header file, but they're defined in
34// https://github.com/metrasynth/sunvox-dll-python/blob/master/sunvox/types.py
35/// Change the pitch of a currently playing note.
36pub const NOTECMD_SET_PITCH: c_int = 133;
37
38/// Apply effect in this note cell to the corresponding one in the previous track.
39pub const NOTECMD_PREV_TRACK: c_int = 134;
40
41
42/// A single note cell in a pattern.
43#[repr(C)]
44#[derive(Clone, Debug)]
45pub struct sunvox_note {
46 /// The note column.
47 ///
48 /// - 0: Nothing.
49 /// - 1 to 127 inclusive: A normal note.
50 /// - 128+: See the `NOTECMD` constants.
51 pub note: c_uchar,
52
53 /// The velocity column (note velocity).
54 ///
55 /// - 0: Empty (default).
56 /// - 1 to 129 inclusive: The specified velocity + 1.
57 pub vel: c_uchar,
58
59 /// The module column (module to affect).
60 ///
61 /// - 0: Empty (none).
62 /// - 1 to 255 inclusive: The specified module + 1.
63 pub module: c_uchar,
64
65 /// Padding.
66 pub nothing: c_uchar,
67
68 /// The value of the controller/effect column.
69 ///
70 /// Interpreted as a hexadecimal number, the first two digits are the
71 /// controller of the selected module to affect, and the last two digits
72 /// are the number of an effect. Set a pair of digits to zero to
73 /// ignore that part.
74 pub ctl: c_ushort,
75
76 /// The value of the controller/effect parameter column.
77 pub ctl_val: c_ushort,
78}
79
80
81/// Supresses debug output from the SunVox library.
82pub const SV_INIT_FLAG_NO_DEBUG_OUTPUT: c_uint = 1 << 0;
83
84/// Interaction with sound card is on the user side.
85///
86/// See `sv_audio_callback()`.
87pub const SV_INIT_FLAG_USER_AUDIO_CALLBACK: c_uint = 1 << 1;
88
89/// Audio is signed 16-bit (`c_short`).
90pub const SV_INIT_FLAG_AUDIO_INT16: c_uint = 1 << 2;
91
92/// Audio is float (`c_float`).
93pub const SV_INIT_FLAG_AUDIO_FLOAT32: c_uint = 1 << 3;
94
95/// Audio callback and song modification functions are in a single thread.
96pub const SV_INIT_FLAG_ONE_THREAD: c_uint = 1 << 4;
97
98
99pub const SV_MODULE_FLAG_EXISTS: c_int = 1;
100pub const SV_MODULE_FLAG_EFFECT: c_int = 2;
101pub const SV_MODULE_INPUTS_OFF: c_int = 16;
102pub const SV_MODULE_INPUTS_MASK: c_int = 255 << SV_MODULE_INPUTS_OFF;
103pub const SV_MODULE_OUTPUTS_OFF: c_int = 16 + 8;
104pub const SV_MODULE_OUTPUTS_MASK: c_int = 255 << SV_MODULE_OUTPUTS_OFF;
105
106
107pub const SV_STYPE_INT16: c_int = 0;
108pub const SV_STYPE_INT32: c_int = 1;
109pub const SV_STYPE_FLOAT32: c_int = 2;
110pub const SV_STYPE_FLOAT64: c_int = 3;
111
112
113#[link(name = "sunvox")]
114extern "C" {
115 /// Gets the next piece of SunVox audio.
116 ///
117 /// With `sv_audio_callback()` you can ignore the built-in SunVox sound
118 /// output mechanism and use some other sound system. Set the
119 /// `SV_INIT_FLAG_USER_AUDIO_CALLBACK` flag when calling `sv_init()` if
120 /// you want to use this function.
121 ///
122 /// # Parameters
123 ///
124 /// - buf: Destination buffer. If `SV_INIT_FLAG_AUDIO_INT16` was passed to
125 /// `sv_init()`, this is a buffer of `c_short`s. If `SV_INIT_FLAG_AUDIO_FLOAT32`
126 /// was passed, this is a buffer of `c_float`s. Stereo data will be interleaved
127 /// in this buffer: LRLR... ; where the LR is one frame (Left+Right channels).
128 /// - frames: Number of frames in destination buffer.
129 /// - latency: Audio latency (in frames).
130 /// - out_time: Output time (in ticks).
131 ///
132 /// The `out_time` parameter is elaborated on a little bit in this thread:
133 /// http://www.warmplace.ru/forum/viewtopic.php?f=12&t=4152
134 ///
135 /// For normal use, pass the value of `sv_get_ticks()`, as detailed in that
136 /// thread.
137 pub fn sv_audio_callback(buf: *mut c_void,
138 frames: c_int,
139 latency: c_int,
140 out_time: c_uint)
141 -> c_int;
142
143
144 /// Opens a slot.
145 ///
146 /// A slot is like an instance of the SunVox engine. Each slot can have a
147 /// single project loaded at a time. The library supports up to four slots,
148 /// 0 to 3 inclusive. This call appears to hang if called with a number
149 /// outside this range.
150 ///
151 /// Returns 0 on success, -1 on failure. Failure conditions include the
152 /// slot already being open.
153 ///
154 /// I say "like" an instance of the engine because I think all slots share
155 /// the same tick counter, which you can get by calling `sv_get_ticks()`.
156 pub fn sv_open_slot(slot: c_int) -> c_int;
157
158 /// Closes a slot. See `sv_open_slot()` for more details.
159 pub fn sv_close_slot(slot: c_int) -> c_int;
160
161 /// Locks a slot.
162 ///
163 /// There are a few functions that need to be called between a
164 /// `sv_lock_slot()`/`sv_unlock_slot()` pair. These are marked with
165 /// "USE LOCK/UNLOCK!".
166 pub fn sv_lock_slot(slot: c_int) -> c_int;
167
168 /// Unlocks a slot. See `sv_lock_slot()` for more details.
169 pub fn sv_unlock_slot(slot: c_int) -> c_int;
170
171
172 /// Initializes the library.
173 ///
174 /// The `flags` parameter takes either zero (for default options), or a
175 /// number of `SV_INIT_FLAG_xxx` constants ORed together.
176 pub fn sv_init(dev: *const c_char, freq: c_int, channels: c_int, flags: c_uint) -> c_int;
177
178 /// Deinitializes the library.
179 pub fn sv_deinit() -> c_int;
180
181
182 /// Gets the internal sample type of the SunVox engine.
183 ///
184 /// Returns one of the `SV_STYPE_xxx` constants.
185 ///
186 /// Use it to get the scope buffer type from `get_module_scope()` function.
187 pub fn sv_get_sample_type() -> c_int;
188
189
190 /// Loads a SunVox project file into the specified slot.
191 pub fn sv_load(slot: c_int, name: *const c_char) -> c_int;
192
193 /// Loads a SunVox project from file data in memory. TEST
194 pub fn sv_load_from_memory(slot: c_int, data: *mut c_void, data_size: c_uint) -> c_int;
195
196
197 /// Starts playing the project from the current play cursor position.
198 pub fn sv_play(slot: c_int) -> c_int;
199
200 /// Starts playing the project from the beginning.
201 pub fn sv_play_from_beginning(slot: c_int) -> c_int;
202
203 /// Stops playing the project. The play cursor stays where it is.
204 pub fn sv_stop(slot: c_int) -> c_int;
205
206 /// Enables or disables autostop.
207 ///
208 /// - 0: Disable autostop.
209 /// - 1: Enable autostop.
210 ///
211 /// When disabled, the project plays in a loop.
212 pub fn sv_set_autostop(slot: c_int, autostop: c_int) -> c_int;
213
214
215 /// Gets whether the project is stopped (ie. not playing).
216 ///
217 /// Returns 0 if it is playing, 1 if it is stopped.
218 pub fn sv_end_of_song(slot: c_int) -> c_int;
219
220
221 /// Rewinds the project to the beginning.
222 pub fn sv_rewind(slot: c_int, line_num: c_int) -> c_int;
223
224
225 /// Sets the volume of the project.
226 pub fn sv_volume(slot: c_int, vol: c_int) -> c_int;
227
228
229 /// Causes an event to occur as though it had been played in a pattern.
230 ///
231 /// `track_num` is in the range 0 to 15 inclusive, and refers to the track
232 /// number in a special hidden pattern.
233 pub fn sv_send_event(slot: c_int,
234 track_num: c_int,
235 note: c_int,
236 vel: c_int,
237 module: c_int,
238 ctl: c_int,
239 ctl_val: c_int)
240 -> c_int;
241
242
243 /// Gets the line number of the play cursor.
244 pub fn sv_get_current_line(slot: c_int) -> c_int;
245
246 /// Gets the line number of the play in fixed point format: 27.5
247 ///
248 /// TODO: Figure out exactly what this means.
249 /// I'm guessing it means 27 bits for the integer part and 5 bits for the
250 /// fractional part.
251 pub fn sv_get_current_line2(slot: c_int) -> c_int;
252
253
254 /// Gets the current signal level/amplitude for a given audio channel
255 /// in the range 0 to 255 inclusive.
256 pub fn sv_get_current_signal_level(slot: c_int, channel: c_int) -> c_int;
257
258
259 /// Gets the name of the currently loaded project.
260 ///
261 /// Returns NULL if no project is loaded.
262 pub fn sv_get_song_name(slot: c_int) -> *const c_char;
263
264
265 /// Gets the Beats Per Minute of the currently loaded project.
266 ///
267 /// Returns zero if no project is loaded.
268 pub fn sv_get_song_bpm(slot: c_int) -> c_int;
269
270
271 /// Gets the Ticks Per Line of the currently loaded project.
272 ///
273 /// Returns zero if no project is loaded.
274 pub fn sv_get_song_tpl(slot: c_int) -> c_int;
275
276
277 /// Gets the currently loaded song's length in audio samples/frames.
278 pub fn sv_get_song_length_frames(slot: c_int) -> c_uint;
279
280 /// Gets the currently loaded song's length in pattern lines.
281 pub fn sv_get_song_length_lines(slot: c_int) -> c_uint;
282
283
284 /// Creates a new module. USE LOCK/UNLOCK!
285 pub fn sv_new_module(slot: c_int,
286 _type: *const c_char,
287 name: *const c_char,
288 x: c_int,
289 y: c_int,
290 z: c_int)
291 -> c_int;
292
293 /// Removes the specified module. USE LOCK/UNLOCK!
294 pub fn sv_remove_module(slot: c_int, mod_num: c_int) -> c_int;
295
296 /// Connects the source to the destination. USE LOCK/UNLOCK!
297 pub fn sv_connect_module(slot: c_int, source: c_int, destination: c_int) -> c_int;
298
299 /// Disconnects the source from the destination. USE LOCK/UNLOCK!
300 pub fn sv_disconnect_module(slot: c_int, source: c_int, destination: c_int) -> c_int;
301
302 /// Loads a module.
303 ///
304 /// Supported file formats: `sunsynth`, `xi`, `wav`, `aiff`
305 pub fn sv_load_module(slot: c_int,
306 file_name: *const c_char,
307 x: c_int,
308 y: c_int,
309 z: c_int)
310 -> c_int;
311
312 /// Loads a sample to an existing Sampler.
313 ///
314 /// To replace the whole sampler, set `sample_slot` to -1.
315 pub fn sv_sampler_load(slot: c_int,
316 sampler_module: c_int,
317 file_name: *const c_char,
318 sample_slot: c_int)
319 -> c_int;
320
321
322 /// Gets the number of modules in the currently loaded project?
323 ///
324 /// Does not seem to directly correspond to that.
325 /// TODO: Investigate this.
326 ///
327 /// Returns zero if no project is loaded.
328 pub fn sv_get_number_of_modules(slot: c_int) -> c_int;
329
330
331 pub fn sv_get_module_flags(slot: c_int, mod_num: c_int) -> c_uint;
332 pub fn sv_get_module_inputs(slot: c_int, mod_num: c_int) -> *mut c_int;
333 pub fn sv_get_module_outputs(slot: c_int, mod_num: c_int) -> *mut c_int;
334 pub fn sv_get_module_name(slot: c_int, mod_num: c_int) -> *const c_char;
335 pub fn sv_get_module_xy(slot: c_int, mod_num: c_int) -> c_uint;
336 pub fn sv_get_module_color(slot: c_int, mod_num: c_int) -> c_int;
337 pub fn sv_get_module_scope(slot: c_int,
338 mod_num: c_int,
339 channel: c_int,
340 buffer_offset: *mut c_int,
341 buffer_size: *mut c_int)
342 -> *mut c_void;
343
344 /// Return value: received number of samples (may be less or equal to `samples_to_read`).
345 pub fn sv_get_module_scope2(slot: c_int,
346 mod_num: c_int,
347 channel: c_int,
348 read_buf: *mut c_short,
349 samples_to_read: c_uint)
350 -> c_uint;
351
352 pub fn sv_get_number_of_module_ctls(slot: c_int, mod_num: c_int) -> c_int;
353 pub fn sv_get_module_ctl_name(slot: c_int, mod_num: c_int, ctl_num: c_int) -> *const c_char;
354 pub fn sv_get_module_ctl_value(slot: c_int,
355 mod_num: c_int,
356 ctl_num: c_int,
357 scaled: c_int)
358 -> c_int;
359
360
361 pub fn sv_get_number_of_patterns(slot: c_int) -> c_int;
362 pub fn sv_get_pattern_x(slot: c_int, pat_num: c_int) -> c_int;
363 pub fn sv_get_pattern_y(slot: c_int, pat_num: c_int) -> c_int;
364 pub fn sv_get_pattern_tracks(slot: c_int, pat_num: c_int) -> c_int;
365 pub fn sv_get_pattern_lines(slot: c_int, pat_num: c_int) -> c_int;
366
367
368 /// How to use sv_get_pattern_data():
369 ///
370 /// - `int pat_tracks = sv_get_pattern_tracks(slot, pat_num);`
371 /// - `sunvox_note* data = sv_get_pattern_data(slot, pat_num);`
372 /// - `sunvox_note* n = &data[ line_number * pat_tracks + track_number ];`
373 /// - ... and then do someting with note n
374 pub fn sv_get_pattern_data(slot: c_int, pat_num: c_int) -> *mut sunvox_note;
375
376
377 /// USE LOCK/UNLOCK!
378 pub fn sv_pattern_mute(slot: c_int, pat_num: c_int, mute: c_int) -> c_int;
379
380
381 /// Gets the current tick counter (from 0 to 0xFFFFFFFF).
382 ///
383 /// SunVox engine uses its own time space, measured in ticks.
384 pub fn sv_get_ticks() -> c_uint;
385
386 /// Gets the number of SunVox ticks per second.
387 pub fn sv_get_ticks_per_second() -> c_uint;
388}