diff options
| author | Carl Hetherington <cth@carlh.net> | 2014-07-15 13:15:02 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2014-07-15 13:15:02 +0100 |
| commit | 7f38d676e69639a7825e506618613051651968cf (patch) | |
| tree | fcbdaf6d1536c58bfffe739d26c7c9bf676f8695 /src/lib | |
| parent | e5f79c57e1123754b1325f964123fcb56a2572b3 (diff) | |
Add simple stereo-5.1 upmixer.
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/audio_buffers.cc | 26 | ||||
| -rw-r--r-- | src/lib/audio_buffers.h | 4 | ||||
| -rw-r--r-- | src/lib/audio_decoder.cc | 5 | ||||
| -rw-r--r-- | src/lib/audio_filter.cc | 6 | ||||
| -rw-r--r-- | src/lib/audio_filter.h | 2 | ||||
| -rw-r--r-- | src/lib/audio_processor.cc | 2 | ||||
| -rw-r--r-- | src/lib/audio_processor.h | 3 | ||||
| -rw-r--r-- | src/lib/mid_side_decoder.cc | 2 | ||||
| -rw-r--r-- | src/lib/mid_side_decoder.h | 2 | ||||
| -rw-r--r-- | src/lib/single_stream_audio_content.cc | 5 | ||||
| -rw-r--r-- | src/lib/upmixer_a.cc | 109 | ||||
| -rw-r--r-- | src/lib/upmixer_a.h | 43 | ||||
| -rw-r--r-- | src/lib/wscript | 1 |
13 files changed, 205 insertions, 5 deletions
diff --git a/src/lib/audio_buffers.cc b/src/lib/audio_buffers.cc index 4ada94db8..56ca7a94b 100644 --- a/src/lib/audio_buffers.cc +++ b/src/lib/audio_buffers.cc @@ -285,3 +285,29 @@ AudioBuffers::apply_gain (float dB) } } } + +/** @param c Channel index. + * @return AudioBuffers object containing only channel `c' from this AudioBuffers. + */ +shared_ptr<AudioBuffers> +AudioBuffers::channel (int c) const +{ + shared_ptr<AudioBuffers> o (new AudioBuffers (1, frames ())); + o->copy_channel_from (this, c, 0); + return o; +} + +void +AudioBuffers::copy_channel_from (AudioBuffers const * from, int from_channel, int to_channel) +{ + assert (from->frames() == frames()); + memcpy (data(to_channel), from->data(from_channel), frames() * sizeof (float)); +} + +shared_ptr<AudioBuffers> +AudioBuffers::clone () const +{ + shared_ptr<AudioBuffers> b (new AudioBuffers (channels (), frames ())); + b->copy_from (this, frames (), 0, 0); + return b; +} diff --git a/src/lib/audio_buffers.h b/src/lib/audio_buffers.h index 51488c39a..8cd67aaa7 100644 --- a/src/lib/audio_buffers.h +++ b/src/lib/audio_buffers.h @@ -39,6 +39,9 @@ public: AudioBuffers & operator= (AudioBuffers const &); + boost::shared_ptr<AudioBuffers> clone () const; + boost::shared_ptr<AudioBuffers> channel (int) const; + void ensure_size (int); float** data () const { @@ -64,6 +67,7 @@ public: void apply_gain (float); void copy_from (AudioBuffers const * from, int frames_to_copy, int read_offset, int write_offset); + void copy_channel_from (AudioBuffers const * from, int from_channel, int to_channel); void move (int from, int to, int frames); void accumulate_channel (AudioBuffers const * from, int from_channel, int to_channel, float gain = 1); void accumulate_frames (AudioBuffers const *, int read_offset, int write_offset, int frames); diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index 19f31d30a..e4f98c678 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -45,7 +45,7 @@ AudioDecoder::AudioDecoder (shared_ptr<const AudioContent> content) } if (content->audio_processor ()) { - _processor = content->audio_processor()->clone (); + _processor = content->audio_processor()->clone (content->resampled_audio_frame_rate ()); } reset_decoded_audio (); @@ -215,4 +215,7 @@ AudioDecoder::seek (ContentTime t, bool accurate) if (accurate) { _seek_reference = t; } + if (_processor) { + _processor->flush (); + } } diff --git a/src/lib/audio_filter.cc b/src/lib/audio_filter.cc index 0cd2b18fb..59b5684ea 100644 --- a/src/lib/audio_filter.cc +++ b/src/lib/audio_filter.cc @@ -100,6 +100,12 @@ AudioFilter::run (shared_ptr<AudioBuffers> in) return out; } +void +AudioFilter::flush () +{ + _tail.reset (); +} + LowPassAudioFilter::LowPassAudioFilter (float transition_bandwidth, float cutoff) : AudioFilter (transition_bandwidth) { diff --git a/src/lib/audio_filter.h b/src/lib/audio_filter.h index 9dfcec58b..f361c27d2 100644 --- a/src/lib/audio_filter.h +++ b/src/lib/audio_filter.h @@ -37,6 +37,8 @@ public: boost::shared_ptr<AudioBuffers> run (boost::shared_ptr<AudioBuffers> in); + void flush (); + protected: friend class audio_filter_impulse_kernel_test; friend class audio_filter_impulse_input_test; diff --git a/src/lib/audio_processor.cc b/src/lib/audio_processor.cc index 27146806b..f350cc2aa 100644 --- a/src/lib/audio_processor.cc +++ b/src/lib/audio_processor.cc @@ -19,6 +19,7 @@ #include "audio_processor.h" #include "mid_side_decoder.h" +#include "upmixer_a.h" using std::string; using std::list; @@ -29,6 +30,7 @@ void AudioProcessor::setup_audio_processors () { _all.push_back (new MidSideDecoder ()); + _all.push_back (new UpmixerA (48000)); } AudioProcessor const * diff --git a/src/lib/audio_processor.h b/src/lib/audio_processor.h index 7ff9f0ec6..9b332e7fe 100644 --- a/src/lib/audio_processor.h +++ b/src/lib/audio_processor.h @@ -36,8 +36,9 @@ public: virtual std::string id () const = 0; virtual ChannelCount in_channels () const = 0; virtual int out_channels (int) const = 0; - virtual boost::shared_ptr<AudioProcessor> clone () const = 0; + virtual boost::shared_ptr<AudioProcessor> clone (int sampling_rate) const = 0; virtual boost::shared_ptr<AudioBuffers> run (boost::shared_ptr<const AudioBuffers>) = 0; + virtual void flush () {} static std::list<AudioProcessor const *> all (); static void setup_audio_processors (); diff --git a/src/lib/mid_side_decoder.cc b/src/lib/mid_side_decoder.cc index a518a4389..be82f6754 100644 --- a/src/lib/mid_side_decoder.cc +++ b/src/lib/mid_side_decoder.cc @@ -50,7 +50,7 @@ MidSideDecoder::out_channels (int) const } shared_ptr<AudioProcessor> -MidSideDecoder::clone () const +MidSideDecoder::clone (int) const { return shared_ptr<AudioProcessor> (new MidSideDecoder ()); } diff --git a/src/lib/mid_side_decoder.h b/src/lib/mid_side_decoder.h index a6d2721b6..dac6cb7d9 100644 --- a/src/lib/mid_side_decoder.h +++ b/src/lib/mid_side_decoder.h @@ -26,7 +26,7 @@ public: std::string id () const; ChannelCount in_channels () const; int out_channels (int) const; - boost::shared_ptr<AudioProcessor> clone () const; + boost::shared_ptr<AudioProcessor> clone (int) const; boost::shared_ptr<AudioBuffers> run (boost::shared_ptr<const AudioBuffers>); }; diff --git a/src/lib/single_stream_audio_content.cc b/src/lib/single_stream_audio_content.cc index ac4da25ee..521597606 100644 --- a/src/lib/single_stream_audio_content.cc +++ b/src/lib/single_stream_audio_content.cc @@ -23,6 +23,7 @@ #include "film.h" using std::string; +using std::cout; using boost::shared_ptr; using dcp::raw_convert; @@ -92,10 +93,12 @@ SingleStreamAudioContent::take_from_audio_examiner (shared_ptr<AudioExaminer> ex signal_changed (AudioContentProperty::AUDIO_LENGTH); signal_changed (AudioContentProperty::AUDIO_FRAME_RATE); + int const p = processed_audio_channels (); + { boost::mutex::scoped_lock lm (_mutex); /* XXX: do this in signal_changed...? */ - _audio_mapping = AudioMapping (_audio_channels); + _audio_mapping = AudioMapping (p); _audio_mapping.make_default (); } diff --git a/src/lib/upmixer_a.cc b/src/lib/upmixer_a.cc new file mode 100644 index 000000000..dce08fe37 --- /dev/null +++ b/src/lib/upmixer_a.cc @@ -0,0 +1,109 @@ +/* + Copyright (C) 2014 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "upmixer_a.h" +#include "audio_buffers.h" + +#include "i18n.h" + +using std::string; +using boost::shared_ptr; + +UpmixerA::UpmixerA (int sampling_rate) + : _left (0.02, 1900.0 / sampling_rate, 4800.0 / sampling_rate) + , _right (0.02, 1900.0 / sampling_rate, 4800.0 / sampling_rate) + , _centre (0.02, 150.0 / sampling_rate, 1900.0 / sampling_rate) + , _lfe (0.02, 20.0 / sampling_rate, 150.0 / sampling_rate) + , _ls (0.02, 4800.0 / sampling_rate, 20000.0 / sampling_rate) + , _rs (0.02, 4800.0 / sampling_rate, 20000.0 / sampling_rate) +{ + +} + +string +UpmixerA::name () const +{ + return _("Stereo to 5.1 up-mixer A"); +} + + +string +UpmixerA::id () const +{ + return N_("stereo-5.1-upmix-a"); +} + +ChannelCount +UpmixerA::in_channels () const +{ + return ChannelCount (2); +} + +int +UpmixerA::out_channels (int) const +{ + return 6; +} + +shared_ptr<AudioProcessor> +UpmixerA::clone (int sampling_rate) const +{ + return shared_ptr<AudioProcessor> (new UpmixerA (sampling_rate)); +} + +shared_ptr<AudioBuffers> +UpmixerA::run (shared_ptr<const AudioBuffers> in) +{ + /* Input L and R */ + shared_ptr<AudioBuffers> in_L = in->channel (0); + shared_ptr<AudioBuffers> in_R = in->channel (1); + + /* Mix of L and R */ + shared_ptr<AudioBuffers> in_LR = in_L->clone (); + in_LR->accumulate_frames (in_R.get(), 0, 0, in_R->frames ()); + in_LR->apply_gain (0.5); + + /* Run filters */ + shared_ptr<AudioBuffers> L = _left.run (in_L); + shared_ptr<AudioBuffers> R = _right.run (in_R); + shared_ptr<AudioBuffers> C = _centre.run (in_LR); + shared_ptr<AudioBuffers> Lfe = _lfe.run (in_LR); + shared_ptr<AudioBuffers> Ls = _ls.run (in_L); + shared_ptr<AudioBuffers> Rs = _rs.run (in_R); + + shared_ptr<AudioBuffers> out (new AudioBuffers (6, in->frames ())); + out->copy_channel_from (L.get(), 0, 0); + out->copy_channel_from (R.get(), 0, 1); + out->copy_channel_from (C.get(), 0, 2); + out->copy_channel_from (Lfe.get(), 0, 3); + out->copy_channel_from (Ls.get(), 0, 4); + out->copy_channel_from (Rs.get(), 0, 5); + return out; +} + +void +UpmixerA::flush () +{ + _left.flush (); + _right.flush (); + _centre.flush (); + _lfe.flush (); + _ls.flush (); + _rs.flush (); +} diff --git a/src/lib/upmixer_a.h b/src/lib/upmixer_a.h new file mode 100644 index 000000000..32e3f5fb6 --- /dev/null +++ b/src/lib/upmixer_a.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2014 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "audio_processor.h" +#include "audio_filter.h" + +class UpmixerA : public AudioProcessor +{ +public: + UpmixerA (int sampling_rate); + + std::string name () const; + std::string id () const; + ChannelCount in_channels () const; + int out_channels (int) const; + boost::shared_ptr<AudioProcessor> clone (int) const; + boost::shared_ptr<AudioBuffers> run (boost::shared_ptr<const AudioBuffers>); + void flush (); + +private: + BandPassAudioFilter _left; + BandPassAudioFilter _right; + BandPassAudioFilter _centre; + BandPassAudioFilter _lfe; + BandPassAudioFilter _ls; + BandPassAudioFilter _rs; +}; diff --git a/src/lib/wscript b/src/lib/wscript index ee8a59c0b..66a25be0a 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -85,6 +85,7 @@ sources = """ types.cc ui_signaller.cc update.cc + upmixer_a.cc util.cc video_content.cc video_decoder.cc |
