}
}
}
+
+/** @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;
+}
AudioBuffers & operator= (AudioBuffers const &);
+ boost::shared_ptr<AudioBuffers> clone () const;
+ boost::shared_ptr<AudioBuffers> channel (int) const;
+
void ensure_size (int);
float** data () const {
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);
}
if (content->audio_processor ()) {
- _processor = content->audio_processor()->clone ();
+ _processor = content->audio_processor()->clone (content->resampled_audio_frame_rate ());
}
reset_decoded_audio ();
if (accurate) {
_seek_reference = t;
}
+ if (_processor) {
+ _processor->flush ();
+ }
}
return out;
}
+void
+AudioFilter::flush ()
+{
+ _tail.reset ();
+}
+
LowPassAudioFilter::LowPassAudioFilter (float transition_bandwidth, float cutoff)
: AudioFilter (transition_bandwidth)
{
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;
#include "audio_processor.h"
#include "mid_side_decoder.h"
+#include "upmixer_a.h"
using std::string;
using std::list;
AudioProcessor::setup_audio_processors ()
{
_all.push_back (new MidSideDecoder ());
+ _all.push_back (new UpmixerA (48000));
}
AudioProcessor const *
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 ();
}
shared_ptr<AudioProcessor>
-MidSideDecoder::clone () const
+MidSideDecoder::clone (int) const
{
return shared_ptr<AudioProcessor> (new MidSideDecoder ());
}
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>);
};
#include "film.h"
using std::string;
+using std::cout;
using boost::shared_ptr;
using dcp::raw_convert;
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 ();
}
--- /dev/null
+/*
+ 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 ();
+}
--- /dev/null
+/*
+ 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;
+};
types.cc
ui_signaller.cc
update.cc
+ upmixer_a.cc
util.cc
video_content.cc
video_decoder.cc
add_label_to_grid_bag_sizer (grid, this, _("Stream"), true, wxGBPosition (r, 0));
_stream = new wxChoice (this, wxID_ANY);
grid->Add (_stream, wxGBPosition (r, 1));
- _description = add_label_to_grid_bag_sizer (grid, this, "", false, wxGBPosition (r, 3));
+ _description = add_label_to_grid_bag_sizer (grid, this, "", false, wxGBPosition (r, 2), wxGBSpan (1, 2));
++r;
add_label_to_grid_bag_sizer (grid, this, _("Process with"), true, wxGBPosition (r, 0));
subrip_test.cc
test.cc
threed_test.cc
+ upmixer_a_test.cc
util_test.cc
xml_subtitle_test.cc
"""