Skip to main content

Channel

Struct Channel 

Source
pub struct Channel {
Show 31 fields pub sample_index: u8, pub sample_pos: f32, pub period: u16, pub volume: u8, pub active: bool, pub finetune: i8, pub effect: u8, pub effect_param: u8, pub arp_base_period: u16, pub mem_porta_up: u8, pub mem_porta_down: u8, pub tone_porta_target: u16, pub tone_porta_speed: u8, pub mem_vibrato: u8, pub vib_pos: i8, pub vib_wave: Waveform, pub mem_tremolo: u8, pub trem_pos: i8, pub trem_wave: Waveform, pub mem_sample_offset: u8, pub mem_volslide: u8, pub retrig_ticks: u8, pub cut_tick: u8, pub delay: Option<DelayedTrigger>, pub glissando: bool, pub pending_sample: u8, pub pending_led: Option<bool>, pub pan: u8, pub last_mixed_sample: f32, pub ramp_prev_sample: f32, pub ramp_remaining_frames: u32,
}
Expand description

Per-channel playback state.

Fields§

§sample_index: u8

1-based sample index (0 = no sample ever triggered).

§sample_pos: f32

Fractional read position into the sample’s pcm buffer.

§period: u16

Current period (0 = silent / not playing).

§volume: u8

Current volume 0..=64.

§active: bool

Whether this channel is currently sounding.

§finetune: i8

Current finetune for the most recently loaded sample.

§effect: u8

Current effect command (0..=0xF).

§effect_param: u8§arp_base_period: u16

Arpeggio base period — the un-modulated period for this row.

§mem_porta_up: u8

Last portamento-up param (1xx), used when param == 0.

§mem_porta_down: u8

Last portamento-down param (2xx), used when param == 0.

§tone_porta_target: u16

Tone portamento target period (set by a note on a 3xy / 5xy row).

§tone_porta_speed: u8

Tone portamento speed (3xy / 5xy param; 0 reuses the last value).

§mem_vibrato: u8

Last vibrato params — nibble format rate<<4 | depth.

§vib_pos: i8

Vibrato LFO position, signed -32..=31.

§vib_wave: Waveform

Vibrato waveform control.

§mem_tremolo: u8

Last tremolo params — nibble format rate<<4 | depth.

§trem_pos: i8

Tremolo LFO position, signed -32..=31.

§trem_wave: Waveform

Tremolo waveform control.

§mem_sample_offset: u8

Last 9xx sample-offset param.

§mem_volslide: u8

Last volume-slide param (A/5/6).

§retrig_ticks: u8

E9x retrigger period (ticks between retriggers).

§cut_tick: u8

ECx note-cut tick (0 = no cut pending).

§delay: Option<DelayedTrigger>

EDx note-delay state — Some(delay_tick) while pending, filled in on row entry.

§glissando: bool

Glissando flag (E3x): if set, tone portamento snaps to nearest semitone each tick rather than sliding smoothly.

§pending_sample: u8

Sample number written on a row that did not also trigger a note — the swap is deferred until the next note-on per Protracker quirk (see enter_row for the citation). 0 means no pending swap.

§pending_led: Option<bool>

Pending LED-filter state from an E0x on this channel’s row. Some(true) = filter ON (E00, LED on). Some(false) = filter OFF (E01, LED off). None = no E0 this row. Resolved at the end of enter_row after all four channels’ tick-0 effects are processed: like Fxx, a later channel’s E0 wins on the same row.

§pan: u8

Per-channel pan position, 0..=255. 0 = hard LEFT, 255 = hard RIGHT, 128 = centre. This is the FT-extension panning state set by 8xx (full 8-bit pan, Protracker-effects- MODFIL12.txt lines 1201-1207: “Command 8: Set FINE Panning … xxxxyyyy = panning position. (0=Most left, 255=most right.)”) and by E8x (rough nibble pan, Protracker-effects- MODFIL12.txt lines 1503-1505: “Command $E8: Set (Rough) Panning … yyyy = panning value. $0 = most left, $F = most right.”) — the E8 nibble is replicated across both halves of the byte so E80 → 0x00, E8F → 0xFF, E87 → 0x77, matching the “rough” 16-step interpretation also documented in multimedia-cx-protracker.html (“$0 is hard left, $F is hard right”). Initial values follow the Amiga LRRL hard-pan convention (channels 0 & 3 → 0, 1 & 2 → 255, pattern repeats every 4) so a MOD with no panning commands renders identically to the pre-r75 build.

§last_mixed_sample: f32

Last post-volume sample emitted by this channel’s mixer. Used as the starting point for the crossfade ramp on the next re-trigger (see ramp_prev_sample). Updated by mix_one every output frame.

§ramp_prev_sample: f32

Volume that the previous note was being mixed at the moment this channel was re-triggered. Captured by enter_row on every fresh note-on (and on retrigger paths like E9x and the EDx delayed trigger) so the mixer can crossfade from this old value to the new note’s first sample over a short ramp, instead of stepping discontinuously and producing the audible pop that a hard re-trigger leaves behind.

Without the ramp, every note-on creates a discontinuity in the mixed bus equal to (last sample of the old note) → (first sample of the new note), which is typically a step of a few hundred i16 LSBs and accumulates into the per-trigger HF drift observed on real-world MODs (halluc.mod, rhmst.mod).

§ramp_remaining_frames: u32

Number of output frames remaining in the per-trigger crossfade ramp. The ramp linearly interpolates from ramp_prev_sample to the new note’s mixed sample. Set to PlayerState::RAMP_FRAMES on every fresh trigger; counted down by mix_one once per output frame.

Trait Implementations§

Source§

impl Clone for Channel

Source§

fn clone(&self) -> Channel

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Channel

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Channel

Source§

fn default() -> Channel

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.