---
title: "channel"
description: "The channel namespace — the engine's Luau API reference for channel."
section: "API Reference"
slug: "api-channel"
canonical: "https://origozero.ai/docs/api-channel"
updated: "2026-09-05T23:13:46.274362702+00:00"
tags: ["api", "reference"]
---

# channel

The `channel` namespace — 19 functions.

## globals/channel/create {#globals-channel-create}

```lua
channel.create(opts: ChannelOpts) -> number?
```

Register a keyframe channel. `times` is the sorted keyframe
time array; `values` is the packed value array (layout depends
on `interp`); `stride` is the floats-per-sample width; `interp`
is `"step"` | `"linear"` | `"slerp"` | `"cubicHermite"`. Returns
the channel handle, or nil on malformed input.

**Parameters**

- `opts` `ChannelOpts` — `{ times, values, stride, interp }`.

**Returns** `number?` — Channel handle, or nil.

```lua
local h = channel.create({ times = ts, values = vs, stride = 3, interp = "linear" })
```

## globals/channel/destroy {#globals-channel-destroy}

```lua
channel.destroy(handle: number) -> boolean
```

Drop the channel from the registry.

**Parameters**

- `handle` `number` — Channel handle.

**Returns** `boolean` — True if the channel existed and was removed.

## globals/channel/sampleInto {#globals-channel-sampleinto}

```lua
channel.sampleInto(ch: number, time: number, buf: Substrate.TypedBuffer, offset: number) -> boolean
```

Sample the channel at `time` and write `stride` floats into
the buffer starting at f32 index `offset`. Returns false
on unknown handle, layout mismatch, or out-of-bounds; the
buffer is unchanged on failure.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time in seconds.
- `buf` `Substrate.TypedBuffer` — The buffer written into.
- `offset` `number` — Starting f32 index in the buffer.

**Returns** `boolean` — True on success.

## globals/channel/sampleManyInto {#globals-channel-samplemanyinto}

```lua
channel.sampleManyInto(ch: number, time: number, buf: Substrate.TypedBuffer, offsets: { number }) -> boolean
```

Sample once, blit the result into every position in
`offsets`. Saves the per-offset binary search when one channel
feeds many bones / particles / parameters.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time in seconds.
- `buf` `Substrate.TypedBuffer` — The buffer written into.
- `offsets` `{ number }` — Array of f32 indices.

**Returns** `boolean` — True on success.

## globals/channel/sampleQuat {#globals-channel-samplequat}

```lua
channel.sampleQuat(ch: number, time: number) -> (number?, number?, number?, number?)
```

Convenience accessor for stride-4 quaternion channels.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time.

**Returns** `(number?, number?, number?, number?)` — `(x, y, z, w)` or nil.

## globals/channel/sampleVec3 {#globals-channel-samplevec3}

```lua
channel.sampleVec3(ch: number, time: number) -> (number?, number?, number?)
```

Convenience accessor for stride-3 channels. Returns the
three components as multiret, or nil if the channel is
unknown / has a different stride.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time.

**Returns** `(number?, number?, number?)` — `(x, y, z)` or nil.

```lua
local x, y, z = channel.sampleVec3(h, t)
```

## modules/channel/README {#modules-channel-readme}

```lua
require("@builtin/modules/api/engine/channel") -- channel (also available as global 'channel')
```

Keyframe-channel sampling primitives — registry + sampleInto variants. Public Luau surface over the `__channel` Internal FFI namespace.

Usage: local channel = require("@builtin/modules/api/engine/channel")
Also available as global: channel

## modules/channel/create {#modules-channel-create}

```lua
create(opts: ChannelOpts): number?
```

Register a keyframe channel. `times` is the sorted keyframe
time array; `values` is the packed value array (layout depends
on `interp`); `stride` is the floats-per-sample width; `interp`
is `"step"` | `"linear"` | `"slerp"` | `"cubicHermite"`. Returns
the channel handle, or nil on malformed input.

**Parameters**

- `opts` `ChannelOpts` — `{ times, values, stride, interp }`.

```lua
local h = channel.create({ times = ts, values = vs, stride = 3, interp = "linear" })
```

## modules/channel/destroy {#modules-channel-destroy}

```lua
destroy(handle: number): boolean
```

Drop the channel from the registry.

**Parameters**

- `handle` `number` — Channel handle.

## modules/channel/sampleInto {#modules-channel-sampleinto}

```lua
sampleInto(ch: number, time: number, buf: Substrate.TypedBuffer, offset: number): boolean
```

