45 const float*
const* preload_channels,
46 std::uint32_t channels,
47 std::uint64_t total_frames,
49 std::uint64_t preload_frames,
50 bool has_preload_contract,
52 bool has_stream_source,
54 const bool stream_matches =
56 (stream_source.valid() &&
57 stream_registration_.matches(stream_source.token,
59 stream_source.total_frames,
60 stream_source.page_frames,
61 stream_source.registration_epoch) &&
62 stream_memory_governor_epoch_ == stream_source.memory_governor_epoch);
63 return stream_matches && asset_.asset_id == asset.asset_id &&
64 asset_.asset_generation == asset.asset_generation &&
65 source_.source_id == source.source_id &&
66 source_.source_generation == source.source_generation &&
67 preload_channels_ == preload_channels && channels_ == channels &&
68 total_frames_ == total_frames && sample_rate_ == sample_rate &&
69 preload_frames_ == preload_frames &&
70 has_preload_contract_ == has_preload_contract &&
71 same_contract(preload_contract_, preload_contract) &&
72 has_stream_source_ == has_stream_source;
79 const float*
const* preload_channels) noexcept
80 : asset_(config.asset),
81 source_(config.source),
82 preload_channels_(preload_channels),
83 channels_(config.channels),
84 total_frames_(config.total_frames),
85 sample_rate_(config.sample_rate),
86 preload_frames_(config.preload_frames),
87 has_preload_contract_(config.preload_contract.has_value()),
89 has_stream_source_(config.stream_source.has_value()),
90 stream_registration_(config.stream_source
91 ? config.stream_source->registration
93 stream_memory_governor_epoch_(config.stream_source
94 ? config.stream_source->memory_governor_epoch
99 return left.source_sample_rate == right.source_sample_rate &&
100 left.host_sample_rate == right.host_sample_rate &&
101 left.maximum_playback_ratio == right.maximum_playback_ratio &&
102 left.certified_io_latency_seconds == right.certified_io_latency_seconds &&
103 left.scheduler_margin_seconds == right.scheduler_margin_seconds &&
104 left.decoder_latency_seconds == right.decoder_latency_seconds &&
105 left.maximum_host_block_frames == right.maximum_host_block_frames &&
106 left.interpolation_guard_frames == right.interpolation_guard_frames &&
107 left.loop_prefetch_guard_frames == right.loop_prefetch_guard_frames &&
108 left.configured_preload_frames == right.configured_preload_frames;
111 SampleAssetToken asset_{};
112 SampleStreamSourceToken source_{};
113 const float*
const* preload_channels_ =
nullptr;
114 std::uint32_t channels_ = 0;
115 std::uint64_t total_frames_ = 0;
116 double sample_rate_ = 0.0;
117 std::uint64_t preload_frames_ = 0;
118 bool has_preload_contract_ =
false;
119 SamplePreloadContract preload_contract_{};
120 bool has_stream_source_ =
false;
121 SampleStreamSourceRegistrationProof stream_registration_{};
122 SampleMemoryGovernorEpoch stream_memory_governor_epoch_{};
125static_assert(std::is_trivially_copyable_v<SampleAssetRegistrationProof>);
126static_assert(std::is_standard_layout_v<SampleAssetRegistrationProof>);
145 const bool base_valid =
asset.asset_id != 0 &&
asset.asset_generation != 0 &&
146 source.source_id != 0 &&
source.source_generation != 0 &&
193static_assert(std::is_trivially_copyable_v<SampleAssetView>);
194static_assert(std::is_standard_layout_v<SampleAssetView>);
208 template<
typename SampleType>
210 static_assert(std::is_same_v<std::remove_const_t<SampleType>,
float>);
212 if (!config_valid(config, preload))
return false;
215 preload_.resize(config.channels,
static_cast<std::size_t
>(config.preload_frames));
216 preload_channel_ptrs_.resize(config.channels);
217 for (std::uint32_t channel = 0; channel < config.channels; ++channel) {
219 static_cast<std::size_t
>(config.preload_frames),
220 preload_.channel(channel).data());
221 preload_channel_ptrs_[channel] = preload_.channel(channel).data();
228 publish_view(config);
240 config.channels, config.preload_frames);
241 const auto expected_samples = bytes
242 ? *bytes /
static_cast<std::uint64_t
>(
sizeof(float))
244 if (!bytes || !preload_lease ||
246 preload_lease.
bytes() != *bytes ||
250 (config.stream_source &&
251 preload_lease.
epoch() != config.stream_source->memory_governor_epoch) ||
252 !config_valid(config, preload.
view())) {
254 preload_lease.
reset();
259 preload_ = std::move(preload);
260 preload_channel_ptrs_.resize(config.channels);
261 for (std::uint32_t channel = 0; channel < config.channels; ++channel) {
262 preload_channel_ptrs_[channel] = preload_.channel(channel).data();
264 preload_lease_ = std::move(preload_lease);
268 preload_lease.
reset();
272 publish_view(config);
278 std::vector<const float*>().swap(preload_channel_ptrs_);
280 preload_lease_.reset();
283 bool prepared() const noexcept {
return view_.valid(); }
289 .asset = config.asset,
290 .source = config.source,
291 .preload_channels = preload_channel_ptrs_.data(),
292 .channels = config.channels,
293 .total_frames = config.total_frames,
294 .sample_rate = config.sample_rate,
295 .preload_frames = config.preload_frames,
296 .has_preload_contract = config.preload_contract.has_value(),
298 .has_stream_source = config.stream_source.has_value(),
299 .stream_source = config.stream_source.value_or(SampleStreamCacheSourceView{}),
300 .registration = SampleAssetRegistrationProof(
301 config, preload_channel_ptrs_.data()),
305 template<
typename SampleType>
306 static bool config_valid(
const SampleAssetConfig& config,
307 BufferView<SampleType> preload)
noexcept {
308 if (
config.asset.asset_id == 0 ||
config.asset.asset_generation == 0 ||
309 config.source.source_id == 0 ||
config.source.source_generation == 0 ||
311 !(
config.sample_rate > 0.0) || !std::isfinite(
config.sample_rate) ||
313 config.preload_frames > std::numeric_limits<std::size_t>::max() ||
315 std::numeric_limits<std::size_t>::max() /
config.channels ||
316 preload.num_channels() !=
config.channels ||
317 config.preload_frames > preload.num_samples()) {
320 for (std::uint32_t channel = 0; channel <
config.channels; ++channel) {
321 if (preload.channel_ptr(channel) ==
nullptr)
return false;
326 if (!
config.preload_contract)
return false;
327 const auto& contract = *
config.preload_contract;
328 if (contract.source_sample_rate !=
config.sample_rate ||
329 contract.configured_preload_frames !=
config.preload_frames ||
330 contract.maximum_host_block_frames == 0 ||
331 contract.interpolation_guard_frames == 0) {
335 if (!evaluated.valid() || !evaluated.sufficient)
return false;
337 const auto& stream = *
config.stream_source;
338 return stream.valid() && stream.token.source_id ==
config.source.source_id &&
339 stream.token.source_generation ==
config.source.source_generation &&
340 stream.total_frames ==
config.total_frames && stream.window->prepared() &&
341 stream.window->channels() ==
config.channels &&
342 stream.window->page_frames() == stream.page_frames;
347 SampleMemoryLease preload_lease_;
348 Buffer<float> preload_;
349 std::vector<const float*> preload_channel_ptrs_;
350 SampleAssetView view_{};
Non-owning view over multi-channel audio sample data.
Definition buffer.hpp:30
SampleType * channel_ptr(std::size_t index)
Raw pointer to one channel's sample data.
Definition buffer.hpp:68
Owning multi-channel audio buffer with contiguous storage.
Definition buffer.hpp:119
std::size_t num_channels() const
Definition buffer.hpp:204
void release() noexcept
Release all owned sample and channel-pointer storage.
Definition buffer.hpp:211
std::size_t allocated_sample_capacity() const noexcept
Number of sample elements retained by the backing allocation.
Definition buffer.hpp:208
BufferView< SampleType > view()
Create a non-owning BufferView over this buffer's data.
Definition buffer.hpp:182
std::size_t num_samples() const
Definition buffer.hpp:205
Definition sample_asset.hpp:39
SampleAssetRegistrationProof()=default
bool matches(SampleAssetToken asset, SampleStreamSourceToken source, const float *const *preload_channels, std::uint32_t channels, std::uint64_t total_frames, double sample_rate, std::uint64_t preload_frames, bool has_preload_contract, const SamplePreloadContract &preload_contract, bool has_stream_source, const SampleStreamCacheSourceView &stream_source) const noexcept
Definition sample_asset.hpp:43
friend class SampleAsset
Definition sample_asset.hpp:76
Off-audio-thread owner for immutable sampler metadata and resident preload.
Definition sample_asset.hpp:200
SampleAssetView view() const noexcept
Definition sample_asset.hpp:284
SampleAsset(SampleAsset &&)=delete
SampleAsset & operator=(const SampleAsset &)=delete
bool prepare_owned(const SampleAssetConfig &config, Buffer< float > preload, SampleMemoryLease preload_lease)
Takes ownership of an already-filled preload without allocating and copying a second planar sample st...
Definition sample_asset.hpp:235
SampleAsset(const SampleAsset &)=delete
bool prepare(const SampleAssetConfig &config, BufferView< SampleType > preload)
Definition sample_asset.hpp:209
void release() noexcept
Definition sample_asset.hpp:276
SampleAsset & operator=(SampleAsset &&)=delete
bool prepared() const noexcept
Definition sample_asset.hpp:283
Definition sample_memory_governor.hpp:16
Move-only reservation against one shared sampler-memory cap.
Definition sample_memory_governor.hpp:79
std::uint64_t bytes() const noexcept
Definition sample_memory_governor.hpp:103
SampleMemoryCategory category() const noexcept
Definition sample_memory_governor.hpp:102
SampleMemoryGovernorEpoch epoch() const noexcept
Definition sample_memory_governor.hpp:105
void reset() noexcept
Definition sample_memory_governor.hpp:111
Definition sample_stream_service.hpp:158
Definition analyzer_provider.hpp:12
@ Preload
Definition sample_memory_governor.hpp:36
std::optional< std::uint64_t > checked_sample_storage_bytes(std::uint32_t channels, std::uint64_t frames_per_buffer, std::uint32_t buffer_count=1, std::uint32_t bytes_per_sample=sizeof(float)) noexcept
Checked planar sample-storage formula shared by preload and page admission.
Definition sample_memory_governor.hpp:254
SamplePreloadContractResult evaluate_sample_preload_contract(const SamplePreloadContract &contract) noexcept
Calculate the resident head required to cover a certified streaming service interval at the fastest s...
Definition sample_preload_contract.hpp:45
Definition sample_asset.hpp:24
std::optional< SampleStreamCacheSourceView > stream_source
Definition sample_asset.hpp:34
std::uint64_t total_frames
Definition sample_asset.hpp:28
double sample_rate
Definition sample_asset.hpp:29
std::uint64_t preload_frames
Definition sample_asset.hpp:30
std::uint32_t channels
Definition sample_asset.hpp:27
SampleAssetToken asset
Definition sample_asset.hpp:25
std::optional< SamplePreloadContract > preload_contract
Definition sample_asset.hpp:33
SampleStreamSourceToken source
Definition sample_asset.hpp:26
Definition sample_asset.hpp:19
std::uint64_t asset_generation
Definition sample_asset.hpp:21
std::uint64_t asset_id
Definition sample_asset.hpp:20
Immutable audio-thread snapshot borrowed from one SampleAsset owner.
Definition sample_asset.hpp:130
std::uint64_t total_frames
Definition sample_asset.hpp:135
bool has_preload_contract
Definition sample_asset.hpp:138
double sample_rate
Definition sample_asset.hpp:136
bool preload_contains(std::uint64_t frame) const noexcept
Definition sample_asset.hpp:183
SampleAssetRegistrationProof registration
Definition sample_asset.hpp:142
const float *const * preload_channels
Definition sample_asset.hpp:133
SampleStreamCacheSourceView stream_source
Definition sample_asset.hpp:141
std::uint32_t channels
Definition sample_asset.hpp:134
std::uint64_t preload_frames
Definition sample_asset.hpp:137
SamplePreloadContract preload_contract
Definition sample_asset.hpp:139
bool valid() const noexcept
Definition sample_asset.hpp:144
bool fully_resident() const noexcept
Definition sample_asset.hpp:179
bool has_stream_source
Definition sample_asset.hpp:140
const float * preload_channel_data(std::uint32_t channel) const noexcept
Definition sample_asset.hpp:187
SampleAssetToken asset
Definition sample_asset.hpp:131
SampleStreamSourceToken source
Definition sample_asset.hpp:132
Definition sample_preload_contract.hpp:18
Definition sample_stream_service.hpp:200
Definition sample_stream_service.hpp:18