Skip to content

Channel

Channel

Bases: _FLObject

Represents a channel of one of the kinds in Kind in the channel rack.

Source code in pyflp/channel/channel.py
 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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
class Channel(_FLObject):
    """Represents a channel of one of the kinds in `Kind` in the channel rack."""

    def __init__(self):
        super().__init__()
        self._layer_children: List[int] = []

        # Since default event isn't stored and having this event means it is zipped.
        self._zipped = False

        # 1 for vol tracking, 1 for key tracking.
        self.__tracking_events: List[ChannelTrackingEvent] = []

        # 1 each for panning, volume, pitch, mod x and mod y
        self._env_lfos: Dict[str, ChannelEnvelopeLFO] = {}
        self.__envlfo_events: List[ChannelEnvelopeLFOEvent] = []

    def _setprop(self, n: str, v: Any) -> None:
        if n == "volume":
            self.levels.volume = v
        elif n == "pan":
            self.levels.pan = v
        else:
            super()._setprop(n, v)

    @enum.unique
    class Kind(enum.IntEnum):
        """Used by `Channel.kind` for event `Channel.EventID.Kind`."""

        Sampler = 0
        Native = 2  # Used by audio clips and other native FL Studio synths
        Layer = 3
        Instrument = 4
        Automation = 5

    @enum.unique
    class EventID(enum.IntEnum):
        """Event IDs used by `Channel`."""

        Enabled = 0
        """See `Channel.enabled`."""

        _Vol = 2
        """See `Channel.volume`. Obsolete."""

        _Pan = 3
        """See `Channel.pan`. Obsolete."""

        Zipped = 15
        """See `Channel.zipped`. Default event is not stored."""

        UseLoopPoints = 19
        Kind = 21
        """Stores `ChannelKind`, used by `Channel.kind`."""

        TargetInsert = 22
        """See `Channel.insert`."""

        # FXProperties = 27
        Locked = 32
        """See `Channel.locked`. FL 12.3+."""

        New = WORD
        """Marks the beginning of a new channel."""

        # Fx = WORD + 5
        # FadeStereo = WORD + 6
        _Volume = WORD + 8
        """See `Channel.volume`. Deprecates `ChannelEventID._Vol`. Obsolete."""

        _Panning = WORD + 9
        """See `Channel.pan`. Deprecates `ChannelEventID._Pan`. Obsolete."""

        # DotNote = WORD + 13
        # DotPitch = WORD + 14
        # DotMix = WORD + 15
        # Fx3 = WORD + 22
        # DotReso = WORD + 23
        # DotCutOff = WORD + 24
        # ShiftDelay = WORD + 25
        # Dot = WORD + 27
        # DotRel = WORD + 32
        # DotShift = WORD + 28

        LayerChildren = WORD + 30
        """Stores index of a child `Channel`. See `Channel.children`.
        Used by layer channels only. Each child has its own events."""

        Swing = WORD + 33
        """See `Channel.swing`."""

        Color = DWORD
        """See `Channel.color`. Defaults to #485156."""

        # Echo = DWORD + 2
        # FxSine = DWORD + 3

        CutSelfCutBy = DWORD + 4
        """See `Channel.cut_group`. Default event (0, 0)
        is not stored only for Layer channels."""

        RootNote = DWORD + 7
        """See `Channel.root_note`. Default event is not stored."""

        # _MainResoCutOff = DWORD + 9
        """Obsolete."""

        # DelayModXY = DWORD + 10

        StretchTime = DWORD + 12
        """See `Channel.stretch_time`."""

        # FineTune = DWORD + 14
        SamplerFlags = DWORD + 15
        """See `Channel.sampler_flags`."""

        LayerFlags = DWORD + 16
        """See `Channel.layer_flags`."""

        FilterChannelNum = DWORD + 17
        """See `Channel.filter_channel`."""

        AUSampleRate = DWORD + 25
        """See `Channel.au_sample_rate`. Possibly obsolete."""

        Icon = DWORD + 27
        """Index of the icon used. See `Channel.icon`."""

        SamplePath = TEXT + 4
        """See `Channel.sample_path`. Default event is not stored."""

        DefaultName = TEXT + 9
        """See `Channel.default_name`."""

        Name = TEXT + 11
        """See `Channel.name`. Default event is not stored."""

        Delay = DATA + 1
        """See `Channel.delay`. Implemented by `ChannelDelayEvent`."""

        Plugin = DATA + 5
        """See `Channel.plugin`. Implemented by `Plugin`."""

        Parameters = DATA + 7
        """See `Channel.parameters`. Implemented by `ChannelParametersEvent`."""

        Levels = DATA + 11
        """See `Channel.levels`. Implemented by `ChannelLevelsEvent`."""

        # _Filter = DATA + 12
        Polyphony = DATA + 13
        """See `Channel.polyphony`. Implemented by `ChannelPolyphonyEvent`."""

        EnvelopeLFO = DATA + 10
        """See `Channel.env_lfos`. Impelemented by `ChannelEnvelopeLFOEvent`"""

        Tracking = DATA + 20
        """See `Channel.tracking`. Implemented by `ChannelTrackingEvent`."""

        LevelOffsets = DATA + 21
        """See `Channel.level_offsets`. Implemented by `ChannelLevelOffsetsEvent`."""

    # * Properties
    default_name: Optional[str] = _StrProperty()
    """Default name of the channel.
    The value of this depends on the type of `plugin`:

    * Native (stock) plugin: The factory name of the plugin.
    * VST instruments: "Fruity Wrapper".

    See `name` also."""

    index: Optional[int] = _UIntProperty()

    volume: Optional[int] = _UIntProperty(max_=12800)
    """Min: 0, Max: 12800, Default: 10000."""

    pan: Optional[int] = _UIntProperty(max_=12800)
    """Min: 0, Max: 12800, Default: 6400."""

    color: Optional[colour.Color] = _ColorProperty()

    target_insert: Optional[int] = _IntProperty(min_=-1)
    """The index of the `Insert` the channel is routed to."""

    kind: Optional[Kind] = _EnumProperty(Kind)
    """Type of channel. See `Kind`."""

    enabled: Optional[bool] = _BoolProperty()
    """Whether the channel is in enabled state."""

    locked: Optional[bool] = _BoolProperty()
    """Whether the channel is locked in the channel rack. Paired with
    the `Channel.enabled`, it represents actual state of the channel."""

    zipped: bool = _BoolProperty()
    """Whether the channel is in zipped state."""

    root_note: Optional[int] = _IntProperty()
    """Miscellaneous settings -> Root note. Min: 0 (C0), Max: 131 (B10)"""

    icon: Optional[int] = _IntProperty()

    sample_path: Optional[str] = _StrProperty()
    """Absolute path of a sample file on the disk. Valid only if
    `Channel.kind` is `ChannelKind.Sampler` or `ChannelKind.Audio`.
    Contains '%FLStudioFactoryData%' for stock samples."""

    # TODO Maybe the lower limit for this is -1
    filter_channel: Optional[int] = _IntProperty()
    """Display filter under which this channel is grouped. See `Filter`."""

    @property
    def plugin(self) -> Optional[_Plugin]:
        """The `Plugin` associated with the channel. Valid
        only if `kind` is `ChannelKind.Instrument`."""
        return getattr(self, "_plugin", None)

    @property
    def children(self) -> List[int]:
        """List of children `index`es of a Layer.
        Valid only if `kind` is `ChannelKind.Layer`."""
        return getattr(self, "_layer_children")

    @property
    def fx(self) -> Optional[ChannelFX]:
        """See `ChannelFX`."""
        return getattr(self, "_fx", None)

    name: Optional[str] = _StrProperty()
    """The value of this depends on the type of `plugin`:

    * Native (stock) plugin: User-given name. Default event is not stored.
    * VST plugin (VSTi): The name obtained from the VST, or the user-given name.
        Default event (i.e VST plugin name) is stored.

    See `default_name` also."""

    # TODO Discover
    sampler_flags: Optional[int] = _IntProperty()
    """Flags associated with `Channel` of kind `Kind.Sampler`."""

    # TODO Discover
    layer_flags: Optional[int] = _IntProperty()
    """Flags associated with a `Channel` of kind `Kind.Layer`."""

    use_loop_points: Optional[bool] = _BoolProperty()
    """Sampler/Audio -> Playback -> Use loop points."""

    swing: Optional[int] = _UIntProperty()
    """Sampler/Instruemnt -> Miscellaneous functions -> Time -> Swing."""

    @property
    def delay(self) -> Optional[ChannelDelay]:
        """See `ChannelDelay`."""
        return getattr(self, "_delay", None)

    @property
    def polyphony(self) -> Optional[ChannelPolyphony]:
        """See `ChannelPolyphony`."""
        return getattr(self, "_polyphony", None)

    @property
    def levels(self) -> Optional[ChannelLevels]:
        """See `ChannelLevels`."""
        return getattr(self, "_levels", None)

    @property
    def tracking_vol(self) -> Optional[ChannelTracking]:
        """Volume tracking. See `ChannelTracking`."""
        return getattr(self, "_tracking_vol", None)

    @property
    def tracking_key(self) -> Optional[ChannelTracking]:
        """Key tracking. See `ChannelTracking`."""
        return getattr(self, "_tracking_key", None)

    @property
    def level_offsets(self) -> Optional[ChannelLevelOffsets]:
        """See `ChannelLevelOffsets`."""
        return getattr(self, "_level_offsets", None)

    stretch_time: Optional[int] = _UIntProperty()
    """Sampler/Audio -> Time stretching -> Time.

    [Manual](https://www.image-line.com/fl-studio-learning/fl-studio-online-manual/html/chansettings_sampler.htm#Sampler_Beatmatching)"""  # noqa

    au_sample_rate: Optional[int] = _UIntProperty()
    """AU-format sample specific."""

    @property
    def arp(self) -> Optional[ChannelArp]:
        """See `ChannelArp` and `ChannelParametersEvent`."""
        return getattr(self, "_arp", None)

    @property
    def env_lfos(self) -> Dict[str, ChannelEnvelopeLFO]:
        """Channel AHDSR envelopes and LFOs for Panning, Volume, Pitch, Mod X (Cutoff)
        and Mod Y (Resonance). See `ChannelEnvelope` and `ChannelEnvelopeEvent`."""
        return getattr(self, "_env_lfos", {})

    @property
    def cut_group(self) -> Tuple[int]:
        """Cut group in the form of (Cut self, cut by)."""
        return getattr(self, "_cut_group", tuple())

    @cut_group.setter
    def cut_group(self, value: Tuple[int]):
        if len(value) != 2:
            raise TypeError("Expected a tuple of size 2")
        self._events["cut_group"]._data = struct.pack("2H", *value)
        self._cut_group = value

    # * Parsing logic
    def parse_event(self, e: EventType) -> None:
        if e.id_ in ChannelFX.EventID.__members__.values():
            if not hasattr(self, "_fx"):
                self._fx = ChannelFX()
            return self._fx.parse_event(e)
        return super().parse_event(e)

    def _parse_byte_event(self, e: ByteEventType) -> None:
        if e.id_ == Channel.EventID.Enabled:
            self._parse_bool(e, "enabled")
        elif e.id_ == Channel.EventID._Vol:
            self._parse_B(e, "volume")
        elif e.id_ == Channel.EventID._Pan:
            self._parse_b(e, "pan")
        elif e.id_ == Channel.EventID.Kind:
            self._events["kind"] = e
            kind = e.to_uint8()
            try:
                self._kind = Channel.Kind(kind)
            except AttributeError:
                self._kind = kind
        elif e.id_ == Channel.EventID.Zipped:
            self._parse_bool(e, "zipped")
        elif e.id_ == Channel.EventID.UseLoopPoints:
            self._parse_bool(e, "use_loop_points")
        elif e.id_ == Channel.EventID.TargetInsert:
            self._parse_b(e, "target_insert")
        elif e.id_ == Channel.EventID.Locked:
            self._parse_bool(e, "locked")

    def _parse_word_event(self, e: WordEventType) -> None:
        if e.id_ == Channel.EventID.New:
            self._parse_H(e, "index")
        elif e.id_ == Channel.EventID._Volume:
            self._parse_H(e, "volume")
        elif e.id_ == Channel.EventID._Panning:
            self._parse_h(e, "pan")
        elif e.id_ == Channel.EventID.LayerChildren:
            self._events[f"child{len(self._layer_children)}"] = e
            self._layer_children.append(e.to_uint16())
        elif e.id_ == Channel.EventID.Swing:
            self._parse_H(e, "swing")

    def _parse_dword_event(self, e: DWordEventType) -> None:
        if e.id_ == Channel.EventID.Color:
            self._parse_color(e, "color")
        elif e.id_ == Channel.EventID.CutSelfCutBy:
            self._parseprop(e, "cut_group", struct.unpack("2H", e.data))
        elif e.id_ == Channel.EventID.RootNote:
            self._parse_I(e, "root_note")
        elif e.id_ == Channel.EventID.StretchTime:
            self._parse_I(e, "stretch_time")
        elif e.id_ == Channel.EventID.SamplerFlags:
            self._parse_I(e, "sampler_flags")
        elif e.id_ == Channel.EventID.LayerFlags:
            self._parse_I(e, "layer_flags")
        elif e.id_ == Channel.EventID.FilterChannelNum:
            self._parse_i(e, "filter_channel")
        elif e.id_ == Channel.EventID.Icon:
            self._parse_I(e, "icon")
        elif e.id_ == Channel.EventID.AUSampleRate:
            self._parse_I(e, "au_sample_rate")

    def _parse_text_event(self, e: TextEventType) -> None:
        if e.id_ == Channel.EventID.DefaultName:
            self._parse_s(e, "default_name")
        elif e.id_ == Channel.EventID.SamplePath:
            self._parse_s(e, "sample_path")
        elif e.id_ == Channel.EventID.Name:
            self._parse_s(e, "name")

    def _parse_data_event(self, e: DataEventType) -> None:
        if e.id_ == Channel.EventID.Plugin:
            if self.default_name == "BooBass":
                plugin = BooBass()
            elif self.default_name == "Fruity Wrapper":
                plugin = VSTPlugin()
            else:
                plugin = _Plugin()
            self._parse_flobject(e, "plugin", plugin)
        elif e.id_ == Channel.EventID.Delay:
            self._parse_flobject(e, "delay", ChannelDelay())
        elif e.id_ == Channel.EventID.Polyphony:
            self._parse_flobject(e, "polyphony", ChannelPolyphony())
        elif e.id_ == Channel.EventID.LevelOffsets:
            self._parse_flobject(e, "level_offsets", ChannelLevelOffsets())
        elif e.id_ == Channel.EventID.Levels:
            self._parse_flobject(e, "levels", ChannelLevels())
            self._volume = self.levels.volume
            self._pan = self.levels.pan
        elif e.id_ == Channel.EventID.Tracking:
            self.__tracking_events.append(e)
            ct = ChannelTracking()
            ct.parse_event(e)
            if not self.tracking_vol:
                self._tracking_vol = ct
            else:
                self._tracking_key = ct
        elif e.id_ == Channel.EventID.Parameters:
            self._events["parameters"] = e
            self._arp = e.arp
        elif e.id_ == Channel.EventID.EnvelopeLFO:
            idx = len(self.__envlfo_events)
            name = EnvelopeLFONames[idx]
            self.__envlfo_events.append(e)
            el = ChannelEnvelopeLFO()
            el.parse_event(e)
            self._env_lfos[name] = el

    def _save(self) -> List[EventType]:
        if self.plugin:
            self.plugin._save()
        events = list(super()._save())
        if self.fx:
            events.extend(list(self.fx._save()))
        events.extend(self.__tracking_events)
        events.extend(self.__envlfo_events)
        return events

    # * Utility methods
    def get_name(self) -> Optional[str]:
        if self.name:
            return self.name
        return self.default_name

