Extract audio samples from any ReaderBase class
| 49 | |
| 50 | // Extract audio samples from any ReaderBase class |
| 51 | AudioWaveformData AudioWaveformer::ExtractSamples(int channel, int num_per_second, bool normalize) { |
| 52 | // Legacy entry point: resolve a source reader (unwrap Clip/FrameMapper), then extract audio-only. |
| 53 | AudioWaveformData data; |
| 54 | if (!reader) { |
| 55 | return data; |
| 56 | } |
| 57 | |
| 58 | ReaderBase* source = ResolveWaveformReader(); |
| 59 | |
| 60 | Fraction source_fps = ResolveSourceFPS(source); |
| 61 | |
| 62 | AudioWaveformData base = ExtractSamplesFromReader(source, channel, num_per_second, false); |
| 63 | |
| 64 | // If this is a Clip, apply its keyframes using project fps (timeline if available, else reader fps) |
| 65 | if (auto clip = dynamic_cast<Clip*>(reader)) { |
| 66 | Timeline* timeline = dynamic_cast<Timeline*>(clip->ParentTimeline()); |
| 67 | Fraction project_fps = timeline ? timeline->info.fps : clip->Reader()->info.fps; |
| 68 | return ApplyKeyframes(base, &clip->time, &clip->volume, project_fps, source_fps, source->info.channels, num_per_second, channel, normalize); |
| 69 | } |
| 70 | |
| 71 | // No keyframes to apply |
| 72 | if (normalize) { |
| 73 | float max_sample = 0.0f; |
| 74 | for (auto v : base.max_samples) { |
| 75 | max_sample = std::max(max_sample, std::abs(v)); |
| 76 | } |
| 77 | if (max_sample > 0.0f) { |
| 78 | base.scale(static_cast<int>(base.max_samples.size()), 1.0f / max_sample); |
| 79 | } |
| 80 | } |
| 81 | return base; |
| 82 | } |
| 83 | |
| 84 | AudioWaveformData AudioWaveformer::ExtractSamples(const std::string& path, int channel, int num_per_second, bool normalize) { |
| 85 | FFmpegReader temp_reader(path); |
no test coverage detected