1use std::alloc::{self, Layout, LayoutError};
2use std::os::raw::{c_char, c_void};
3
4pub type BYTE = u8;
5pub type WORD = u16;
6pub type DWORD = u32;
7pub type QWORD = u64;
8pub type BOOL = i32;
9
10pub type HMUSIC = DWORD;
11pub type HSAMPLE = DWORD;
12pub type HCHANNEL = DWORD;
13pub type HSTREAM = DWORD;
14pub type HRECORD = DWORD;
15pub type HSYNC = DWORD;
16pub type HDSP = DWORD;
17pub type HFX = DWORD;
18pub type HPLUGIN = DWORD;
19
20pub type STREAMPROC = extern "C" fn(HSTREAM, *mut c_void, DWORD, *mut c_void) -> DWORD;
21pub type FILECLOSEPROC = extern "C" fn(*mut c_void);
22pub type FILELENPROC = extern "C" fn(*mut c_void) -> QWORD;
23pub type FILEREADPROC = extern "C" fn(*mut c_void, DWORD, *mut c_void) -> DWORD;
24pub type FILESEEKPROC = extern "C" fn(QWORD, *mut c_void) -> BOOL;
25pub type DOWNLOADPROC = extern "C" fn(*mut c_void, DWORD, *mut c_void);
26pub type SYNCPROC = extern "C" fn(HSYNC, DWORD, DWORD, *mut c_void);
27pub type DSPPROC = extern "C" fn(HDSP, DWORD, *mut c_void, DWORD, *mut c_void);
28pub type RECORDPROC = extern "C" fn(HRECORD, *mut c_void, DWORD, *mut c_void) -> BOOL;
29pub type IOSNOTIFYPROC = extern "C" fn(DWORD);
30
31#[repr(C)]
32#[derive(Debug, Clone)]
33pub struct BassDeviceInfo {
34    pub name: *const c_void,
35    pub driver: *const c_void,
36    pub flags: DWORD,
37}
38
39impl BassDeviceInfo {
40    pub fn new(name: *const c_void, driver: *const c_void, flags: DWORD) -> Self {
41        Self {
42            name,
43            driver,
44            flags,
45        }
46    }
47}
48
49#[repr(C)]
50#[derive(Default, Debug, Clone)]
51pub struct BassInfo {
52    pub flags: DWORD,
53    pub size_of_hardware_memory: DWORD,
54    pub size_of_free_hardware_memory: DWORD,
55    pub free_samples: DWORD,
56    pub free_3d_sample_slots: DWORD,
57    pub minimum_sample_rate: DWORD,
58    pub maxiumum_sample_rate: DWORD,
59    pub eax_support: BOOL,
60    pub minimum_buffer_length: DWORD,
61    pub direct_sound_version: DWORD,
62    pub latency: DWORD,
63    pub init_flags: DWORD,
64    pub speakers: DWORD,
65    pub output_frequency: DWORD,
66}
67
68impl BassInfo {
69    pub fn new(
70        flags: DWORD,
71        size_of_hardware_memory: DWORD,
72        size_of_free_hardware_memory: DWORD,
73        free_samples: DWORD,
74        free_3d_sample_slots: DWORD,
75        minimum_sample_rate: DWORD,
76        maxiumum_sample_rate: DWORD,
77        eax_support: BOOL,
78        minimum_buffer_length: DWORD,
79        direct_sound_version: DWORD,
80        latency: DWORD,
81        init_flags: DWORD,
82        speakers: DWORD,
83        output_frequency: DWORD,
84    ) -> Self {
85        Self {
86            flags,
87            size_of_hardware_memory,
88            size_of_free_hardware_memory,
89            free_samples,
90            free_3d_sample_slots,
91            minimum_sample_rate,
92            maxiumum_sample_rate,
93            eax_support,
94            minimum_buffer_length,
95            direct_sound_version,
96            latency,
97            init_flags,
98            speakers,
99            output_frequency,
100        }
101    }
102}
103
104#[repr(C)]
105#[derive(Default, Debug, Clone)]
106pub struct BassRecordInfo {
107    pub flags: DWORD,
108    pub supported_formats: DWORD,
109    pub number_of_inputs: DWORD,
110    pub single_in: BOOL,
111    pub current_frequency: DWORD,
112}
113
114impl BassRecordInfo {
115    pub fn new(
116        flags: DWORD,
117        supported_formats: DWORD,
118        number_of_inputs: DWORD,
119        single_in: BOOL,
120        current_frequency: DWORD,
121    ) -> Self {
122        Self {
123            flags,
124            supported_formats,
125            number_of_inputs,
126            single_in,
127            current_frequency,
128        }
129    }
130}
131
132#[repr(C)]
133#[derive(Default, Debug, Clone)]
134pub struct BassSample {
135    pub default_frequency: DWORD,
136    pub volume: f32,
137    pub pan: f32,
138    pub flags: DWORD,
139    pub length: DWORD,
140    pub maximum_simultaneous_playbacks: DWORD,
141    pub original_resolution: DWORD,
142    pub number_of_channels: DWORD,
143    pub minimum_gap: DWORD,
144    pub mode_3d: DWORD,
145    pub minimum_distance: f32,
146    pub maximum_distance: f32,
147    pub angle_of_inside_projection_cone: DWORD,
148    pub angle_of_outside_projection_cone: DWORD,
149    pub volume_delta_of_outside_projection_cone: f32,
150    pub voice_allocation_flags: DWORD,
151    pub priority: DWORD,
152}
153
154impl BassSample {
155    pub fn new(
156        default_frequency: DWORD,
157        volume: f32,
158        pan: f32,
159        flags: DWORD,
160        length: DWORD,
161        maximum_simultaneous_playbacks: DWORD,
162        original_resolution: DWORD,
163        number_of_channels: DWORD,
164        minimum_gap: DWORD,
165        mode_3d: DWORD,
166        minimum_distance: f32,
167        maximum_distance: f32,
168        angle_of_inside_projection_cone: DWORD,
169        angle_of_outside_projection_cone: DWORD,
170        volume_delta_of_outside_projection_cone: f32,
171        voice_allocation_flags: DWORD,
172        priority: DWORD,
173    ) -> Self {
174        Self {
175            default_frequency,
176            volume,
177            pan,
178            flags,
179            length,
180            maximum_simultaneous_playbacks,
181            original_resolution,
182            number_of_channels,
183            minimum_gap,
184            mode_3d,
185            minimum_distance,
186            maximum_distance,
187            angle_of_inside_projection_cone,
188            angle_of_outside_projection_cone,
189            volume_delta_of_outside_projection_cone,
190            voice_allocation_flags,
191            priority,
192        }
193    }
194}
195
196#[repr(C)]
197#[derive(Debug, Clone)]
198pub struct BassChannelInfo {
199    pub default_frequency: DWORD,
200    pub channels: DWORD,
201    pub flags: DWORD,
202    pub type_of_channel: DWORD,
203    pub original_resolution: DWORD,
204    pub plugin: HPLUGIN,
205    pub sample: HSAMPLE,
206    pub file_name: *const c_char,
207}
208
209impl BassChannelInfo {
210    pub fn new(
211        default_frequency: DWORD,
212        channels: DWORD,
213        flags: DWORD,
214        type_of_channel: DWORD,
215        original_resolution: DWORD,
216        plugin: HPLUGIN,
217        sample: HSAMPLE,
218        file_name: *const c_char,
219    ) -> Self {
220        Self {
221            default_frequency,
222            channels,
223            flags,
224            type_of_channel,
225            original_resolution,
226            plugin,
227            sample,
228            file_name,
229        }
230    }
231}
232
233#[repr(C)]
234#[derive(Debug, Clone)]
235pub struct BassPluginForm {
236    pub name: *const c_void,
237    pub file_extension_filter: *const c_void,
238}
239
240impl BassPluginForm {
241    pub fn new(name: *const c_void, file_extension_filter: *const c_void) -> Self {
242        Self {
243            name,
244            file_extension_filter,
245        }
246    }
247}
248
249#[repr(C)]
250#[derive(Debug, Clone)]
251pub struct BassPluginInfo {
252    pub version: DWORD,
253    pub format_count: DWORD,
254    pub formats: *mut BassPluginForm,
255}
256
257impl BassPluginInfo {
258    pub fn new(version: DWORD, format_count: DWORD, formats: *mut BassPluginForm) -> Self {
259        Self {
260            version,
261            format_count,
262            formats,
263        }
264    }
265}
266
267#[repr(C)]
268#[derive(Default, Debug, Clone)]
269pub struct Bass3DVector {
270    pub x: f32,
271    pub y: f32,
272    pub z: f32,
273}
274
275impl Bass3DVector {
276    pub fn new(x: f32, y: f32, z: f32) -> Self {
277        Self { x, y, z }
278    }
279}
280
281#[repr(C)]
282#[derive(Debug, Clone)]
283pub struct BassFileProcs {
284    pub close_handle: *mut FILECLOSEPROC,
285    pub length_handle: *mut FILELENPROC,
286    pub read_handle: *mut FILEREADPROC,
287    pub seek_handle: *mut FILESEEKPROC,
288}
289
290impl BassFileProcs {
291    pub fn new(
292        close_handle: *mut FILECLOSEPROC,
293        length_handle: *mut FILELENPROC,
294        read_handle: *mut FILEREADPROC,
295        seek_handle: *mut FILESEEKPROC,
296    ) -> Self {
297        Self {
298            close_handle,
299            length_handle,
300            read_handle,
301            seek_handle,
302        }
303    }
304}
305
306#[repr(C)]
307#[derive(Default, Debug, Clone)]
308pub struct TagId3 {
309    pub id: [c_char; 3],
310    pub title: [c_char; 30],
311    pub artist: [c_char; 30],
312    pub album: [c_char; 30],
313    pub year: [c_char; 4],
314    pub comment: [c_char; 30],
315    pub genre: BYTE,
316}
317
318impl TagId3 {
319    pub fn new(
320        id: [c_char; 3],
321        title: [c_char; 30],
322        artist: [c_char; 30],
323        album: [c_char; 30],
324        year: [c_char; 4],
325        comment: [c_char; 30],
326        genre: BYTE,
327    ) -> Self {
328        Self {
329            id,
330            title,
331            artist,
332            album,
333            year,
334            comment,
335            genre,
336        }
337    }
338}
339
340#[repr(C)]
341#[derive(Debug, Clone)]
342pub struct TagApeBinary {
343    pub key: *mut c_char,
344    pub data: *mut c_void,
345    pub length: DWORD,
346}
347
348impl TagApeBinary {
349    pub fn new(key: *mut c_char, data: *mut c_void, length: DWORD) -> Self {
350        Self { key, data, length }
351    }
352}
353
354#[repr(C, packed(1))]
355pub struct TagBext {
356    pub description: [c_char; 256],
357    pub originator: [c_char; 32],
358    pub originator_reference: [c_char; 32],
359    pub originator_date: [c_char; 10],
360    pub originator_time: [c_char; 8],
361    pub time_reference: QWORD,
362    pub version: WORD,
363    pub umid: [BYTE; 64],
364    pub reserved: [BYTE; 190],
365    pub coding_history: [c_char; 0],
366}
367
368impl TagBext {
369    pub fn new<T: AsRef<[c_char]>>(
370        description: [c_char; 256],
371        originator: [c_char; 32],
372        originator_reference: [c_char; 32],
373        originator_date: [c_char; 10],
374        originator_time: [c_char; 8],
375        time_reference: QWORD,
376        version: WORD,
377        umid: [BYTE; 64],
378        reserved: [BYTE; 190],
379        coding_history: &T,
380    ) -> Result<Box<Self>, LayoutError> {
381        let coding_history_layout = Layout::array::<c_char>(coding_history.as_ref().len())?;
382        let (tag_bext_layout, _) = Layout::new::<TagBext>()
383            .extend(coding_history_layout)?;
384        let tag_bext_layout = tag_bext_layout.pad_to_align();
385
386        let tag_bext = unsafe { alloc::alloc(tag_bext_layout) }.cast::<TagBext>();
387
388        if tag_bext.is_null() {
389            alloc::handle_alloc_error(tag_bext_layout);
390        }
391
392        unsafe {
393            (*tag_bext).description = description;
394            (*tag_bext).originator = originator;
395            (*tag_bext).originator_reference = originator_reference;
396            (*tag_bext).originator_date = originator_date;
397            (*tag_bext).originator_time = originator_time;
398            (*tag_bext).time_reference = time_reference;
399            (*tag_bext).version = version;
400            (*tag_bext).umid = umid;
401            (*tag_bext).reserved = reserved;
402        }
403
404        for (index, value) in coding_history.as_ref().iter().enumerate() {
405            unsafe { (*tag_bext).coding_history[index] = *value };
406        }
407
408        Ok(unsafe { Box::from_raw(tag_bext) })
409    }
410}
411
412#[repr(C)]
413#[derive(Default, Debug, Clone)]
414pub struct TagCartTimer {
415    pub timer_usage_id: DWORD,
416    pub timer_value: DWORD,
417}
418
419impl TagCartTimer {
420    pub fn new(timer_usage_id: DWORD, timer_value: DWORD) -> Self {
421        Self {
422            timer_usage_id,
423            timer_value,
424        }
425    }
426}
427
428#[repr(C)]
429#[derive(Debug, Clone)]
430pub struct TagCart {
431    pub version: [c_char; 4],
432    pub title: [c_char; 64],
433    pub artist: [c_char; 64],
434    pub cut_id: [c_char; 64],
435    pub client_id: [c_char; 64],
436    pub category: [c_char; 64],
437    pub classification: [c_char; 64],
438    pub out_cue: [c_char; 64],
439    pub start_date: [c_char; 10],
440    pub start_time: [c_char; 8],
441    pub end_date: [c_char; 10],
442    pub end_time: [c_char; 8],
443    pub procuder_app_id: [c_char; 64],
444    pub producer_app_version: [c_char; 64],
445    pub user_text: [c_char; 64],
446    pub sample_value_reference: DWORD,
447    pub post_timer: [TagCartTimer; 8],
448    pub reserved: [c_char; 276],
449    pub url: [c_char; 1024],
450    pub tag_text: [c_char; 0],
451}
452
453impl TagCart {
454    pub fn new<T: AsRef<[c_char]>>(
455        version: [c_char; 4],
456        title: [c_char; 64],
457        artist: [c_char; 64],
458        cut_id: [c_char; 64],
459        client_id: [c_char; 64],
460        category: [c_char; 64],
461        classification: [c_char; 64],
462        out_cue: [c_char; 64],
463        start_date: [c_char; 10],
464        start_time: [c_char; 8],
465        end_date: [c_char; 10],
466        end_time: [c_char; 8],
467        procuder_app_id: [c_char; 64],
468        producer_app_version: [c_char; 64],
469        user_text: [c_char; 64],
470        sample_value_reference: DWORD,
471        post_timer: [TagCartTimer; 8],
472        reserved: [c_char; 276],
473        url: [c_char; 1024],
474        tag_text: &T,
475    ) -> Result<Box<Self>, LayoutError> {
476        let tag_text_layout = Layout::array::<c_char>(tag_text.as_ref().len())?;
477        let (tag_cart_layout, _) = Layout::new::<TagCart>()
478            .extend(tag_text_layout)?;
479        let tag_cart_layout = tag_cart_layout.pad_to_align();
480
481        let tag_cart = unsafe { alloc::alloc(tag_cart_layout) }.cast::<TagCart>();
482
483        if tag_cart.is_null() {
484            alloc::handle_alloc_error(tag_cart_layout);
485        }
486
487        unsafe {
488            (*tag_cart).version = version;
489            (*tag_cart).title = title;
490            (*tag_cart).artist = artist;
491            (*tag_cart).cut_id = cut_id;
492            (*tag_cart).client_id = client_id;
493            (*tag_cart).category = category;
494            (*tag_cart).classification = classification;
495            (*tag_cart).out_cue = out_cue;
496            (*tag_cart).start_date = start_date;
497            (*tag_cart).start_time = start_time;
498            (*tag_cart).end_date = end_date;
499            (*tag_cart).end_time = end_time;
500            (*tag_cart).procuder_app_id = procuder_app_id;
501            (*tag_cart).producer_app_version = producer_app_version;
502            (*tag_cart).user_text = user_text;
503            (*tag_cart).sample_value_reference = sample_value_reference;
504            (*tag_cart).post_timer = post_timer;
505            (*tag_cart).reserved = reserved;
506            (*tag_cart).url = url;
507        }
508
509        for (index, value) in tag_text.as_ref().iter().enumerate() {
510            unsafe { (*tag_cart).tag_text[index] = *value };
511        }
512
513        Ok(unsafe { Box::from_raw(tag_cart) })
514    }
515}
516
517#[repr(C)]
518#[derive(Default, Debug, Clone)]
519pub struct TagCuePoint {
520    pub name: DWORD,
521    pub position: DWORD,
522    pub chunk: DWORD,
523    pub chun_start: DWORD,
524    pub block_start: DWORD,
525    pub sample_offset: DWORD,
526}
527
528impl TagCuePoint {
529    pub fn new(
530        name: DWORD,
531        position: DWORD,
532        chunk: DWORD,
533        chun_start: DWORD,
534        block_start: DWORD,
535        sample_offset: DWORD,
536    ) -> Self {
537        Self {
538            name,
539            position,
540            chunk,
541            chun_start,
542            block_start,
543            sample_offset,
544        }
545    }
546}
547
548#[repr(C)]
549#[derive(Default, Debug, Clone)]
550pub struct TagCue {
551    pub cue_points_count: DWORD,
552    pub cue_points: [TagCuePoint; 0],
553}
554
555impl TagCue {
556    pub fn new<T: AsRef<[TagCuePoint]>>(cue_points_count: DWORD, cue_points: &T) -> Result<Box<Self>, LayoutError> {
557        assert!(cue_points_count as usize == cue_points.as_ref().len());
558
559        let cue_points_layout = Layout::array::<TagCuePoint>(cue_points.as_ref().len())?;
560        let (tag_cue_layout, _) = Layout::new::<TagCue>()
561            .extend(cue_points_layout)?;
562        let tag_cue_layout = tag_cue_layout.pad_to_align();
563
564        let tag_cue = unsafe { alloc::alloc(tag_cue_layout) }.cast::<TagCue>();
565
566        if tag_cue.is_null() {
567            alloc::handle_alloc_error(tag_cue_layout);
568        }
569
570        unsafe { (*tag_cue).cue_points_count = cue_points_count };
571
572        for (index, value) in cue_points.as_ref().iter().enumerate() {
573            unsafe { (*tag_cue).cue_points[index] = value.clone() };
574        }
575
576        Ok(unsafe { Box::from_raw(tag_cue) })
577    }
578}
579
580#[repr(C)]
581#[derive(Default, Debug, Clone)]
582pub struct TagSampleLoop {
583    pub identifier: DWORD,
584    pub sample_type: DWORD,
585    pub start: DWORD,
586    pub end: DWORD,
587    pub fraction: DWORD,
588    pub play_count: DWORD,
589}
590
591impl TagSampleLoop {
592    pub fn new(
593        identifier: DWORD,
594        sample_type: DWORD,
595        start: DWORD,
596        end: DWORD,
597        fraction: DWORD,
598        play_count: DWORD,
599    ) -> Self {
600        Self {
601            identifier,
602            sample_type,
603            start,
604            end,
605            fraction,
606            play_count,
607        }
608    }
609}
610
611#[repr(C)]
612#[derive(Default, Debug, Clone)]
613pub struct TagSample {
614    pub manufacturer: DWORD,
615    pub product: DWORD,
616    pub sample_period: DWORD,
617    pub midi_unity_note: DWORD,
618    pub midi_pitch_fraction: DWORD,
619    pub smpte_format: DWORD,
620    pub smpte_offset: DWORD,
621    pub sample_loops_count: DWORD,
622    pub sampler_data: DWORD,
623    pub sample_loops: [TagSampleLoop; 0],
624}
625
626impl TagSample {
627    pub fn new<T: AsRef<[TagSampleLoop]>>(
628        manufacturer: DWORD,
629        product: DWORD,
630        sample_period: DWORD,
631        midi_unity_note: DWORD,
632        midi_pitch_fraction: DWORD,
633        smpte_format: DWORD,
634        smpte_offset: DWORD,
635        sample_loops_count: DWORD,
636        sampler_data: DWORD,
637        sample_loops: &T,
638    ) -> Result<Box<Self>, LayoutError> {
639        assert!(sample_loops_count as usize == sample_loops.as_ref().len());
640
641        let sample_loops_layout = Layout::array::<TagSampleLoop>(sample_loops.as_ref().len())?;
642        let (tag_sample_layout, _) = Layout::new::<TagSample>()
643            .extend(sample_loops_layout)?;
644        let tag_sample_layout = tag_sample_layout.pad_to_align();
645
646        let tag_sample = unsafe { alloc::alloc(tag_sample_layout) }.cast::<TagSample>();
647
648        if tag_sample.is_null() {
649            alloc::handle_alloc_error(tag_sample_layout);
650        }
651
652        unsafe { 
653            (*tag_sample).manufacturer = manufacturer;
654            (*tag_sample).product = product;
655            (*tag_sample).sample_period = sample_period;
656            (*tag_sample).midi_unity_note = midi_unity_note;
657            (*tag_sample).midi_pitch_fraction = midi_pitch_fraction;
658            (*tag_sample).smpte_format = smpte_format;
659            (*tag_sample).smpte_offset = smpte_offset;
660            (*tag_sample).sample_loops_count = sample_loops_count;
661            (*tag_sample).sampler_data = sampler_data;
662        }
663
664        for (index, value) in sample_loops.as_ref().iter().enumerate() {
665            unsafe { (*tag_sample).sample_loops[index] = value.clone() };
666        }
667
668        Ok(unsafe { Box::from_raw(tag_sample) })
669    }
670}
671
672#[repr(C)]
673#[derive(Debug, Clone)]
674pub struct TagCaCodec {
675    pub file_type: DWORD,
676    pub audio_format: DWORD,
677    pub description: *mut c_char,
678}
679
680impl TagCaCodec {
681    pub fn new(file_type: DWORD, audio_format: DWORD, description: *mut c_char) -> Self {
682        Self {
683            file_type,
684            audio_format,
685            description,
686        }
687    }
688}
689
690#[repr(C, packed(1))]
691#[derive(Default)]
692pub struct WaveFormatEx {
693    pub format_tag: WORD,
694    pub channels_number: WORD,
695    pub samples_per_second: DWORD,
696    pub average_bytes_per_second: DWORD,
697    pub block_align: WORD,
698    pub bits_per_sample: WORD,
699    pub size: WORD,
700}
701
702impl WaveFormatEx {
703    pub fn new(
704        format_tag: WORD,
705        channels_number: WORD,
706        samples_per_second: DWORD,
707        average_bytes_per_second: DWORD,
708        block_align: WORD,
709        bits_per_sample: WORD,
710        size: WORD,
711    ) -> Self {
712        Self {
713            format_tag,
714            channels_number,
715            samples_per_second,
716            average_bytes_per_second,
717            block_align,
718            bits_per_sample,
719            size,
720        }
721    }
722}
723
724#[repr(C)]
725#[derive(Default, Debug, Clone)]
726pub struct BassDx8Chorus {
727    pub wet_dry_mix: f32,
728    pub depth: f32,
729    pub feedback: f32,
730    pub frequency: f32,
731    pub waveform: DWORD,
732    pub delay: f32,
733    pub phase: DWORD,
734}
735
736impl BassDx8Chorus {
737    pub fn new(
738        wet_dry_mix: f32,
739        depth: f32,
740        feedback: f32,
741        frequency: f32,
742        waveform: DWORD,
743        delay: f32,
744        phase: DWORD,
745    ) -> Self {
746        Self {
747            wet_dry_mix,
748            depth,
749            feedback,
750            frequency,
751            waveform,
752            delay,
753            phase,
754        }
755    }
756}
757
758#[repr(C)]
759#[derive(Default, Debug, Clone)]
760pub struct BassDx8Compressor {
761    pub gain: f32,
762    pub attack: f32,
763    pub release: f32,
764    pub threshold: f32,
765    pub ratio: f32,
766    pub predelay: f32,
767}
768
769impl BassDx8Compressor {
770    pub fn new(
771        gain: f32,
772        attack: f32,
773        release: f32,
774        threshold: f32,
775        ratio: f32,
776        predelay: f32,
777    ) -> Self {
778        Self {
779            gain,
780            attack,
781            release,
782            threshold,
783            ratio,
784            predelay,
785        }
786    }
787}
788
789#[repr(C)]
790#[derive(Default, Debug, Clone)]
791pub struct BassDx8Distortion {
792    pub gain: f32,
793    pub edge: f32,
794    pub post_eq_center_frequency: f32,
795    pub post_eq_bandwidth: f32,
796    pub pre_lowpass_cutoff: f32,
797}
798
799impl BassDx8Distortion {
800    pub fn new(
801        gain: f32,
802        edge: f32,
803        post_eq_center_frequency: f32,
804        post_eq_bandwidth: f32,
805        pre_lowpass_cutoff: f32,
806    ) -> Self {
807        Self {
808            gain,
809            edge,
810            post_eq_center_frequency,
811            post_eq_bandwidth,
812            pre_lowpass_cutoff,
813        }
814    }
815}
816
817#[repr(C)]
818#[derive(Default, Debug, Clone)]
819pub struct BassDx8Echo {
820    pub wet_dry_mix: f32,
821    pub feedback: f32,
822    pub left_delay: f32,
823    pub right_delay: f32,
824    pub pan_delay: BOOL,
825}
826
827impl BassDx8Echo {
828    pub fn new(
829        wet_dry_mix: f32,
830        feedback: f32,
831        left_delay: f32,
832        right_delay: f32,
833        pan_delay: BOOL,
834    ) -> Self {
835        Self {
836            wet_dry_mix,
837            feedback,
838            left_delay,
839            right_delay,
840            pan_delay,
841        }
842    }
843}
844
845#[repr(C)]
846#[derive(Default, Debug, Clone)]
847pub struct BassDx8Flanger {
848    pub wet_dry_mix: f32,
849    pub depth: f32,
850    pub feedback: f32,
851    pub frequency: f32,
852    pub waveform: DWORD,
853    pub delay: f32,
854    pub phase: DWORD,
855}
856
857impl BassDx8Flanger {
858    pub fn new(
859        wet_dry_mix: f32,
860        depth: f32,
861        feedback: f32,
862        frequency: f32,
863        waveform: DWORD,
864        delay: f32,
865        phase: DWORD,
866    ) -> Self {
867        Self {
868            wet_dry_mix,
869            depth,
870            feedback,
871            frequency,
872            waveform,
873            delay,
874            phase,
875        }
876    }
877}
878
879#[repr(C)]
880#[derive(Default, Debug, Clone)]
881pub struct BassDx8Gargle {
882    pub rate_hz: DWORD,
883    pub wave_shape: DWORD,
884}
885
886impl BassDx8Gargle {
887    pub fn new(rate_hz: DWORD, wave_shape: DWORD) -> Self {
888        Self {
889            rate_hz,
890            wave_shape,
891        }
892    }
893}
894
895#[repr(C)]
896#[derive(Default, Debug, Clone)]
897pub struct BassDx8I3Dl2Reverb {
898    pub room: i32,
899    pub room_hf: i32,
900    pub room_rolloff_factor: f32,
901    pub decay_time: f32,
902    pub decay_hf_ratio: f32,
903    pub reflections: i32,
904    pub reflections_delay: f32,
905    pub reverb: i32,
906    pub reverb_delay: f32,
907    pub diffusion: f32,
908    pub density: f32,
909    pub hf_reference: f32,
910}
911
912impl BassDx8I3Dl2Reverb {
913    pub fn new(
914        room: i32,
915        room_hf: i32,
916        room_rolloff_factor: f32,
917        decay_time: f32,
918        decay_hf_ratio: f32,
919        reflections: i32,
920        reflections_delay: f32,
921        reverb: i32,
922        reverb_delay: f32,
923        diffusion: f32,
924        density: f32,
925        hf_reference: f32,
926    ) -> Self {
927        Self {
928            room,
929            room_hf,
930            room_rolloff_factor,
931            decay_time,
932            decay_hf_ratio,
933            reflections,
934            reflections_delay,
935            reverb,
936            reverb_delay,
937            diffusion,
938            density,
939            hf_reference,
940        }
941    }
942}
943
944#[repr(C)]
945#[derive(Default, Debug, Clone)]
946pub struct BassDx8ParamEq {
947    pub center: f32,
948    pub bandwidth: f32,
949    pub gain: f32,
950}
951
952impl BassDx8ParamEq {
953    pub fn new(center: f32, bandwidth: f32, gain: f32) -> Self {
954        Self {
955            center,
956            bandwidth,
957            gain,
958        }
959    }
960}
961
962#[repr(C)]
963#[derive(Default, Debug, Clone)]
964pub struct BassDx8Reverb {
965    pub gain: f32,
966    pub reverb_mix: f32,
967    pub reverb_time: f32,
968    pub high_frequency_rt_ratio: f32,
969}
970
971impl BassDx8Reverb {
972    pub fn new(gain: f32, reverb_mix: f32, reverb_time: f32, high_frequency_rt_ratio: f32) -> Self {
973        Self {
974            gain,
975            reverb_mix,
976            reverb_time,
977            high_frequency_rt_ratio,
978        }
979    }
980}
981
982#[repr(C)]
983#[derive(Default, Debug, Clone)]
984pub struct BassFxVolumeParam {
985    pub target: f32,
986    pub current: f32,
987    pub time: f32,
988    pub curve: DWORD,
989}
990
991impl BassFxVolumeParam {
992    pub fn new(target: f32, current: f32, time: f32, curve: DWORD) -> Self {
993        Self {
994            target,
995            current,
996            time,
997            curve,
998        }
999    }
1000}