| 274 | } |
| 275 | |
| 276 | fl::vector<audio::Sample> Vorbis::decodeAll(fl::span<const fl::u8> data, fl::string* errorMessage) { |
| 277 | fl::vector<audio::Sample> samples; |
| 278 | |
| 279 | StbVorbisDecoder decoder; |
| 280 | if (!decoder.openMemory(data)) { |
| 281 | if (errorMessage) *errorMessage = "Failed to open Vorbis stream"; |
| 282 | return samples; |
| 283 | } |
| 284 | |
| 285 | VorbisInfo info = decoder.getInfo(); |
| 286 | const fl::i32 channels = info.channels > 0 ? info.channels : 1; |
| 287 | constexpr fl::i32 FRAME_SIZE = 1024; |
| 288 | fl::vector<fl::i16> buffer(FRAME_SIZE * 2); |
| 289 | |
| 290 | while (true) { |
| 291 | fl::i32 samplesDecoded = decoder.getSamplesShortInterleaved( |
| 292 | channels, buffer.data(), static_cast<fl::i32>(buffer.size()) |
| 293 | ); |
| 294 | |
| 295 | if (samplesDecoded == 0) break; |
| 296 | |
| 297 | // Convert stereo to mono |
| 298 | if (channels == 2) { |
| 299 | fl::vector<fl::i16> mono; |
| 300 | mono.reserve(samplesDecoded); |
| 301 | for (fl::i32 i = 0; i < samplesDecoded; ++i) { |
| 302 | fl::i32 left = buffer[i * 2]; |
| 303 | fl::i32 right = buffer[i * 2 + 1]; |
| 304 | mono.push_back(static_cast<fl::i16>((left + right) / 2)); |
| 305 | } |
| 306 | samples.push_back(audio::Sample(mono)); |
| 307 | } else { |
| 308 | samples.push_back(audio::Sample(fl::span<const fl::i16>(buffer.data(), samplesDecoded))); |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | return samples; |
| 313 | } |
| 314 | |
| 315 | } // namespace fl |
nothing calls this directly
no test coverage detected