Files
JustOneCacophony/src/speaker/speaker_step.cpp
T
TheM14 42d6da6302
ci / ubuntu-latest (push) Failing after 13s
ci / macos-latest (push) Has been cancelled
ci / windows-latest (push) Has been cancelled
Initial pure C++ implementation
2026-09-25 04:17:30 +08:00

63 lines
2.7 KiB
C++

#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