/
reds
/
OpenDAW
Обзор
Документация
Войти
/
reds
/
OpenDAW
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop
src/core/AudioGraph.cpp
227 строк
6 KB
OpenDAW Developer
feat(v1.0.0-phase1): Add AudioGraph foundation
21 фев 2026, 08:49
21 фев 2026, 08:49
2a0b0b6
Код
Авторство
О чём код?
#include <opendaw/core/AudioGraph.h> #include <algorithm> #include <iostream> namespace opendaw { // ============================================================================ // Track Implementation // ============================================================================ Track::Track(const std::string& name, TrackType type) : name_(name) , type_(type) { } void Track::prepare(double sampleRate, int blockSize) { sampleRate_ = sampleRate; blockSize_ = blockSize; // Подготовить все плагины for (auto& plugin : plugins_) { if (plugin) { plugin->initialize(sampleRate, blockSize); } } // Создать временный буфер tempBuffer_.resize(2, blockSize); } void Track::process(AudioBuffer<float>& audio, MidiBuffer& midi) { if (!active_ || muted_) { audio.clear(); return; } // Обработать плагины последовательно for (auto& plugin : plugins_) { if (plugin) { plugin->process(audio, midi); } } // Применить громкость audio.applyGain(volume_); // Применить панораму (простая реализация) if (pan_ != 0.0f && audio.getNumChannels() >= 2) { auto* left = audio.getChannel(0); auto* right = audio.getChannel(1); float leftGain = 1.0f - std::max(0.0f, pan_); float rightGain = 1.0f + std::min(0.0f, pan_); for (int i = 0; i < audio.getNumSamples(); ++i) { left[i] *= leftGain; right[i] *= rightGain; } } } void Track::reset() { for (auto& plugin : plugins_) { if (plugin) { plugin->reset(); } } } void Track::addPlugin(std::unique_ptr<Plugin> plugin) { if (plugin) { plugin->initialize(sampleRate_, blockSize_); plugins_.push_back(std::move(plugin)); } } void Track::removePlugin(int index) { if (index >= 0 && index < static_cast<int>(plugins_.size())) { plugins_.erase(plugins_.begin() + index); } } Plugin* Track::getPlugin(int index) { if (index >= 0 && index < static_cast<int>(plugins_.size())) { return plugins_[index].get(); } return nullptr; } // ============================================================================ // AudioGraph Implementation // ============================================================================ AudioGraph::AudioGraph() { // Создать мастер дорожку master_ = std::make_unique<Track>("Master", TrackType::Master); } void AudioGraph::prepare(double sampleRate, int blockSize) { sampleRate_ = sampleRate; blockSize_ = blockSize; // Подготовить все дорожки for (auto& track : tracks_) { track->prepare(sampleRate, blockSize); } if (master_) { master_->prepare(sampleRate, blockSize); } // Создать выходной буфер outputBuffer_.resize(2, blockSize); } void AudioGraph::process(AudioBuffer<float>& audio, MidiBuffer& midi) { // Очистить выходной буфер outputBuffer_.clear(); // 1. Обработать MIDI дорожки (генерируют аудио из MIDI) for (auto& track : tracks_) { if (track->getType() == TrackType::Midi && track->isActive()) { // MIDI дорожки могут генерировать аудио // Пока просто обрабатываем MIDI track->process(audio, midi); } } // 2. Обработать Audio дорожки for (auto& track : tracks_) { if (track->getType() == TrackType::Audio && track->isActive()) { // Копировать входной буфер AudioBuffer<float> trackBuffer(2, blockSize_); if (audio.getNumChannels() >= 2) { trackBuffer.copyFrom(audio); } // Обработать дорожку track->process(trackBuffer, midi); // Смиксовать с выходом outputBuffer_.addFrom(trackBuffer); } } // 3. Обработать Bus дорожки for (auto& track : tracks_) { if (track->getType() == TrackType::Bus && track->isActive()) { track->process(outputBuffer_, midi); } } // 4. Обработать Master if (master_ && master_->isActive()) { master_->process(outputBuffer_, midi); } // Копировать результат в выходной буфер audio.copyFrom(outputBuffer_); } void AudioGraph::reset() { for (auto& track : tracks_) { track->reset(); } if (master_) { master_->reset(); } } Track* AudioGraph::addTrack(const std::string& name, TrackType type) { auto track = std::make_unique<Track>(name, type); track->prepare(sampleRate_, blockSize_); Track* trackPtr = track.get(); tracks_.push_back(std::move(track)); std::cout << "[AudioGraph] Added track: " << name << " (type: " << (type == TrackType::Audio ? "Audio" : "MIDI") << ")" << std::endl; return trackPtr; } void AudioGraph::removeTrack(int index) { if (index >= 0 && index < static_cast<int>(tracks_.size())) { std::cout << "[AudioGraph] Removed track: " << tracks_[index]->getName() << std::endl; tracks_.erase(tracks_.begin() + index); } } Track* AudioGraph::getTrack(int index) { if (index >= 0 && index < static_cast<int>(tracks_.size())) { return tracks_[index].get(); } return nullptr; } const Track* AudioGraph::getTrack(int index) const { if (index >= 0 && index < static_cast<int>(tracks_.size())) { return tracks_[index].get(); } return nullptr; } int AudioGraph::getTotalLatencySamples() const { int totalLatency = 0; // Сложить задержки всех дорожек for (const auto& track : tracks_) { totalLatency += track->getLatencySamples(); } // Добавить задержку мастера if (master_) { totalLatency += master_->getLatencySamples(); } return totalLatency; } } // namespace opendaw