]> git.sesse.net Git - casparcg/blob - core/mixer/audio/audio_mixer.cpp
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
[casparcg] / core / mixer / audio / audio_mixer.cpp
1 #include "../../stdafx.h"\r
2 \r
3 #include "audio_mixer.h"\r
4 \r
5 namespace caspar { namespace core {\r
6         \r
7 audio_transform::audio_transform()\r
8         : gain_(1.0){}\r
9 \r
10 void audio_transform::set_gain(double value)\r
11 {\r
12         tbb::spin_mutex::scoped_lock lock(mutex_);\r
13         gain_ = value;\r
14 }\r
15 \r
16 double audio_transform::get_gain() const\r
17 {\r
18         tbb::spin_mutex::scoped_lock lock(mutex_);\r
19         return gain_;\r
20 }\r
21 \r
22 audio_transform& audio_transform::operator*=(const audio_transform &other) \r
23 {\r
24         tbb::spin_mutex::scoped_lock lock(mutex_);\r
25         gain_ *= other.gain_;\r
26         return *this;\r
27 }\r
28 \r
29 const audio_transform audio_transform::operator*(const audio_transform &other) const \r
30 {\r
31         return audio_transform(*this) *= other;\r
32 }\r
33 \r
34 struct audio_mixer::implementation\r
35 {\r
36         std::vector<short> audio_data_;\r
37         std::stack<audio_transform> transform_stack_;\r
38 \r
39 public:\r
40         implementation()\r
41         {\r
42                 transform_stack_.push(audio_transform());\r
43         }\r
44 \r
45         void begin(const audio_transform& transform)\r
46         {\r
47                 transform_stack_.push(transform_stack_.top()*transform);\r
48         }\r
49 \r
50         void process(const std::vector<short>& audio_data)\r
51         {               \r
52                 if(audio_data_.empty())\r
53                         audio_data_.resize(audio_data.size(), 0);\r
54 \r
55                 double gain = transform_stack_.top().get_gain();\r
56                 tbb::parallel_for\r
57                 (\r
58                         tbb::blocked_range<size_t>(0, audio_data.size()),\r
59                         [&](const tbb::blocked_range<size_t>& r)\r
60                         {\r
61                                 for(size_t n = r.begin(); n < r.end(); ++n)\r
62                                 {\r
63                                         int sample = static_cast<int>(audio_data[n]);\r
64                                         sample = (static_cast<int>(gain*8192.0)*sample)/8192;\r
65                                         audio_data_[n] = static_cast<short>((static_cast<int>(audio_data_[n]) + sample) & 0xFFFF);\r
66                                 }\r
67                         }\r
68                 );\r
69         }\r
70 \r
71         void end()\r
72         {\r
73                 transform_stack_.pop();\r
74         }\r
75 \r
76         std::vector<short> begin_pass()\r
77         {\r
78                 return std::move(audio_data_);\r
79         }\r
80 };\r
81 \r
82 audio_mixer::audio_mixer() : impl_(new implementation()){}\r
83 void audio_mixer::begin(const audio_transform& transform){impl_->begin(transform);}\r
84 void audio_mixer::process(const std::vector<short>& audio_data){impl_->process(audio_data);}\r
85 void audio_mixer::end(){impl_->end();}\r
86 std::vector<short> audio_mixer::begin_pass(){return impl_->begin_pass();}       \r
87 void audio_mixer::end_pass(){}\r
88 \r
89 }}