au_sample_rate: Optional[int] = _UIntProperty() class-attribute

AU-format sample specific.

color: Optional[colour.Color] = _ColorProperty() class-attribute

default_name: Optional[str] = _StrProperty() class-attribute

Default name of the channel. The value of this depends on the type of plugin:

  • Native (stock) plugin: The factory name of the plugin.
  • VST instruments: "Fruity Wrapper".

See name also.

enabled: Optional[bool] = _BoolProperty() class-attribute

Whether the channel is in enabled state.

filter_channel: Optional[int] = _IntProperty() class-attribute

Display filter under which this channel is grouped. See Filter.

icon: Optional[int] = _IntProperty() class-attribute

index: Optional[int] = _UIntProperty() class-attribute

kind: Optional[Kind] = _EnumProperty(Kind) class-attribute

Type of channel. See Kind.

layer_flags: Optional[int] = _IntProperty() class-attribute

Flags associated with a Channel of kind Kind.Layer.

locked: Optional[bool] = _BoolProperty() class-attribute

Whether the channel is locked in the channel rack. Paired with the Channel.enabled, it represents actual state of the channel.

name: Optional[str] = _StrProperty() class-attribute

The value of this depends on the type of plugin:

  • Native (stock) plugin: User-given name. Default event is not stored.
  • VST plugin (VSTi): The name obtained from the VST, or the user-given name. Default event (i.e VST plugin name) is stored.

