Initial pure C++ implementation
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
#include "speaker/speaker_step.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace joc::speaker {
|
||||
|
||||
Status step(SpeakerStep* context, const std::vector<float>& objects16_planar,
|
||||
const oamd::OamdUpdate* update, std::string* error) {
|
||||
if (context == nullptr || context->handle == nullptr) {
|
||||
return Status::fail(JOC_ERR_STATE, stage::kRender, "speaker renderer is not open");
|
||||
}
|
||||
if (objects16_planar.size() !=
|
||||
static_cast<std::size_t>(JOC_OUTPUT_CHANNELS) * JOC_FRAME_SAMPLES) {
|
||||
return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kRender,
|
||||
"objects16 must be [16][1536]");
|
||||
}
|
||||
context->interleaved.assign(static_cast<std::size_t>(JOC_FRAME_SAMPLES) * JOC_OUTPUT_CHANNELS,
|
||||
0.0f);
|
||||
for (std::size_t n = 0; n < JOC_FRAME_SAMPLES; ++n) {
|
||||
for (std::size_t c = 0; c < JOC_OUTPUT_CHANNELS; ++c) {
|
||||
context->interleaved[n * JOC_OUTPUT_CHANNELS + c] =
|
||||
objects16_planar[c * JOC_FRAME_SAMPLES + n];
|
||||
}
|
||||
}
|
||||
context->output.assign(
|
||||
static_cast<std::size_t>(JOC_FRAME_SAMPLES) * context->layout.channel_count, 0.0);
|
||||
|
||||
context->last_had_payload = update != nullptr;
|
||||
std::uint32_t ramp = 0;
|
||||
if (update != nullptr) {
|
||||
context->state.apply(*update);
|
||||
ramp = update->ramp_duration_samples;
|
||||
context->last_block_offset = update->block_offset_samples;
|
||||
context->last_ramp_duration = update->ramp_duration_samples;
|
||||
context->last_object_count = update->object_count;
|
||||
}
|
||||
|
||||
std::uint16_t positions[oamd::kObjects][3] = {};
|
||||
context->state.object_positions_q15(positions);
|
||||
// A frame without OAMD must not touch the gains at all (no event), otherwise a
|
||||
// pending ramp would snap - matching the reference exactly.
|
||||
const std::uint32_t event_count = context->last_had_payload ? 1u : 0u;
|
||||
const std::uint32_t offset = context->metadata_offset;
|
||||
const int result = ejoc_speaker_renderer_process(
|
||||
context->handle, context->interleaved.data(), JOC_FRAME_SAMPLES, event_count,
|
||||
event_count != 0u ? &offset : nullptr, event_count != 0u ? &ramp : nullptr,
|
||||
event_count != 0u ? &positions[0][0] : nullptr, nullptr, nullptr, nullptr,
|
||||
context->output.data());
|
||||
if (result != 0) {
|
||||
const char* message = ejoc_speaker_renderer_last_error(context->handle);
|
||||
const std::string text =
|
||||
"ejoc_speaker_renderer_process failed (" + std::to_string(result) + "): " +
|
||||
(message != nullptr ? message : "unknown");
|
||||
if (error != nullptr) {
|
||||
*error = text;
|
||||
}
|
||||
return Status::fail(JOC_ERR_RENDER_FAILED, stage::kRender, text);
|
||||
}
|
||||
return Status::success();
|
||||
}
|
||||
|
||||
} // namespace joc::speaker
|
||||
Reference in New Issue
Block a user