std::vector<audio_item> items_;
std::vector<int> audio_cadence_;
video_format_desc format_desc_;
-
+ float master_volume_;
+ float previous_master_volume_;
public:
impl()
+ : master_volume_(1.0f)
+ , previous_master_volume_(master_volume_)
{
transform_stack_.push(core::audio_transform());
}
{
transform_stack_.pop();
}
-
+
+ void set_master_volume(float volume)
+ {
+ master_volume_ = volume;
+ }
+
audio_buffer mix(const video_format_desc& format_desc)
{
if(format_desc_ != format_desc)
if(it == audio_streams_.end() && item.audio_data.empty())
continue;
- const float prev_volume = static_cast<float>(prev_transform.volume);
- const float next_volume = static_cast<float>(next_transform.volume);
-
+ const float prev_volume = static_cast<float>(prev_transform.volume) * previous_master_volume_;
+ const float next_volume = static_cast<float>(next_transform.volume) * master_volume_;
+
// TODO: Move volume mixing into code below, in order to support audio sample counts not corresponding to frame audio samples.
auto alpha = (next_volume-prev_volume)/static_cast<float>(item.audio_data.size()/format_desc.audio_channels);
for(size_t n = 0; n < item.audio_data.size(); ++n)
- next_audio.push_back(item.audio_data[n] * (prev_volume + (n/format_desc_.audio_channels) * alpha));
+ {
+ auto sample_multiplier = (prev_volume + (n/format_desc_.audio_channels) * alpha);
+ next_audio.push_back(item.audio_data[n] * sample_multiplier);
+ }
next_audio_streams[tag].prev_transform = std::move(next_transform); // Store all active tags, inactive tags will be removed at the end.
next_audio_streams[tag].audio_data = std::move(next_audio);
next_audio_streams[tag].is_still = item.transform.is_still;
}
+ previous_master_volume_ = master_volume_;
items_.clear();
audio_streams_ = std::move(next_audio_streams);
void audio_mixer::push(const frame_transform& transform){impl_->push(transform);}
void audio_mixer::visit(const const_frame& frame){impl_->visit(frame);}
void audio_mixer::pop(){impl_->pop();}
+void audio_mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); }
audio_buffer audio_mixer::operator()(const video_format_desc& format_desc){return impl_->mix(format_desc);}
}}
\ No newline at end of file
{
blend_modes_.clear();
}, task_priority::high_priority);
- }
+ }
+
+ void set_master_volume(float volume)
+ {
+ executor_.begin_invoke([=]
+ {
+ audio_mixer_.set_master_volume(volume);
+ }, task_priority::high_priority);
+ }
+
boost::unique_future<boost::property_tree::wptree> info() const
{
boost::promise<boost::property_tree::wptree> info;
void mixer::set_blend_mode(int index, blend_mode value){impl_->set_blend_mode(index, value);}
void mixer::clear_blend_mode(int index) { impl_->clear_blend_mode(index); }
void mixer::clear_blend_modes() { impl_->clear_blend_modes(); }
+void mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); }
boost::unique_future<boost::property_tree::wptree> mixer::info() const{return impl_->info();}
const_frame mixer::operator()(std::map<int, draw_frame> frames, const struct video_format_desc& format_desc){return (*impl_)(std::move(frames), format_desc);}
mutable_frame mixer::create_frame(const void* tag, const core::pixel_format_desc& desc) {return impl_->image_mixer_->create_frame(tag, desc);}
int layer = GetLayerIndex();
GetChannel()->mixer().set_blend_mode(GetLayerIndex(), get_blend_mode(blend_str));
}
+ else if(_parameters[0] == L"MASTERVOLUME")
+ {
+ float master_volume = boost::lexical_cast<float>(_parameters.at(1));
+ GetChannel()->mixer().set_master_volume(master_volume);
+ }
else if(_parameters[0] == L"BRIGHTNESS")
{
auto value = boost::lexical_cast<double>(_parameters.at(1));