See default_name also.

pan: Optional[int] = _UIntProperty(max_=12800) class-attribute

Min: 0, Max: 12800, Default: 6400.

root_note: Optional[int] = _IntProperty() class-attribute

Miscellaneous settings -> Root note. Min: 0 (C0), Max: 131 (B10)

sample_path: Optional[str] = _StrProperty() class-attribute

Absolute path of a sample file on the disk. Valid only if Channel.kind is ChannelKind.Sampler or ChannelKind.Audio. Contains '%FLStudioFactoryData%' for stock samples.

sampler_flags: Optional[int] = _IntProperty() class-attribute

Flags associated with Channel of kind Kind.Sampler.

stretch_time: Optional[int] = _UIntProperty() class-attribute

Sampler/Audio -> Time stretching -> Time.

Manual

swing: Optional[int] = _UIntProperty() class-attribute

Sampler/Instruemnt -> Miscellaneous functions -> Time -> Swing.

target_insert: Optional[int] = _IntProperty(min_=-1) class-attribute

The index of the Insert the channel is routed to.

use_loop_points: Optional[bool] = _BoolProperty() class-attribute

Sampler/Audio -> Playback -> Use loop points.

volume: Optional[int] = _UIntProperty(max_=12800) class-attribute

Min: 0, Max: 12800, Default: 10000.

zipped: bool = _BoolProperty() class-attribute

Whether the channel is in zipped state.

EventID

Bases: enum.IntEnum

Event IDs used by Channel.

Source code in pyflp/channel/channel.py
 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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
