/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
***/
#ifndef OAK_EDITOR_AUDIO_PROCESSOR_H
#define OAK_EDITOR_AUDIO_PROCESSOR_H
#include
#include "error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file processor.h
* @brief C ABI for the oakaudio real-time resampler/format converter
* (olive::AudioProcessor).
*
* OakAudioProcessor follows the neutral by-value handle convention (see
* oakcommon's common/handle.h): oakaudio_processor_init() returns a handle
* whose underlying object has reference count 1, the addref and release
* function pointers adjust that count atomically (release destroys the
* object at zero), and abi_version is always OAKAUDIO_ABI_VERSION.
* Functions that only use a handle take it BY VALUE; an empty handle
* (ctx == NULL) is reported as OAKAUDIO_E_INVALID.
*
* Sample formats are passed as ints matching the
* olive::core::SampleFormat::Format enum values (invalid = -1, u8_p = 0,
* s16_p, s32_p, s64_p, f32_p, f64_p, u8, s16, s32, s64, f32, f64,
* count). Channel layouts are ffmpeg-style channel masks.
*/
typedef struct OakAudioProcessor {
void *ctx; /**< Opaque pointer to the reference-counted object. */
void (*addref)(void *ctx); /**< Atomically increments the count. */
void (*release)(void *ctx); /**< Decrements the count, destroys at 0. */
uint32_t abi_version; /**< OAKAUDIO_ABI_VERSION. */
} OakAudioProcessor;
/** oakaudio_processor_convert() delivers planar 32-bit float output. */
#define OAKAUDIO_PROCESSOR_OUTPUT_FORMAT 4 /**< SampleFormat::f32_p. */
/**
* @brief Create a closed audio processor (count 1).
*
* @return Handle with reference count 1; ctx is NULL on allocation
* failure.
*/
OAKAUDIO_API OakAudioProcessor oakaudio_processor_init(void);
/**
* @brief Release one reference to a processor.
*
* Convenience wrapper around self->release(self->ctx); nulls self->ctx.
* No-op when self is NULL or self->ctx is NULL.
*/
OAKAUDIO_API void oakaudio_processor_free(OakAudioProcessor *self);
/**
* @brief Open the resampling/format-conversion graph.
*
* out_format is accepted for interface completeness but the conversion
* output is always planar 32-bit float (see
* OAKAUDIO_PROCESSOR_OUTPUT_FORMAT); passing any other format returns
* OAKAUDIO_E_INVALID. A channel layout mask of 0 falls back to the
* default layout for the channel count (stereo when unknown), matching
* the C++ implementation.
*
* @param speed Tempo factor (1.0 = unchanged).
* @return OAKAUDIO_OK, OAKAUDIO_E_STATE when already open,
* OAKAUDIO_E_INVALID for bad arguments, or OAKAUDIO_E_FAILED when
* the filter graph could not be created.
*/
OAKAUDIO_API int oakaudio_processor_open(OakAudioProcessor self,
int in_rate, uint64_t in_layout, int in_format,
int out_rate, uint64_t out_layout, int out_format, double speed);
/**
* @brief Close the graph (safe when closed; self must be non-empty).
*/
OAKAUDIO_API int oakaudio_processor_close(OakAudioProcessor self);
/**
* @brief 1 when open, 0 when closed, OAKAUDIO_E_INVALID for empty handle.
*/
OAKAUDIO_API int oakaudio_processor_is_open(OakAudioProcessor self);
/**
* @brief Push planar float input and pull converted output.
*
* @param in_planar Per-channel float input planes (in channel count);
* NULL with in_frame_count == 0 only pulls pending output.
* @param in_frame_count Frames per input channel.
* @param out_planar Per-channel float output planes (out channel count);
* NULL to discard/pull nothing (returns 0).
* @param out_capacity_frames Capacity of each output plane in frames.
* @return Number of output frames written (>= 0), or a negative
* OAKAUDIO_E_* code. Output is clamped to out_capacity_frames;
* remaining frames stay queued in the graph.
*/
OAKAUDIO_API int oakaudio_processor_convert(OakAudioProcessor self,
const float *const *in_planar, int in_frame_count,
float *const *out_planar, int out_capacity_frames);
/**
* @brief Signal end-of-input to the graph (flushes internal delay).
*/
OAKAUDIO_API int oakaudio_processor_flush(OakAudioProcessor self);
#ifdef __cplusplus
}
#endif
#endif //OAK_EDITOR_AUDIO_PROCESSOR_H