137 lines
6.1 KiB
C
137 lines
6.1 KiB
C
/*
|
|
* joc_stream.h -- streaming (push/pull) interface of the JustOneCacophony core.
|
|
*
|
|
* This is the narrow, embedder-facing surface: a player or decoder component
|
|
* includes only this header. It is the same shared library as joc_core.h, split
|
|
* so an integrator never has to see the bitstream/verification tier.
|
|
*
|
|
* A stream is a stateful instance for hosts that cannot wait for a whole file:
|
|
* the caller feeds E-AC-3 bytes and the core PCM of the same frames (or already
|
|
* rebuilt objects16) and pulls rendered PCM as soon as it is available. It
|
|
* mirrors the two library shapes a decoder library normally offers: this
|
|
* push/pull form for host-owned I/O, and joc_task_execute() in joc_core.h for
|
|
* library-owned file I/O.
|
|
*
|
|
* Contract:
|
|
* - all state is instance-private, so several streams coexist;
|
|
* - a stream is NOT thread safe: push and pull must come from one thread;
|
|
* - rendering is stateful (matrix interpolation, gain ramps, room tail), so a
|
|
* new position on the timeline requires decoding to continue from the start
|
|
* of the stream; there is no seek in this version;
|
|
* - the kernel latency is 961 samples for speaker/binaural output: the first
|
|
* pull after two 512-sample blocks, and flush() drains the binaural tail.
|
|
*/
|
|
#pragma once
|
|
|
|
#include "joc_core.h"
|
|
|
|
/* JOC_STATIC (building the sources directly into an application): joc_core.h above already installs the empty JOC_API. */
|
|
#if defined(JOC_STATIC) && !defined(JOC_API)
|
|
#define JOC_API
|
|
#define JOC_CALL __cdecl
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef struct joc_stream joc_stream;
|
|
|
|
typedef enum joc_stream_input {
|
|
JOC_STREAM_IN_EAC3 = 0, /* bare E-AC-3 syncframes (the metadata stream) */
|
|
JOC_STREAM_IN_PCM_OBJECTS16 = 1, /* 16-channel objects16, decoded by the host */
|
|
JOC_STREAM_IN_CORE_PCM = 3 /* the 5.1 core PCM of the pushed E-AC-3 frames */
|
|
} joc_stream_input;
|
|
|
|
typedef enum joc_stream_output {
|
|
JOC_STREAM_OUT_PCM_OBJECTS16 = 0, /* planar [16][samples] float32 */
|
|
JOC_STREAM_OUT_SPEAKER = 1, /* interleaved [samples][channels] f32 */
|
|
JOC_STREAM_OUT_BINAURAL = 2 /* interleaved [samples][2] f32 */
|
|
} joc_stream_output;
|
|
|
|
typedef struct joc_stream_config {
|
|
uint32_t struct_size;
|
|
uint32_t struct_version;
|
|
uint32_t input;
|
|
uint32_t output;
|
|
const char* speaker_layout_name;
|
|
uint32_t speaker_metadata_offset; /* default 1473 */
|
|
uint32_t binaural_mode; /* near|mid|far; 0 means mid */
|
|
const char* hrtf_path; /* binaural only */
|
|
const char* kernels_path; /* binaural only */
|
|
double binaural_tail_seconds; /* default 5.0 */
|
|
uint32_t object_delay_samples; /* default 1473 */
|
|
double gain_db; /* default 0 */
|
|
uint32_t native_threads;
|
|
uint32_t reserved;
|
|
/* Binaural HRTF input, the same three shapes joc_task_config accepts: when
|
|
* hrtf_sofa_path is set the library compiles it with hrtf_cache_policy /
|
|
* hrtf_cache_dir / hrtf_radius_m and hrtf_path is unused; when
|
|
* personalized_headphone_path is set the Rosella runtime renders instead.
|
|
* hrtf_path stays the fallback/advanced input that reads a .jochrtf directly. */
|
|
const char* hrtf_sofa_path; /* SOFA SimpleFreeFieldHRIR input */
|
|
const char* personalized_headphone_path; /* Rosella .personalized_headphone input */
|
|
const char* hrtf_cache_dir; /* disk cache directory for SOFA compilation */
|
|
uint32_t hrtf_cache_policy; /* joc_hrtf_cache_policy: 0 none, 1 memory, 2 disk */
|
|
double hrtf_radius_m; /* SOFA measurement-radius shell, default 1.0 */
|
|
} joc_stream_config;
|
|
|
|
typedef struct joc_stream_buffer {
|
|
uint32_t struct_size;
|
|
uint32_t struct_version;
|
|
uint32_t kind; /* which joc_stream_input/output this buffer carries */
|
|
uint32_t channels;
|
|
uint32_t sample_rate;
|
|
uint32_t sample_count; /* in: capacity / out: produced (per channel) */
|
|
uint32_t byte_count; /* in: capacity / out: consumed or produced bytes */
|
|
uint32_t reserved;
|
|
const uint8_t* bytes; /* EAC3 input */
|
|
const float* pcm; /* PCM input */
|
|
uint8_t* out_bytes; /* reserved for encoded outputs */
|
|
float* out_pcm; /* PCM output */
|
|
} joc_stream_buffer;
|
|
|
|
typedef struct joc_stream_status_info {
|
|
uint32_t struct_size;
|
|
uint32_t struct_version;
|
|
uint64_t frames_in;
|
|
uint64_t frames_out;
|
|
uint64_t samples_in;
|
|
uint64_t samples_out;
|
|
uint64_t bytes_in;
|
|
uint64_t buffered_samples; /* rendered but not yet pulled, per channel */
|
|
uint64_t oamd_payloads;
|
|
uint64_t oamd_transitions;
|
|
uint32_t output_channels;
|
|
uint32_t ended; /* 1 after flush() */
|
|
} joc_stream_status_info;
|
|
|
|
JOC_API joc_error JOC_CALL joc_stream_create(const joc_stream_config* config, joc_stream** out);
|
|
|
|
/* Feeds one buffer. Kind selects the path: EAC3 bytes, the core PCM of those
|
|
* frames, or objects16. Consumed counts are reported so a caller can resume
|
|
* from a partial push. */
|
|
JOC_API joc_error JOC_CALL joc_stream_push(joc_stream* stream, const joc_stream_buffer* input,
|
|
uint32_t* consumed_samples, uint32_t* consumed_bytes);
|
|
|
|
/* Copies as many rendered samples as fit into `output` (interleaved, or planar
|
|
* for PCM_OBJECTS16) and reports how many were produced; 0 means "push more". */
|
|
JOC_API joc_error JOC_CALL joc_stream_pull(joc_stream* stream, joc_stream_buffer* output,
|
|
uint32_t* produced_samples);
|
|
|
|
/* Marks the end of input and drains whatever the renderer still holds (the
|
|
* binaural room tail); pull the remaining samples afterwards. */
|
|
JOC_API joc_error JOC_CALL joc_stream_flush(joc_stream* stream);
|
|
|
|
/* Returns the instance to its initial state (kernel, ramps, timeline, room,
|
|
* parser, counters) so the same stream can be reused for another pass. */
|
|
JOC_API joc_error JOC_CALL joc_stream_reset(joc_stream* stream);
|
|
|
|
JOC_API joc_error JOC_CALL joc_stream_status(const joc_stream* stream,
|
|
joc_stream_status_info* out);
|
|
JOC_API joc_error JOC_CALL joc_stream_destroy(joc_stream* stream);
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|