@enum.unique
class EventID(enum.IntEnum):
    """Event IDs used by `Channel`."""

    Enabled = 0
    """See `Channel.enabled`."""

    _Vol = 2
    """See `Channel.volume`. Obsolete."""

    _Pan = 3
    """See `Channel.pan`. Obsolete."""

    Zipped = 15
    """See `Channel.zipped`. Default event is not stored."""

    UseLoopPoints = 19
    Kind = 21
    """Stores `ChannelKind`, used by `Channel.kind`."""

    TargetInsert = 22
    """See `Channel.insert`."""

    # FXProperties = 27
    Locked = 32
    """See `Channel.locked`. FL 12.3+."""

    New = WORD
    """Marks the beginning of a new channel."""

    # Fx = WORD + 5
    # FadeStereo = WORD + 6
    _Volume = WORD + 8
    """See `Channel.volume`. Deprecates `ChannelEventID._Vol`. Obsolete."""

    _Panning = WORD + 9
    """See `Channel.pan`. Deprecates `ChannelEventID._Pan`. Obsolete."""

    # DotNote = WORD + 13
    # DotPitch = WORD + 14
    # DotMix = WORD + 15
    # Fx3 = WORD + 22
    # DotReso = WORD + 23
    # DotCutOff = WORD + 24
    # ShiftDelay = WORD + 25
    # Dot = WORD + 27
    # DotRel = WORD + 32
    # DotShift = WORD + 28

    LayerChildren = WORD + 30
    """Stores index of a child `Channel`. See `Channel.children`.
    Used by layer channels only. Each child has its own events."""

    Swing = WORD + 33
    """See `Channel.swing`."""

    Color = DWORD
    """See `Channel.color`. Defaults to #485156."""

    # Echo = DWORD + 2
    # FxSine = DWORD + 3

    CutSelfCutBy = DWORD + 4
    """See `Channel.cut_group`. Default event (0, 0)
    is not stored only for Layer channels."""

    RootNote = DWORD + 7
    """See `Channel.root_note`. Default event is not stored."""

    # _MainResoCutOff = DWORD + 9
    """Obsolete."""

    # DelayModXY = DWORD + 10

    StretchTime = DWORD + 12
    """See `Channel.stretch_time`."""

    # FineTune = DWORD + 14
    SamplerFlags = DWORD + 15
    """See `Channel.sampler_flags`."""

    LayerFlags = DWORD + 16
    """See `Channel.layer_flags`."""

    FilterChannelNum = DWORD + 17
    """See `Channel.filter_channel`."""

    AUSampleRate = DWORD + 25
    """See `Channel.au_sample_rate`. Possibly obsolete."""

    Icon = DWORD + 27
    """Index of the icon used. See `Channel.icon`."""

    SamplePath = TEXT + 4
    """See `Channel.sample_path`. Default event is not stored."""

    DefaultName = TEXT + 9
    """See `Channel.default_name`."""

    Name = TEXT + 11
    """See `Channel.name`. Default event is not stored."""

    Delay = DATA + 1
    """See `Channel.delay`. Implemented by `ChannelDelayEvent`."""

    Plugin = DATA + 5
    """See `Channel.plugin`. Implemented by `Plugin`."""

    Parameters = DATA + 7
    """See `Channel.parameters`. Implemented by `ChannelParametersEvent`."""

    Levels = DATA + 11
    """See `Channel.levels`. Implemented by `ChannelLevelsEvent`."""

    # _Filter = DATA + 12
    Polyphony = DATA + 13
    """See `Channel.polyphony`. Implemented by `ChannelPolyphonyEvent`."""

    EnvelopeLFO = DATA + 10
    """See `Channel.env_lfos`. Impelemented by `ChannelEnvelopeLFOEvent`"""

    Tracking = DATA + 20
    """See `Channel.tracking`. Implemented by `ChannelTrackingEvent`."""

    LevelOffsets = DATA + 21
    """See `Channel.level_offsets`. Implemented by `ChannelLevelOffsetsEvent`."""

AUSampleRate = DWORD + 25 class-attribute

See Channel.au_sample_rate. Possibly obsolete.

Color = DWORD class-attribute

See Channel.color. Defaults to #485156.

CutSelfCutBy = DWORD + 4 class-attribute

See Channel.cut_group. Default event (0, 0) is not stored only for Layer channels.

DefaultName = TEXT + 9 class-attribute

See Channel.default_name.

Delay = DATA + 1 class-attribute

See Channel.delay. Implemented by ChannelDelayEvent.

Enabled = 0 class-attribute

See Channel.enabled.

EnvelopeLFO = DATA + 10 class-attribute

See Channel.env_lfos. Impelemented by ChannelEnvelopeLFOEvent

FilterChannelNum = DWORD + 17 class-attribute

See Channel.filter_channel.

Icon = DWORD + 27 class-attribute

Index of the icon used. See Channel.icon.

Kind = 21 class-attribute

Stores ChannelKind, used by Channel.kind.

LayerChildren = WORD + 30 class-attribute

Stores index of a child Channel. See Channel.children. Used by layer channels only. Each child has its own events.

LayerFlags = DWORD + 16 class-attribute

See Channel.layer_flags.

LevelOffsets = DATA + 21 class-attribute

See Channel.level_offsets. Implemented by ChannelLevelOffsetsEvent.

Levels = DATA + 11 class-attribute

See Channel.levels. Implemented by ChannelLevelsEvent.

Locked = 32 class-attribute

See Channel.locked. FL 12.3+.

Name = TEXT + 11 class-attribute

See Channel.name. Default event is not stored.

New = WORD class-attribute

Marks the beginning of a new channel.

Parameters = DATA + 7 class-attribute

See Channel.parameters. Implemented by ChannelParametersEvent.

Plugin = DATA + 5 class-attribute

See Channel.plugin. Implemented by Plugin.

Polyphony = DATA + 13 class-attribute

See Channel.polyphony. Implemented by ChannelPolyphonyEvent.

RootNote = DWORD + 7 class-attribute

See Channel.root_note. Default event is not stored.

SamplePath = TEXT + 4 class-attribute

See Channel.sample_path. Default event is not stored.

SamplerFlags = DWORD + 15 class-attribute

See Channel.sampler_flags.

StretchTime = DWORD + 12 class-attribute

See Channel.stretch_time.

Swing = WORD + 33 class-attribute

See Channel.swing.

TargetInsert = 22 class-attribute

See Channel.insert.

Tracking = DATA + 20 class-attribute

See Channel.tracking. Implemented by ChannelTrackingEvent.

UseLoopPoints = 19 class-attribute

Zipped = 15 class-attribute

See Channel.zipped. Default event is not stored.

arp() property

See ChannelArp and ChannelParametersEvent.

Source code in pyflp/channel/channel.py
345
346
347
348
@property
def arp(self) -> Optional[ChannelArp]:
    """See `ChannelArp` and `ChannelParametersEvent`."""
    return getattr(self, "_arp", None)

children() property

List of children indexes of a Layer. Valid only if kind is ChannelKind.Layer.

Source code in pyflp/channel/channel.py
273
274
275
276
277
@property
def children(self) -> List[int]:
    """List of children `index`es of a Layer.
    Valid only if `kind` is `ChannelKind.Layer`."""
    return getattr(self, "_layer_children")

cut_group() writable property

Cut group in the form of (Cut self, cut by).

Source code in pyflp/channel/channel.py
356
357
358
359
@property
def cut_group(self) -> Tuple[int]:
    """Cut group in the form of (Cut self, cut by)."""
    return getattr(self, "_cut_group", tuple())

delay() property

See ChannelDelay.

Source code in pyflp/channel/channel.py
307
308
309
310
@property
def delay(self) -> Optional[ChannelDelay]:
    """See `ChannelDelay`."""
    return getattr(self, "_delay", None)

env_lfos() property

Channel AHDSR envelopes and LFOs for Panning, Volume, Pitch, Mod X (Cutoff) and Mod Y (Resonance). See ChannelEnvelope and ChannelEnvelopeEvent.

Source code in pyflp/channel/channel.py
350
351
352
353
354
@property
def env_lfos(self) -> Dict[str, ChannelEnvelopeLFO]:
    """Channel AHDSR envelopes and LFOs for Panning, Volume, Pitch, Mod X (Cutoff)
    and Mod Y (Resonance). See `ChannelEnvelope` and `ChannelEnvelopeEvent`."""
    return getattr(self, "_env_lfos", {})

