summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2012-10-20 18:39:15 +0100
committerCarl Hetherington <cth@carlh.net>2012-10-20 20:05:26 +0100
commite9ca66f0d8897739cdef22f5011e0866f5a3f741 (patch)
treefacd02deef05a75094efec59b7d04f26786d1599 /src/lib
parent068f8fe319aad390788bdea24ad21ef758d6dd03 (diff)
Clean up audio passing round a bit.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/decoder.cc17
-rw-r--r--src/lib/decoder.h7
-rw-r--r--src/lib/encoder.h3
-rw-r--r--src/lib/imagemagick_encoder.h2
-rw-r--r--src/lib/j2k_still_encoder.h2
-rw-r--r--src/lib/j2k_wav_encoder.cc50
-rw-r--r--src/lib/j2k_wav_encoder.h5
-rw-r--r--src/lib/util.cc36
-rw-r--r--src/lib/util.h24
9 files changed, 92 insertions, 54 deletions
diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc
index 16d815a07..ee725c39d 100644
--- a/src/lib/decoder.cc
+++ b/src/lib/decoder.cc
@@ -192,12 +192,9 @@ Decoder::emit_audio (uint8_t* data, int size)
{
/* Deinterleave and convert to float */
- float* samples[_fs->audio_channels()];
int const total_samples = size / bytes_per_audio_sample();
int const frames = total_samples / _fs->audio_channels();
- for (int i = 0; i < _fs->audio_channels(); ++i) {
- samples[i] = new float[frames];
- }
+ shared_ptr<AudioBuffers> audio (new AudioBuffers (_fs->audio_channels(), frames));
switch (audio_sample_format()) {
case AV_SAMPLE_FMT_S16:
@@ -211,7 +208,7 @@ Decoder::emit_audio (uint8_t* data, int size)
/* signed sample */
int const os = ou >= 0x8000 ? (- 0x10000 + ou) : ou;
/* float sample */
- samples[channel][sample] = float(os) / 0x8000;
+ audio->data(channel)[sample] = float(os) / 0x8000;
++channel;
if (channel == _fs->audio_channels()) {
@@ -228,7 +225,7 @@ Decoder::emit_audio (uint8_t* data, int size)
{
float* p = reinterpret_cast<float*> (data);
for (int i = 0; i < _fs->audio_channels(); ++i) {
- memcpy (samples[i], p, frames * sizeof(float));
+ memcpy (audio->data(i), p, frames * sizeof(float));
p += frames;
}
}
@@ -243,7 +240,7 @@ Decoder::emit_audio (uint8_t* data, int size)
float const linear_gain = pow (10, _fs->audio_gain() / 20);
for (int i = 0; i < _fs->audio_channels(); ++i) {
for (int j = 0; j < frames; ++j) {
- samples[i][j] *= linear_gain;
+ audio->data(i)[j] *= linear_gain;
}
}
}
@@ -251,11 +248,7 @@ Decoder::emit_audio (uint8_t* data, int size)
/* Update the number of audio frames we've pushed to the encoder */
_audio_frames_processed += frames;
- Audio (samples, frames);
-
- for (int i = 0; i < _fs->audio_channels(); ++i) {
- delete[] samples[i];
- }
+ Audio (audio);
}
/** Called by subclasses to tell the world that some video data is ready.
diff --git a/src/lib/decoder.h b/src/lib/decoder.h
index 14e602ace..85b256f5b 100644
--- a/src/lib/decoder.h
+++ b/src/lib/decoder.h
@@ -99,11 +99,8 @@ public:
*/
sigc::signal<void, boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle> > Video;
- /** Emitted when some audio data is ready.
- * First parameter is an array of pointers to deinterleaved, floating point sample data for each channel.
- * Second parameter is the size of the data in frames (ie samples on each channel).
- */
- sigc::signal<void, float**, int> Audio;
+ /** Emitted when some audio data is ready */
+ sigc::signal<void, boost::shared_ptr<AudioBuffers> > Audio;
protected:
/** perform a single pass at our content */
diff --git a/src/lib/encoder.h b/src/lib/encoder.h
index 5dc0804c6..3317d30d1 100644
--- a/src/lib/encoder.h
+++ b/src/lib/encoder.h
@@ -37,6 +37,7 @@ class Options;
class Image;
class Log;
class Subtitle;
+class AudioBuffers;
/** @class Encoder
* @brief Parent class for classes which can encode video and audio frames.
@@ -67,7 +68,7 @@ public:
* @param d Array of pointers to floating point sample data for each channel.
* @param s Number of frames (ie number of samples in each channel)
*/
- virtual void process_audio (float** d, int s) = 0;
+ virtual void process_audio (boost::shared_ptr<const AudioBuffers>) = 0;
/** Called when a processing run has finished */
virtual void process_end () = 0;
diff --git a/src/lib/imagemagick_encoder.h b/src/lib/imagemagick_encoder.h
index 8e9c416ae..06f1723b1 100644
--- a/src/lib/imagemagick_encoder.h
+++ b/src/lib/imagemagick_encoder.h
@@ -38,6 +38,6 @@ public:
void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format) {}
void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>);
- void process_audio (float**, int) {}
+ void process_audio (boost::shared_ptr<const AudioBuffers>) {}
void process_end () {}
};
diff --git a/src/lib/j2k_still_encoder.h b/src/lib/j2k_still_encoder.h
index 3c8f236ee..7e7719321 100644
--- a/src/lib/j2k_still_encoder.h
+++ b/src/lib/j2k_still_encoder.h
@@ -38,6 +38,6 @@ public:
void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format) {}
void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>);
- void process_audio (float**, int) {}
+ void process_audio (boost::shared_ptr<const AudioBuffers>) {}
void process_end () {}
};
diff --git a/src/lib/j2k_wav_encoder.cc b/src/lib/j2k_wav_encoder.cc
index 7697a5e78..a83c283d7 100644
--- a/src/lib/j2k_wav_encoder.cc
+++ b/src/lib/j2k_wav_encoder.cc
@@ -303,13 +303,10 @@ J2KWAVEncoder::process_end ()
#if HAVE_SWRESAMPLE
if (_swr_context) {
- float* out[_fs->audio_channels()];
- for (int i = 0; i < _fs->audio_channels(); ++i) {
- out[i] = new float[256];
- }
+ shared_ptr<AudioBuffers> out (new AudioBuffers (_fs->audio_channels(), 256));
while (1) {
- int const frames = swr_convert (_swr_context, (uint8_t **) out, 256, 0, 0);
+ int const frames = swr_convert (_swr_context, (uint8_t **) out->data(), 256, 0, 0);
if (frames < 0) {
throw EncodeError ("could not run sample-rate converter");
@@ -319,11 +316,7 @@ J2KWAVEncoder::process_end ()
break;
}
- write_audio (out, frames);
- }
-
- for (int i = 0; i < _fs->audio_channels(); ++i) {
- delete[] out[i];
+ write_audio (out);
}
swr_free (&_swr_context);
@@ -342,50 +335,43 @@ J2KWAVEncoder::process_end ()
}
void
-J2KWAVEncoder::process_audio (float** data, int frames)
+J2KWAVEncoder::process_audio (shared_ptr<const AudioBuffers> audio)
{
- float* resampled[_fs->audio_channels()];
+ shared_ptr<AudioBuffers> resampled;
-#if HAVE_SWRESAMPLE
+#if HAVE_SWRESAMPLE
/* Maybe sample-rate convert */
if (_swr_context) {
/* Compute the resampled frames count and add 32 for luck */
- int const max_resampled_frames = ceil (frames * _fs->target_sample_rate() / _fs->audio_sample_rate()) + 32;
+ int const max_resampled_frames = ceil (audio->frames() * _fs->target_sample_rate() / _fs->audio_sample_rate()) + 32;
- /* Make a buffer to put the result in */
- for (int i = 0; i < _fs->audio_channels(); ++i) {
- resampled[i] = new float[max_resampled_frames];
- }
+ resampled.reset (new AudioBuffers (_fs->audio_channels(), max_resampled_frames));
/* Resample audio */
- int const resampled_frames = swr_convert (_swr_context, (uint8_t **) resampled, max_resampled_frames, (uint8_t const **) data, frames);
+ int const resampled_frames = swr_convert (
+ _swr_context, (uint8_t **) resampled->data(), max_resampled_frames, (uint8_t const **) audio->data(), audio->frames()
+ );
+
if (resampled_frames < 0) {
throw EncodeError ("could not run sample-rate converter");
}
+ resampled->set_frames (resampled_frames);
+
/* And point our variables at the resampled audio */
- data = resampled;
- frames = resampled_frames;
+ audio = resampled;
}
#endif
- write_audio (data, frames);
-
-#if HAVE_SWRESAMPLE
- if (_swr_context) {
- for (int i = 0; i < _fs->audio_channels(); ++i) {
- delete[] resampled[i];
- }
- }
-#endif
+ write_audio (audio);
}
void
-J2KWAVEncoder::write_audio (float** data, int frames)
+J2KWAVEncoder::write_audio (shared_ptr<const AudioBuffers> audio) const
{
for (int i = 0; i < _fs->audio_channels(); ++i) {
- sf_write_float (_sound_files[i], data[i], frames);
+ sf_write_float (_sound_files[i], audio->data(i), audio->frames());
}
}
diff --git a/src/lib/j2k_wav_encoder.h b/src/lib/j2k_wav_encoder.h
index 3fdefcb38..2c18a5730 100644
--- a/src/lib/j2k_wav_encoder.h
+++ b/src/lib/j2k_wav_encoder.h
@@ -39,6 +39,7 @@ class DCPVideoFrame;
class Image;
class Log;
class Subtitle;
+class AudioBuffers;
/** @class J2KWAVEncoder
* @brief An encoder which writes JPEG2000 and WAV files.
@@ -51,12 +52,12 @@ public:
void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format);
void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>);
- void process_audio (float**, int);
+ void process_audio (boost::shared_ptr<const AudioBuffers>);
void process_end ();
private:
- void write_audio (float** data, int frames);
+ void write_audio (boost::shared_ptr<const AudioBuffers> audio) const;
void encoder_thread (ServerDescription *);
void close_sound_files ();
void terminate_worker_threads ();
diff --git a/src/lib/util.cc b/src/lib/util.cc
index 3f5200ead..52a75474b 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -693,3 +693,39 @@ get_optional_int (multimap<string, string> const & kv, string k)
return lexical_cast<int> (i->second);
}
+
+AudioBuffers::AudioBuffers (int channels, int frames)
+ : _channels (channels)
+ , _frames (frames)
+{
+ _data = new float*[_channels];
+ for (int i = 0; i < _channels; ++i) {
+ _data[i] = new float[frames];
+ }
+}
+
+AudioBuffers::~AudioBuffers ()
+{
+ for (int i = 0; i < _channels; ++i) {
+ delete[] _data[i];
+ }
+
+ delete[] _data;
+}
+
+float*
+AudioBuffers::data (int c) const
+{
+ assert (c >= 0 && c < _channels);
+ return _data[c];
+}
+
+void
+AudioBuffers::set_frames (int f)
+{
+ assert (f <= _frames);
+ _frames = f;
+}
+
+
+
diff --git a/src/lib/util.h b/src/lib/util.h
index f2087b3f0..c98049f62 100644
--- a/src/lib/util.h
+++ b/src/lib/util.h
@@ -203,5 +203,29 @@ private:
int _buffer_data;
};
+class AudioBuffers
+{
+public:
+ AudioBuffers (int channels, int frames);
+ ~AudioBuffers ();
+
+ float** data () const {
+ return _data;
+ }
+
+ float* data (int) const;
+
+ int frames () const {
+ return _frames;
+ }
+
+ void set_frames (int f);
+
+private:
+ int _channels;
+ int _frames;
+ float** _data;
+};
+
#endif