in vireo/internal/decode/aac.cpp [106:180]
auto AAC::operator()(uint32_t index) const -> sound::Sound {
THROW_IF(index >= count(), OutOfRange);
THROW_IF(index >= _this->samples.count(), OutOfRange);
const Sample& sample = _this->samples(index);
sound::Sound sound;
sound.pts = sample.pts;
struct audio_info {
uint16_t frame_size;
uint8_t channels;
};
sound.pcm = [_this = _this, index]() -> sound::PCM {
auto decode_sample = [&_this](uint32_t index) -> audio_info {
const Sample& sample = _this->samples(index);
const auto sample_data = sample.nal();
THROW_IF(sample_data.count() + 4 > _AAC::kMaxBufferSize, Unsafe);
_this->scratch_buffer.copy(sample_data);
const UINT size = _this->scratch_buffer.count();
UINT valid_bytes_left = size;
CHECK(aacDecoder_Fill(_this->decoder.get(),
(UCHAR**)util::get_addr(_this->scratch_buffer.data()),
&size,
&valid_bytes_left) == AAC_DEC_OK);
CHECK(valid_bytes_left == 0);
THROW_IF(aacDecoder_DecodeFrame(_this->decoder.get(),
(INT_PCM*)_this->decoded_sample.data(),
_this->decoded_sample.capacity(), 0) != AAC_DEC_OK, Invalid);
CStreamInfo* stream_info = aacDecoder_GetStreamInfo(_this->decoder.get());
const uint8_t audio_object_type = stream_info->aot;
const uint8_t extension_object_type = stream_info->extAot;
const uint16_t frame_size = stream_info->frameSize;
const uint8_t channels = stream_info->numChannels;
const uint32_t sample_rate = stream_info->sampleRate;
// MPEG-4 AAC Low Complexity only with optional SBR supported
THROW_IF(audio_object_type != 2, Unsupported);
if (extension_object_type != 5) { // AAC-LC
CHECK(frame_size == AUDIO_FRAME_SIZE);
CHECK(channels == _this->audio_settings.channels);
CHECK(sample_rate == _this->audio_settings.sample_rate);
} else { // AAC-LC SBR
CHECK(frame_size == AUDIO_FRAME_SIZE * SBR_FACTOR);
// CHECK(channels == _this->audio_settings.channels * SBR_FACTOR);
CHECK(sample_rate == _this->audio_settings.sample_rate * SBR_FACTOR);
}
const uint16_t decoded_size = frame_size * channels;
_this->decoded_sample.set_bounds(0, decoded_size);
return {frame_size, channels};
};
if (index - _this->last_index != 1) {
_this->reset();
if (index > 0) {
decode_sample(index - 1); // There is 1 sample dependency between samples
}
}
const auto info = decode_sample(index);
common::Sample16 decoded_sample_copy(_this->decoded_sample);
_this->last_index = index;
sound::PCM pcm(info.frame_size, info.channels, move(decoded_sample_copy));
if (pcm.size() == AUDIO_FRAME_SIZE * SBR_FACTOR) {
return pcm.downsample(2);
} else {
return move(pcm);
}
};
return sound;
}