Clean up audio passing round a bit.
authorCarl Hetherington <cth@carlh.net>
Sat, 20 Oct 2012 17:39:15 +0000 (18:39 +0100)
committerCarl Hetherington <cth@carlh.net>
Sat, 20 Oct 2012 19:05:26 +0000 (20:05 +0100)
src/lib/decoder.cc
src/lib/decoder.h
src/lib/encoder.h
src/lib/imagemagick_encoder.h
src/lib/j2k_still_encoder.h
src/lib/j2k_wav_encoder.cc
src/lib/j2k_wav_encoder.h
src/lib/util.cc
src/lib/util.h

index 16d815a077e0b85328ad419eafff90abce516cc8..ee725c39d56eee0d03ce3956b021349edd5ec739 100644 (file)
@@ -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.
index 14e602aceac3fa51c8a16b0642a31f74093e7ffc..85b256f5bbe592629b8dad0c2b9c12396816aa73 100644 (file)
@@ -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 */
index 5dc0804c6a00643e51ca363653474144364789bb..3317d30d18497290ffa3f01b893c576890cdc45c 100644 (file)
@@ -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;
index 8e9c416aee0b986ce31da1607ed5e4d91105ee4d..06f1723b196351fbb84e448e3fba2b06c27f3a69 100644 (file)
@@ -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 () {}
 };
index 3c8f236ee13e74836e3400f59dd5f85998d0c5ba..7e7719321759efdb573f04fa97987b8b38c9ed6d 100644 (file)
@@ -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 () {}
 };
index 7697a5e783dbcfb2159b89b7636759c0dd7ccf3c..a83c283d7fc08a062d1af4f07f21c9c24b97ad6f 100644 (file)
@@ -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());
        }
 }
 
index 3fdefcb38ccd39a1c26b6ca9d018a0869e3dc2aa..2c18a5730700acb69fad2bbf2aab4750ea791899 100644 (file)
@@ -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 ();
index 3f5200ead1b2a2fdc80b3aac85d3f766fab71d51..52a75474b6597565e281bb75a0d491ada3c5c163 100644 (file)
@@ -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;
+}
+
+       
+       
index f2087b3f042476d4d42c286dfb834cf6b9c7d02d..c98049f62f2b1ef88006d9652ce3b9c539aff1cf 100644 (file)
@@ -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