fx() property

See ChannelFX.

Source code in pyflp/channel/channel.py
279
280
281
282
@property
def fx(self) -> Optional[ChannelFX]:
    """See `ChannelFX`."""
    return getattr(self, "_fx", None)

level_offsets() property

See ChannelLevelOffsets.

Source code in pyflp/channel/channel.py
332
333
334
335
@property
def level_offsets(self) -> Optional[ChannelLevelOffsets]:
    """See `ChannelLevelOffsets`."""
    return getattr(self, "_level_offsets", None)

levels() property

See ChannelLevels.

Source code in pyflp/channel/channel.py
317
318
319
320
@property
def levels(self) -> Optional[ChannelLevels]:
    """See `ChannelLevels`."""
    return getattr(self, "_levels", None)

plugin() property

The Plugin associated with the channel. Valid only if kind is ChannelKind.Instrument.

Source code in pyflp/channel/channel.py
267
268
269
270
271
@property
def plugin(self) -> Optional[_Plugin]:
    """The `Plugin` associated with the channel. Valid
    only if `kind` is `ChannelKind.Instrument`."""
    return getattr(self, "_plugin", None)

polyphony() property

See ChannelPolyphony.

Source code in pyflp/channel/channel.py
312
313
314
315
@property
def polyphony(self) -> Optional[ChannelPolyphony]:
    """See `ChannelPolyphony`."""
    return getattr(self, "_polyphony", None)

tracking_vol() property

Volume tracking. See ChannelTracking.

Source code in pyflp/channel/channel.py
322
323
324
325
@property
def tracking_vol(self) -> Optional[ChannelTracking]:
    """Volume tracking. See `ChannelTracking`."""
    return getattr(self, "_tracking_vol", None)

tracking_key() property

Key tracking. See ChannelTracking.

Source code in pyflp/channel/channel.py
327
328
329
330
@property
def tracking_key(self) -> Optional[ChannelTracking]:
    """Key tracking. See `ChannelTracking`."""
    return getattr(self, "_tracking_key", None)

ChannelArp

Saving

This object doesn't implement property setters yet!

Bases: _FLObject

Miscellaneous settings -> Arp section.

Manual

Source code in pyflp/channel/arp.py
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
class ChannelArp(_FLObject):
    """Miscellaneous settings -> Arp section.

    [Manual](https://www.image-line.com/fl-studio-learning/fl-studio-online-manual/html/chansettings_misc.htm#Arp)
    """

    class Direction(enum.IntEnum):
        """Arpeggio direction. Used by `ChannelArp.direction`."""

        Off = 0
        Up = 1
        Down = 2
        UpDownBounce = 3
        UpDownSticky = 4
        Random = 5

    # * Properties
    direction: Optional[Direction] = _EnumProperty(Direction)

    range: Optional[int] = _UIntProperty()
    """Range (in octaves)."""

    chord: Optional[int] = _UIntProperty()
    """Index of the selected arpeggio chord."""

    repeat: Optional[int] = _UIntProperty()
    """Number of times a note is repeated."""

    time: Optional[float] = _FloatProperty()
    """Delay between two successive notes played."""

    gate: Optional[float] = _FloatProperty()
    """Results in a more staccato sound."""

    slide: Optional[bool] = _BoolProperty()
    """Whether arpeggio will slide between notes."""

direction: Optional[Direction] = _EnumProperty(Direction) class-attribute

range: Optional[int] = _UIntProperty() class-attribute

Range (in octaves).

chord: Optional[int] = _UIntProperty() class-attribute

Index of the selected arpeggio chord.

repeat: Optional[int] = _UIntProperty() class-attribute

Number of times a note is repeated.

time: Optional[float] = _FloatProperty() class-attribute

Delay between two successive notes played.

gate: Optional[float] = _FloatProperty() class-attribute

Results in a more staccato sound.

slide: Optional[bool] = _BoolProperty() class-attribute

Whether arpeggio will slide between notes.

ChannelDelay

Event information

Size: 20 (all 32 bit unsigned integers)

Structure:

Parameter Offset
feedback 0
pan 4
pitch_shift 8
echo 12
time 16

Bases: _FLObject

Used by Channel.delay.

Manual

Source code in pyflp/channel/delay.py
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
class ChannelDelay(_FLObject):
    """Used by `Channel.delay`.

    [Manual](https://www.image-line.com/fl-studio-learning/fl-studio-online-manual/html/chansettings_misc.htm#EchoDelay)
    """

    def _setprop(self, n: str, v: Any):
        self.__cde.dump(n, v)
        super()._setprop(n, v)

    feedback: Optional[int] = _IntProperty()

    pan: Optional[int] = _IntProperty()

    pitch_shift: Optional[int] = _IntProperty()

    echo: Optional[int] = _IntProperty()

    time: Optional[int] = _IntProperty()

    def _parse_data_event(self, e: ChannelDelayEvent) -> None:
        self.__cde = self._events["delay"] = e
        self._feedback = e.feedback
        self._pan = e.pan
        self._pitch_shift = e.pitch_shift
        self._echo = e.echo
        self._time = e.time

echo: Optional[int] = _IntProperty() class-attribute

feedback: Optional[int] = _IntProperty() class-attribute

pan: Optional[int] = _IntProperty() class-attribute

pitch_shift: Optional[int] = _IntProperty() class-attribute

time: Optional[int] = _IntProperty() class-attribute

ChannelEnvelopeLFO

Event information

Size: 68 (per parameter; occurs 5x per channel)

Structure:

Parameter Offset
__flags 0
enabled 4
env_predelay 8
env_attack 12
env_hold 16
env_decay 20
env_sustain 24
env_release 28
lfo_shape 52
env_att_tns 56
env_sus_tns 60
env_rel_tns 64

Note

__flags holds flags for lfo_synced and lfo_retrig properties.

Todo

Some properties are yet to be discovered.

Bases: _FLObject

Used by Channel._env_lfos.

Manual

