UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
radaudio_encoder.h
Go to the documentation of this file.
1// Copyright Epic Games Tools, LLC. All Rights Reserved.
2#ifndef INCLUDE_RADAUDIO_ENCODER_H
3#define INCLUDE_RADAUDIO_ENCODER_H
4
5#include "egttypes.h"
6#include <stddef.h>
7
8// for feedback to user. actual rate varies, and is sample rate dependent
9// the 0th value is support but should never be used; it allows you to hear what the native artifacts sound like
10static const int approximate_data_rate_for_quality_setting_in_kilobits[2][10] =
11{
12 { 30, 36, 39, 43, 48, 55, 65, 85,125,205 }, // mono (@TODO: measure these, currently just ~half of stereo)
13 { 55, 64, 72, 80, 90,100,120,160,240,400 }, // stereo
14};
15
16// encode context
17typedef struct
18{
19 // placeholder fields to make it large enough
20 RAD_U64 dummy[200];
21 U8 buffer[5000];
23
24#define RADAUDIOENC_AT_EOF 0
25#define RADAUDIOENC_INSUFFICIENT_BUFFER -1
26#define RADAUDIOENC_INTERNAL_ERROR -2
27#define RADAUDIOENC_MAX_OUTPUT_SAMPLES_PER_CHANNEL_PER_CHUNK 1024
28
30
31// RADAUDIO compatibility version - if these are the same the exports are named the same so we expect
32// that if the linker selects a different copy they all work.
33#define RADAUDIO_ENC_LIBRARY_VERSION 1
34
35#ifndef RR_STRING_JOIN3
36#define RR_STRING_JOIN3(arg1, arg2, arg3) RR_STRING_JOIN_DELAY3(arg1, arg2, arg3)
37#define RR_STRING_JOIN_DELAY3(arg1, arg2, arg3) RR_STRING_JOIN_IMMEDIATE3(arg1, arg2, arg3)
38#define RR_STRING_JOIN_IMMEDIATE3(arg1, arg2, arg3) arg1 ## arg2 ## arg3
39#endif
40
41#ifdef RADAUDIO_WRAP
42#define RADAUDIO_ENC_NAME(name) RR_STRING_JOIN3(RADAUDIO_WRAP, name##_, RADAUDIO_ENC_LIBRARY_VERSION )
43#else
44#define RADAUDIO_ENC_NAME(name) RR_STRING_JOIN( name##_, RADAUDIO_ENC_LIBRARY_VERSION )
45#endif
46
47#define radaudio_encode_create RADAUDIO_ENC_NAME(radaudio_encode_create)
48#define radaudio_encode_block RADAUDIO_ENC_NAME(radaudio_encode_block)
49#define radaudio_encode_create_internal RADAUDIO_ENC_NAME(radaudio_encode_create_internal)
50#define RadAudioCompressGetProfileData RADAUDIO_ENC_NAME(RadAudioCompressGetProfileData)
51#define radaudio_determine_preferred_next_block_length RADAUDIO_ENC_NAME(radaudio_determine_preferred_next_block_length)
52#define radaudio_determine_preferred_first_block_length RADAUDIO_ENC_NAME(radaudio_determine_preferred_first_block_length)
53#define radaudio_encode_block_ext RADAUDIO_ENC_NAME(radaudio_encode_block_ext)
54
55// radaudio_encode_create()
56//
57// Creates a new RADaudio encoder.
58//
59// Pass in an uninitialized radaudio_encoder structure, space to output the stream header,
60// and then a description of the stream and the quality settings desired.
61//
62// - `num_channels` must be 1 or 2
63// - `sample_rate` must be 48000, 44100, 32000, or 24000
64// - if the automated quality measurement is to be trusted, then 32K and 24K encodings are
65// lower quality at same size than converting the files to 44.1K or 48K
66// (but ogg vorbis shows same behavior, so maybe automatic quality measurement is wrong for 32K and 24K)
67// - `quality` should be 1..9.
68// - larger values are higher quality and larger files
69// - 5 is recommended setting; it gives comparable results to vorbis 96 kbps
70// - going above 5 gives larger, higher quality files; could default to 6 if paranoid
71// - settings below 5 have not been tuned, as they are not expected to be "transparent" quality
72// - they are only provided for people who want to experiment and explore what it sounds like
73// - `header` is a buffer to store the header
74// - supply RADAUDIO_STREAM_HEADER_MAX
75// - the actual size of the header is returned
76//
77// returns size of header on success, otherwise returns 0
78//
79// there is no destroy() function as the structure holds no other resources
80// just free the memory you passed in as necessary
81#define RADAUDIO_STREAM_HEADER_MAX 128
84 int num_channels,
85 int sample_rate,
86 int quality,
87 U32 flags);
88
89#define RADAUDIO_ENC_FLAG_improve_seamless_loop 1 // actually boosts precision of short block low-frequency coefficients
90
91
92// radaudio_encode_block()
93//
94// Generate a block of audio data in RADaudio format.
95//
96// Pass in a radaudio_encoder initialized by radaudio_encode_init.
97//
98// - `encode_buffer` : storage where the encoder will write compressed data
99// - `encode_buffer_max` : size of encode buffer
100// - `input` : an array of audio samples
101// - values from [-1..1] (can exceed this range, but will distort if you go too far)
102// - for stereo input, interleave the channels in a single array
103// - `input_len` : the number of mono samples or stereo sample pairs in the input
104// - `offset` : the current encoding offset within the input buffer (in mono samples or stereo pairs)
105// - initialize to 0 for the first call
106// - the encoder will encode samples in the range up to [offset-1024, offset+1024)
107// - the encoder will potentially look at samples up to [offset-1024, offset+2047)
108// - the encoder will update `*offset` to reflect the number of samples partially encoded
109// - samples up to `*offset` are only fully encoded after the NEXT encoder step
110//
111// returns:
112// n > 0 number of bytes of data output for this block
113// RADAUDIOENC_AT_EOF at end of stream, previously generated block is last block
114// RADAUDIOENC_INSUFFICIENT_BUFFER if output buffer isn't large enough
115// RADAUDIOENC_INTERNAL_ERROR an internal error occurred. this is probably a bug
117 float *input,
118 size_t input_len, // in samples (stereo pairs count as one)
119 size_t *offset , // in samples (stereo pairs count as one)
120 unsigned char *encode_buffer, // recommend MAX_ENCODED_BLOCK_SIZE
121 size_t encode_buffer_size);
122// In normal use, just load an audio file, convert to float, and pass the obvious
123// values to input / input_len, and allow the encoder to control the value of `*offset`.
124//
125// It is possible to use this API to stream input data by controlling
126// `input`, `input_len, and `*offset`.
127//
128// - you can freely manipulate the value of `*offset`.
129// - the encoder will look at samples i in [*offset-1024, *offset+1024)
130// - with the caveat that 0 <= i < input_len (samples outside this range are treated as 0, and reaching input_len ends the stream)
131// - The initial value of `*offset` must be 0.
132//
133// So, you could do something like:
134//
135// - Keep track of the actual offset within the file where `*offset` indexes; call this `fo`, set to 0.
136// - Iterate:
137// - set `*offset` to 1024, so [input..input+2048) is used, aka input[offset-1024, offset+1024)
138// - set `input_len` = subtract `fo` from the actual length of the file in mono samples or stereo pairs, add *offset
139// - load the file data from [fo-1024,fo+1024) into input[0..2048)
140// - encode a block
141// - update `fo` by the delta change in `*offset`
142// - note that the encoder will read the overlapping samples in each pair of successive blocks
143// - it is crucial that those samples be identical each time
144// - the naive approach, and the above strategy, both make sure this happens
145
146#define MAX_ENCODED_BLOCK_SIZE 5000 // 5000 plus slop due to forgetting to count stuff
147// upper bound on largest size; in reality, 400 Kbps is less than 2KB per block
148//
149// largest possible block:
150// max header size => 8 bytes
151// 48 largest-encoding band exponents@11b => 480 + 48 bits
152// 48 largest-encoding band mantissa @16b => 96 bytes
153// 112 largest-encoding subbands @11b => 1120 + 112 bits
154// 1536 run-length entries of 0 => 1536 bits
155// run-length end of stream code @7b => 7 bits
156// 512 1-bit coefficient locations w/huff => 576 bits
157// 1024 signals for 1-byte coefficients@11b => 10240 + 1024 bits
158// 2048 coefficients encoded 11 bits => 20480 + 2048 bits
159// 3 streams of padding => 3 bytes
160// 32320 + 5351 bits + 107 bytes
161// == 4816 bytes
162
163typedef enum
164{
167
168 // radaudio_encode_block_ext only
169 RADAUDIO_BLOCKTYPE_default = 0 // use transient detector like normal
171
172typedef struct
173{
174 radaudio_blocktype force_first_blocktype; // only used on first call
176
177 // you can achieve seamless looping using the following fields:
178 // use this as the data to pad the beginning and/or end of the stream with, instead of 0s
180 size_t padding_len; // in samples (stereo pairs count as one). Set to 0 to disable.
181 //
182 // At the beginning and end of the stream, based on offset going from 0..input_len, the above
183 // data will be used to "pad" the audio stream instead of the 0 value used by default.
184 //
185 // - at the beginning of the stream, the END of the padding block will be used, pushed up against the start of the stream audio
186 // - at the end of the stream, the BEGINNING of the padding block will be used, pushed right up against the end of the stream audio
187 //
188 // for best results when looping, supply 2048 samples, or the entire stream if the stream is shorter than 2048 samples.
189 // the above logic should do the right thing if the entire stream is very small, even smaller than a block
190 //
191 // In theory the logic should be something like this (assuming the stream is > 2048 samples):
192 // if (offset < 1024)
193 // point padding at end of stream
194 // if (offset > length-2048)
195 // point padding at beginning of stream
196 //
197 // In theory the padding data should only be needed in the first block and the last two blocks, but
198 // in debugging I actually saw the data accessed in the last 3 blocks. I didn't investigate since the
199 // output was correct, but I suspect when this happened it was on short/long block transitions in which
200 // the data in the third-to-last-block was used but windowed to 0 anyway, so it wouldn't matter if it
201 // wasn't available. Also because it requires a short/long transition the above logic should cover the
202 // case anyway. But maybe I'm misunderstanding and the end logic might need to be triggered further from the end--stb
204
206 float *input,
207 size_t input_len, // in samples (stereo pairs count as one)
208 size_t *offset , // in samples (stereo pairs count as one)
209 unsigned char *encode_buffer, // recommend MAX_ENCODED_BLOCK_SIZE
210 size_t encode_buffer_size,
212
213// determine the preferred blocktype for the first block in the stream;
214// pass this in as radaudio_encode_info.force_first_blocktype.
215// you can specify a different value than this function returns by overriding radaudio_encode_info,
216// but specifying long when short is requested will decrease quality, and
217// specifying short when long is requested will increase rate
219 F32 *input,
220 size_t input_len);
221
222// determine the preferred blocktype for the next block in the stream;
223// this is stateful; it assumes `offset` points into the middle of the block to encode, as described for encode_block
224// you can specify a different value than this function returns by overriding radaudio_encode_info,
225// but specifying long when short is requested will decrease quality, and
226// specifying short when long is requested will increase rate
229 F32 *input,
230 size_t input_len,
231 size_t offset);
232
233
235
236#endif//INCLUDE_RADAUDIO_ENCODER_H
#define RADDEFEND
Definition egttypes.h:68
RAD_U32 U32
Definition egttypes.h:501
RAD_U8 U8
Definition egttypes.h:481
#define RADDEFSTART
Definition egttypes.h:67
#define RADDEFFUNC
Definition egttypes.h:66
#define RAD_U64
Definition egttypes.h:464
RAD_F32 F32
Definition egttypes.h:516
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define radaudio_determine_preferred_first_block_length
Definition radaudio_encoder.h:52
#define radaudio_determine_preferred_next_block_length
Definition radaudio_encoder.h:51
#define radaudio_encode_create
Definition radaudio_encoder.h:47
#define radaudio_encode_block
Definition radaudio_encoder.h:48
#define RADAUDIO_STREAM_HEADER_MAX
Definition radaudio_encoder.h:81
radaudio_blocktype
Definition radaudio_encoder.h:164
@ RADAUDIO_BLOCKTYPE_default
Definition radaudio_encoder.h:169
@ RADAUDIO_BLOCKTYPE_short
Definition radaudio_encoder.h:165
@ RADAUDIO_BLOCKTYPE_long
Definition radaudio_encoder.h:166
#define radaudio_encode_block_ext
Definition radaudio_encoder.h:53
Definition radaudio_encoder.h:173
size_t padding_len
Definition radaudio_encoder.h:180
F32 * padding
Definition radaudio_encoder.h:179
radaudio_blocktype force_next_blocktype
Definition radaudio_encoder.h:175
radaudio_blocktype force_first_blocktype
Definition radaudio_encoder.h:174
Definition radaudio_encoder.h:18