Sample the channel at `time` and write `stride` floats into
the buffer starting at f32 index `offset`. Returns false
on unknown handle, layout mismatch, or out-of-bounds; the
buffer is unchanged on failure.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time in seconds.
- `buf` `Substrate.TypedBuffer` — The buffer written into.
- `offset` `number` — Starting f32 index in the buffer.

## modules/channel/sampleManyInto {#modules-channel-samplemanyinto}

```lua
sampleManyInto(ch: number, time: number, buf: Substrate.TypedBuffer, offsets: { number }): boolean
```

Sample once, blit the result into every position in
`offsets`. Saves the per-offset binary search when one channel
feeds many bones / particles / parameters.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time in seconds.
- `buf` `Substrate.TypedBuffer` — The buffer written into.
- `offsets` `{ number }` — Array of f32 indices.

## modules/channel/sampleQuat {#modules-channel-samplequat}

```lua
sampleQuat(ch: number, time: number): (number?, number?, number?, number?)
```

Convenience accessor for stride-4 quaternion channels.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time.

## modules/channel/sampleVec3 {#modules-channel-samplevec3}

```lua
sampleVec3(ch: number, time: number): (number?, number?, number?)
```

Convenience accessor for stride-3 channels. Returns the
three components as multiret, or nil if the channel is
unknown / has a different stride.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time.

```lua
local x, y, z = channel.sampleVec3(h, t)
```

## typed/builtin//modules/api/engine/channel/channel/create {#typed-builtin-modules-api-engine-channel-channel-create}

```lua
channel.create(opts: ChannelOpts) -> number?
```

Register a keyframe channel. `times` is the sorted keyframe
time array; `values` is the packed value array (layout depends
on `interp`); `stride` is the floats-per-sample width; `interp`
is `"step"` | `"linear"` | `"slerp"` | `"cubicHermite"`. Returns
the channel handle, or nil on malformed input.

**Parameters**

- `opts` `ChannelOpts` — `{ times, values, stride, interp }`.

**Returns** `number?` — Channel handle, or nil.

```lua
local h = channel.create({ times = ts, values = vs, stride = 3, interp = "linear" })
```

## typed/builtin//modules/api/engine/channel/channel/destroy {#typed-builtin-modules-api-engine-channel-channel-destroy}

```lua
channel.destroy(handle: number) -> boolean
```

Drop the channel from the registry.

**Parameters**

- `handle` `number` — Channel handle.

**Returns** `boolean` — True if the channel existed and was removed.

## typed/builtin//modules/api/engine/channel/channel/sampleInto {#typed-builtin-modules-api-engine-channel-channel-sampleinto}

```lua
channel.sampleInto(ch: number, time: number, buf: Substrate.TypedBuffer, offset: number) -> boolean
```

Sample the channel at `time` and write `stride` floats into
the buffer starting at f32 index `offset`. Returns false
on unknown handle, layout mismatch, or out-of-bounds; the
buffer is unchanged on failure.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time in seconds.
- `buf` `Substrate.TypedBuffer` — The buffer written into.
- `offset` `number` — Starting f32 index in the buffer.

**Returns** `boolean` — True on success.

## typed/builtin//modules/api/engine/channel/channel/sampleManyInto {#typed-builtin-modules-api-engine-channel-channel-samplemanyinto}

```lua
channel.sampleManyInto(ch: number, time: number, buf: Substrate.TypedBuffer, offsets: { number }) -> boolean
```

Sample once, blit the result into every position in
`offsets`. Saves the per-offset binary search when one channel
feeds many bones / particles / parameters.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time in seconds.
- `buf` `Substrate.TypedBuffer` — The buffer written into.
- `offsets` `{ number }` — Array of f32 indices.

**Returns** `boolean` — True on success.

## typed/builtin//modules/api/engine/channel/channel/sampleQuat {#typed-builtin-modules-api-engine-channel-channel-samplequat}

```lua
channel.sampleQuat(ch: number, time: number) -> (number?, number?, number?, number?)
```

Convenience accessor for stride-4 quaternion channels.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time.

**Returns** `(number?, number?, number?, number?)` — `(x, y, z, w)` or nil.

## typed/builtin//modules/api/engine/channel/channel/sampleVec3 {#typed-builtin-modules-api-engine-channel-channel-samplevec3}

```lua
channel.sampleVec3(ch: number, time: number) -> (number?, number?, number?)
```

Convenience accessor for stride-3 channels. Returns the
three components as multiret, or nil if the channel is
unknown / has a different stride.

**Parameters**

- `ch` `number` — Channel handle.
- `time` `number` — Sample time.

**Returns** `(number?, number?, number?)` — `(x, y, z)` or nil.

```lua
local x, y, z = channel.sampleVec3(h, t)
```