Source code in pyflp/channel/envlfo.py
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
class ChannelEnvelopeLFO(_FLObject):
    """Used by `Channel._env_lfos`.

    [Manual](https://www.image-line.com/fl-studio-learning/fl-studio-online-manual/html/chansettings_ins.htm)"""  # noqa

    _AHDSR_VALIDATOR = _IntValidator(100, 65536)
    _TNS_VALIDATOR = _IntValidator(-128, 128)

    @enum.unique
    class LFOShape(enum.IntEnum):
        """See `ChannelEnvelope.lfo_shape`."""

        Sine = 0
        Triangle = 1
        Pulse = 2

    @enum.unique
    class _Flags(enum.IntFlag):
        """See `ChannelEnvelope.flags`."""

        LFOTempoSync = 1 << 1
        """See `ChannelEnvelope.lfo_synced`."""

        Unknown = 1 << 2
        """Occurs for volume envlope only."""

        LFORetrig = 1 << 5
        """See `ChannelEnvelope.lfo_retrig`."""

    def _setprop(self, n, v):
        self.__cel.dump(n, v)
        super()._setprop(n, v)

    lfo_synced: bool = _BoolProperty()
    """Whether LFO is synced with tempo."""

    lfo_retrig: bool = _BoolProperty()
    """Whether LFO is in retriggered mode."""

    enabled: bool = _BoolProperty()
    """Whether envelope section is enabled."""

    env_predelay: int = _UIntProperty(_AHDSR_VALIDATOR)
    """Min: 100 (0%), Max: 65536 (100%), Default: 100 (0%)."""

    env_attack: int = _UIntProperty(_AHDSR_VALIDATOR)
    """Min: 100 (0%), Max: 65536 (100%), Default: 20000 (31%)."""

    env_hold: int = _UIntProperty(_AHDSR_VALIDATOR)
    """Min: 100 (0%), Max: 65536 (100%), Default: 20000 (31%)."""

    env_decay: int = _UIntProperty(_AHDSR_VALIDATOR)
    """Min: 100 (0%), Max: 65536 (100%), Default: 30000 (46%)."""

    env_sustain: int = _UIntProperty(max_=128)
    """Min: 0 (0%), Max: 128 (100%), Default: 50 (39%)."""

    env_release: int = _UIntProperty(_AHDSR_VALIDATOR)
    """Min: 100 (0%), Max: 65536 (100%), Default: 20000 (31%)."""

    lfo_shape: LFOShape = _EnumProperty(LFOShape)
    """Sine, triangle or pulse. Default: `LFOShape.Sine`."""

    env_att_tns: int = _IntProperty(_TNS_VALIDATOR)
    """Attack tension. Min: -128 (-100%), Max: 128 (100%), Default: 0 (0%)."""

    env_sus_tns: int = _IntProperty(_TNS_VALIDATOR)
    """Sustain tension. Min: -128 (-100%), Max: 128 (100%), Default: 0 (0%)."""

    env_rel_tns: int = _IntProperty(_TNS_VALIDATOR)
    """Release tension.

    Min: -128 (-100%), Max: 128 (100%), Default: -101 / 0 (-79% / 0%)."""

    def _parse_data_event(self, e: ChannelEnvelopeLFOEvent) -> None:
        self.__cel = self._events["envlfo"] = e
        self._lfo_synced = e.lfo_synced
        self._lfo_retrig = e.lfo_retrig
        self._enabled = e.enabled
        self._env_predelay = e.env_predelay
        self._env_attack = e.env_attack
        self._env_hold = e.env_hold
        self._env_decay = e.env_decay
        self._env_sustain = e.env_sustain
        self._env_release = e.env_release
        self._lfo_shape = e.lfo_shape
        self._env_att_tns = e.env_att_tns
        self._env_sus_tns = e.env_sus_tns
        self._env_rel_tns = e.env_rel_tns

lfo_synced: bool = _BoolProperty() class-attribute

Whether LFO is synced with tempo.

lfo_retrig: bool = _BoolProperty() class-attribute

Whether LFO is in retriggered mode.

enabled: bool = _BoolProperty() class-attribute

Whether envelope section is enabled.

env_predelay: int = _UIntProperty(_AHDSR_VALIDATOR) class-attribute

Min: 100 (0%), Max: 65536 (100%), Default: 100 (0%).

env_attack: int = _UIntProperty(_AHDSR_VALIDATOR) class-attribute

Min: 100 (0%), Max: 65536 (100%), Default: 20000 (31%).

env_hold: int = _UIntProperty(_AHDSR_VALIDATOR) class-attribute

Min: 100 (0%), Max: 65536 (100%), Default: 20000 (31%).

env_decay: int = _UIntProperty(_AHDSR_VALIDATOR) class-attribute

Min: 100 (0%), Max: 65536 (100%), Default: 30000 (46%).

env_sustain: int = _UIntProperty(max_=128) class-attribute

Min: 0 (0%), Max: 128 (100%), Default: 50 (39%).

env_release: int = _UIntProperty(_AHDSR_VALIDATOR) class-attribute

Min: 100 (0%), Max: 65536 (100%), Default: 20000 (31%).

lfo_shape: LFOShape = _EnumProperty(LFOShape) class-attribute

Sine, triangle or pulse. Default: LFOShape.Sine.

env_att_tns: int = _IntProperty(_TNS_VALIDATOR) class-attribute

Attack tension. Min: -128 (-100%), Max: 128 (100%), Default: 0 (0%).

env_sus_tns: int = _IntProperty(_TNS_VALIDATOR) class-attribute

Sustain tension. Min: -128 (-100%), Max: 128 (100%), Default: 0 (0%).

env_rel_tns: int = _IntProperty(_TNS_VALIDATOR) class-attribute

Release tension.

Min: -128 (-100%), Max: 128 (100%), Default: -101 / 0 (-79% / 0%).

LFOShape

Bases: enum.IntEnum

See ChannelEnvelope.lfo_shape.

Source code in pyflp/channel/envlfo.py
120
121
122
123
124
125
126
@enum.unique
class LFOShape(enum.IntEnum):
    """See `ChannelEnvelope.lfo_shape`."""

    Sine = 0
    Triangle = 1
    Pulse = 2

Pulse = 2 class-attribute

Sine = 0 class-attribute

Triangle = 1 class-attribute

ChannelLevelOffsets

Event information

Size: 20 (all 32 bit signed integers)

Structure:

Parameter Offset
pan 0
volume 8
mod_x 12
mod_y 16

Bases: _FLObject

Used by Channel.delay.

Manual

Source code in pyflp/channel/level_offsets.py
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class ChannelLevelOffsets(_FLObject):
    """Used by `Channel.delay`.

    [Manual](https://www.image-line.com/fl-studio-learning/fl-studio-online-manual/html/chansettings_misc.htm#EchoDelay)
    """

    def _setprop(self, n, v):
        self.__cloe.dump(n, v)
        super()._setprop(n, v)

    pan = _IntProperty()

    volume = _IntProperty()

    mod_x = _IntProperty()

    mod_y = _IntProperty()

    def _parse_data_event(self, e: ChannelLevelOffsetsEvent) -> None:
        self.__cloe = self._events["delay"] = e
        self._pan = e.pan
        self._volume = e.volume
        self._mod_x = e.mod_x
        self._mod_y = e.mod_y

mod_x = _IntProperty() class-attribute

mod_y = _IntProperty() class-attribute

pan = _IntProperty() class-attribute

volume = _IntProperty() class-attribute

ChannelLevels

Event information

Size: 24 (all 32 bit signed integers)

Structure:

Parameter Offset
pan 0
volume 4
pitch_shift 8

Todo

Some properties are yet to be discovered.

Bases: _FLObject

Used by Channel.levels.

