| 88 | |
| 89 | } // namespace |
| 90 | |
| 91 | std::vector<AudioChunkSpan> plan_audio_chunks(int64_t input_samples, const AudioChunkSpec & spec) { |
| 92 | require_positive(input_samples, "input samples"); |
| 93 | require_positive(spec.chunk_samples, "chunk samples"); |
| 94 | require_positive(spec.hop_samples, "hop samples"); |
| 95 | if (spec.hop_samples > spec.chunk_samples) { |
| 96 | throw std::runtime_error("Audio chunker hop_samples must be <= chunk_samples"); |
| 97 | } |
| 98 | |
| 99 | std::vector<AudioChunkSpan> spans; |
| 100 | int64_t start = 0; |
| 101 | int64_t index = 0; |
| 102 | while (start < input_samples) { |
| 103 | const int64_t valid = std::min(spec.chunk_samples, input_samples - start); |
| 104 | AudioChunkSpan span; |
| 105 | span.index = index++; |
| 106 | span.output_start_sample = start; |
| 107 | span.valid_samples = valid; |
| 108 | span.copy_start_sample = start; |
| 109 | if (valid < spec.chunk_samples && |
| 110 | spec.tail_alignment == AudioChunkTailAlignment::Center) { |
| 111 | span.copy_start_sample -= (spec.chunk_samples - valid) / 2; |
| 112 | } |
| 113 | span.valid_start_in_chunk = start - span.copy_start_sample; |
| 114 | if (span.valid_start_in_chunk < 0 || |
| 115 | span.valid_start_in_chunk + span.valid_samples > spec.chunk_samples) { |
| 116 | throw std::runtime_error("Audio chunker planned invalid chunk span"); |
| 117 | } |
| 118 | spans.push_back(span); |
| 119 | start += spec.hop_samples; |
| 120 | } |
| 121 | return spans; |
| 122 | } |
| 123 | |
| 124 | AudioChunkMode parse_audio_chunk_mode( |