Source code in pyflp/channel/levels.py
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
class ChannelLevels(_FLObject):
    """Used by `Channel.levels`."""

    def _setprop(self, n, v):
        self.__cle.dump(n, v)
        super()._setprop(n, v)

    pan = _IntProperty()

    volume = _IntProperty()

    pitch_shift = _IntProperty()
    """Pitch shift (in cents)."""

    def _parse_data_event(self, e: ChannelLevelsEvent) -> None:
        self.__cle = self._events["levels"] = e
        self._pan = e.pan
        self._volume = e.volume
        self._pitch_shift = e.pitch_shift

pan = _IntProperty() class-attribute

pitch_shift = _IntProperty() class-attribute

Pitch shift (in cents).

volume = _IntProperty() class-attribute

ChannelPolyphony

Event information

Size: 9

Structure:

Parameter Offset Type
max 0 I
slide 4 I
flags 8 B

Bases: _FLObject

Used by Channel.polyphony. Implemented by ChannelPolyphonyEvent.

Manual

Source code in pyflp/channel/polyphony.py
 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
class ChannelPolyphony(_FLObject):
    """Used by `Channel.polyphony`. Implemented by `ChannelPolyphonyEvent`.

    [Manual](https://www.image-line.com/fl-studio-learning/fl-studio-online-manual/html/chansettings_misc.htm#Polyphony)
    """

    def _setprop(self, n, v):
        self.__cpe.dump(n, v)
        super()._setprop(n, v)

    @enum.unique
    class Flags(enum.IntFlag):
        """Used by `ChannelPolyphony.flags`."""

        None_ = 0
        """No options are enabled."""

        Mono = 1 << 0
        """**Mono** is enabled."""

        Porta = 1 << 1
        """**Porta** is enabled."""

        U1 = 1 << 2
        U2 = 1 << 3
        U3 = 1 << 4
        U4 = 1 << 5
        U5 = 1 << 6
        U6 = 1 << 7

    max: int = _IntProperty()
    """Maximum number of voices."""

    slide: int = _IntProperty()
    """Portamento time."""

    flags: Flags = _EnumProperty(Flags)
    """**Mono** and **Porta** buttons. See `ChannelPolyphonyFlags`."""

    def _parse_data_event(self, e: ChannelPolyphonyEvent) -> None:
        self.__cpe = self._events["polyphony"] = e
        self._max = e.max
        self._slide = e.slide
        self._flags = e.flags

flags: Flags = _EnumProperty(Flags) class-attribute

Mono and Porta buttons. See ChannelPolyphonyFlags.

max: int = _IntProperty() class-attribute

Maximum number of voices.

slide: int = _IntProperty() class-attribute

Portamento time.

Flags

Bases: enum.IntFlag

Used by ChannelPolyphony.flags.

Source code in pyflp/channel/polyphony.py
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
@enum.unique
class Flags(enum.IntFlag):
    """Used by `ChannelPolyphony.flags`."""

    None_ = 0
    """No options are enabled."""

    Mono = 1 << 0
    """**Mono** is enabled."""

    Porta = 1 << 1
    """**Porta** is enabled."""

    U1 = 1 << 2
    U2 = 1 << 3
    U3 = 1 << 4
    U4 = 1 << 5
    U5 = 1 << 6
    U6 = 1 << 7

Mono = 1 << 0 class-attribute

Mono is enabled.

None_ = 0 class-attribute

No options are enabled.

Porta = 1 << 1 class-attribute

Porta is enabled.

U1 = 1 << 2 class-attribute

U2 = 1 << 3 class-attribute

U3 = 1 << 4 class-attribute

U4 = 1 << 5 class-attribute

U5 = 1 << 6 class-attribute

U6 = 1 << 7 class-attribute

ChannelTracking

Event information

Size: 16 (all 32 bit signed integers)

Structure:

Parameter Offset
middle_value 0
pan 4
mod_x 8
mod_y 12

Bases: _FLObject

Used by Channel.tracking.

Manual

Source code in pyflp/channel/tracking.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
class ChannelTracking(_FLObject):
    """Used by `Channel.tracking`.

    [Manual](https://www.image-line.com/fl-studio-learning/fl-studio-online-manual/html/chansettings_misc.htm#Tracking)
    """

    def _setprop(self, n, v):
        self.__cte.dump(n, v)
        super()._setprop(n, v)

    middle_value: int = _IntProperty()

    pan: int = _IntProperty()

    mod_x: int = _IntProperty()

    mod_y: int = _IntProperty()

    def _parse_data_event(self, e: ChannelTrackingEvent) -> None:
        self.__cte = self._events["levels"] = e
        self._middle_value = e.middle_value
        self._pan = e.pan
        self._mod_x = e.mod_x
        self._mod_y = e.mod_y

middle_value: int = _IntProperty() class-attribute

mod_x: int = _IntProperty() class-attribute

mod_y: int = _IntProperty() class-attribute

pan: int = _IntProperty() class-attribute

ChannelFX

Bases: _FLObject

Sampler/Audio -> Pre-computed effects. Used by Channel.fx.

Manual

Source code in pyflp/channel/fx.py
 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
class ChannelFX(_FLObject):
    """Sampler/Audio -> Pre-computed effects. Used by `Channel.fx`.

    [Manual](https://www.image-line.com/fl-studio-learning/fl-studio-online-manual/html/chansettings_sampler.htm#channelsampler_Precomputed)
    """

    @enum.unique
    class EventID(enum.IntEnum):
        """Event IDs used by `ChannelFX`."""

        CutOff = WORD + 7
        """See `ChannelFX.cutoff`."""

        PreAmp = WORD + 10
        """See `ChannelFX.boost`."""

        FadeOut = WORD + 11
        """See `ChannelFX.fade_out`."""

        FadeIn = WORD + 12
        """See `ChannelFX.fade_in`."""

        Resonance = WORD + 19
        """See `ChannelFX.resonance`."""

        StereoDelay = WORD + 21
        """See `ChannelFX.stereo_delay`."""

        Reverb = DWORD + 11
        """See `ChannelFX.reverb` and `ChannelFXReverb`."""

    cutoff: Optional[int] = _UIntProperty(max_=1024)
    """Filter Mod X. Min = 0, Max = 1024, Default = 1024."""

    fade_in: Optional[int] = _UIntProperty(max_=1024)
    """Quick fade-in. Min = 0, Max = 1024, Default = 0."""

    fade_out: Optional[int] = _UIntProperty(max_=1024)
    """Quick fade-out. Min = 0, Max = 1024, Default = 0."""

    pre_amp: Optional[int] = _UIntProperty(max_=256)
    """Boost. Min: 0, Max: 256, Default: 0."""

    resonance: Optional[int] = _UIntProperty(max_=1024)
    """Filter Mod Y. Min = 0, Max = 1024, Default = 0."""

    @property
    def reverb(self) -> Optional[ChannelFXReverb]:
        """See `ChannelFXReverb`."""
        return getattr(self, "_reverb", None)

    stereo_delay: Optional[int] = _IntProperty()

    def _parse_word_event(self, e: _WordEvent) -> None:
        if e.id_ == ChannelFX.EventID.CutOff:
            self._parse_H(e, "cutoff")
        elif e.id_ == ChannelFX.EventID.PreAmp:
            self._parse_H(e, "pre_amp")
        elif e.id_ == ChannelFX.EventID.FadeOut:
            self._parse_H(e, "fade_out")
        elif e.id_ == ChannelFX.EventID.Resonance:
            self._parse_H(e, "resonance")
        elif e.id_ == ChannelFX.EventID.FadeIn:
            self._parse_H(e, "fade_in")
        elif e.id_ == ChannelFX.EventID.StereoDelay:
            self._parse_H(e, "stereo_delay")

    def _parse_dword_event(self, e: DWordEventType) -> None:
        if e.id_ == ChannelFX.EventID.Reverb:
            self._parse_flobject(e, "reverb", ChannelFXReverb())

cutoff: Optional[int] = _UIntProperty(max_=1024) class-attribute

Filter Mod X. Min = 0, Max = 1024, Default = 1024.

fade_in: Optional[int] = _UIntProperty(max_=1024) class-attribute

Quick fade-in. Min = 0, Max = 1024, Default = 0.

fade_out: Optional[int] = _UIntProperty(max_=1024) class-attribute

Quick fade-out. Min = 0, Max = 1024, Default = 0.

pre_amp: Optional[int] = _UIntProperty(max_=256) class-attribute

Boost. Min: 0, Max: 256, Default: 0.

resonance: Optional[int] = _UIntProperty(max_=1024) class-attribute

Filter Mod Y. Min = 0, Max = 1024, Default = 0.

stereo_delay: Optional[int] = _IntProperty() class-attribute

EventID

Bases: enum.IntEnum

Event IDs used by ChannelFX.

Source code in pyflp/channel/fx.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
@enum.unique
class EventID(enum.IntEnum):
    """Event IDs used by `ChannelFX`."""

    CutOff = WORD + 7
    """See `ChannelFX.cutoff`."""

    PreAmp = WORD + 10
    """See `ChannelFX.boost`."""

    FadeOut = WORD + 11
    """See `ChannelFX.fade_out`."""

    FadeIn = WORD + 12
    """See `ChannelFX.fade_in`."""

    Resonance = WORD + 19
    """See `ChannelFX.resonance`."""

    StereoDelay = WORD + 21
    """See `ChannelFX.stereo_delay`."""

    Reverb = DWORD + 11
    """See `ChannelFX.reverb` and `ChannelFXReverb`."""

CutOff = WORD + 7 class-attribute

See ChannelFX.cutoff.

FadeIn = WORD + 12 class-attribute

See ChannelFX.fade_in.

FadeOut = WORD + 11 class-attribute

See ChannelFX.fade_out.

PreAmp = WORD + 10 class-attribute

See ChannelFX.boost.

Resonance = WORD + 19 class-attribute

See ChannelFX.resonance.

Reverb = DWORD + 11 class-attribute

See ChannelFX.reverb and ChannelFXReverb.

StereoDelay = WORD + 21 class-attribute

See ChannelFX.stereo_delay.

reverb() property

See ChannelFXReverb.

Source code in pyflp/channel/fx.py
124
125
126
127
@property
def reverb(self) -> Optional[ChannelFXReverb]:
    """See `ChannelFXReverb`."""
    return getattr(self, "_reverb", None)

ChannelFXReverb

Bases: _FLObject

Sampler/Audio -> Pre-computed effects -> Reverb. Used by ChannelFX.reverb.

Manual

Source code in pyflp/channel/fx.py
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
class ChannelFXReverb(_FLObject):
    """Sampler/Audio -> Pre-computed effects -> Reverb. Used by `ChannelFX.reverb`.

    [Manual](https://www.image-line.com/fl-studio-learning/fl-studio-online-manual/html/chansettings_sampler.htm#channelsampler_Precomputed)
    """

    class _Mix(_UIntProperty):
        def __set__(self, obj: "ChannelFXReverb", value) -> None:

            # Update obj._kind and obj._mix
            super().__set__(obj, value)

            buf = (obj._kind + obj._mix).to_bytes(4, "little")
            obj._events["reverb"].dump(buf)

    class _Kind(_EnumProperty):
        def __set__(self, obj: "ChannelFXReverb", value) -> None:

            # Update obj._kind and obj._mix
            super().__set__(obj, value)

            buf = (obj._kind + obj._mix).to_bytes(4, "little")
            obj._events["reverb"].dump(buf)

    class Kind(enum.IntEnum):
        """Sampler/Audio Reverb type (A or B). Used by `kind`."""

        A = 0
        B = 65536

        @classmethod
        def default(cls):
            return cls.B

    kind: Optional[Kind] = _Kind(Kind)
    """See `Kind`."""

    mix: Optional[int] = _Mix(max_=256)
    """Reverb mix (dry/wet). Min: 0, Max: 256, Default: 0."""

    def _parse_dword_event(self, e: DWordEventType) -> None:
        self._events["reverb"] = e
        value = e.to_uint32()
        default = self.Kind.default()
        if value >= default:
            self._kind = self.Kind.B
            self._mix = value - default
        else:
            self._kind = self.Kind.A
            self._mix = value

kind: Optional[Kind] = _Kind(Kind) class-attribute

See Kind.

mix: Optional[int] = _Mix(max_=256) class-attribute

Reverb mix (dry/wet). Min: 0, Max: 256, Default: 0.

Filter

Bases: _FLObject

Channel display filter. Default: 'Unsorted', 'Audio' and 'Automation'. Used by Channel.filter_channel.

Source code in pyflp/channel/filter.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Filter(_FLObject):
    """Channel display filter. Default: 'Unsorted', 'Audio'
    and 'Automation'. Used by `Channel.filter_channel`."""

    @enum.unique
    class EventID(enum.IntEnum):
        """Event IDs used by `FilterChannel`."""

        Name = TEXT + 39
        """See `FilterChannel.name`."""

    name: str = _StrProperty()
    """Name of the filter channel."""

    def _parse_text_event(self, e: _TextEvent) -> None:
        if e.id_ == Filter.EventID.Name:
            self._parse_s(e, "name")

name: str = _StrProperty() class-attribute

Name of the filter channel.

EventID

Bases: enum.IntEnum

Event IDs used by FilterChannel.

Source code in pyflp/channel/filter.py
28
29
30
31
32
33
@enum.unique
class EventID(enum.IntEnum):
    """Event IDs used by `FilterChannel`."""

    Name = TEXT + 39
    """See `FilterChannel.name`."""

Name = TEXT + 39 class-attribute

See FilterChannel.name.