summaryrefslogtreecommitdiff
path: root/src/sound_asset_writer.h
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2023-03-16 21:07:10 +0100
committerCarl Hetherington <cth@carlh.net>2023-03-16 21:07:10 +0100
commit8c5aed0c60927ad3f22ef3b620a4c2e000316a65 (patch)
treebee8b41ba5b48cedf7b402367234f4f5eef9d01c /src/sound_asset_writer.h
parentc1d296b163ddf88a5b387f98e7e77988a242a996 (diff)
Allow writing to sound assets with int32_t as well as float.
Diffstat (limited to 'src/sound_asset_writer.h')
-rw-r--r--src/sound_asset_writer.h80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/sound_asset_writer.h b/src/sound_asset_writer.h
index 6d8191c7..d8ebdc7b 100644
--- a/src/sound_asset_writer.h
+++ b/src/sound_asset_writer.h
@@ -38,8 +38,10 @@
#include "asset_writer.h"
+#include "dcp_assert.h"
#include "fsk.h"
#include "types.h"
+#include "sound_asset.h"
#include "sound_frame.h"
#include <memory>
#include <boost/filesystem.hpp>
@@ -52,6 +54,30 @@ struct sync_test1;
namespace dcp {
+namespace sound_asset_writer {
+
+template <typename T>
+int32_t convert(T) { return {}; }
+
+template <>
+inline int32_t convert(int32_t x)
+{
+ int constexpr clip = (1 << 23);
+ return std::max(-clip, std::min(clip, x));
+}
+
+template<>
+inline int32_t convert(float x)
+{
+ float constexpr clip = 1.0f - (1.0f / (1 << 23));
+ float constexpr scale = (1 << 23);
+ auto const clipped = std::max(-clip, std::min(clip, x));
+ return std::lround(clipped * scale);
+}
+
+}
+
+
class SoundAsset;
@@ -76,12 +102,66 @@ public:
*/
void write(float const * const * data, int channels, int frames);
+ /** @param data Pointer an array of int32_t pointers, one for each channel.
+ * The 24-bit audio sample should be in the lower 24 bits of the int32_t.
+ * @param channels Number of channels in data; if this is less than the channels in the asset
+ * the remaining asset channels will be padded with silence.
+ * @param frames Number of frames i.e. number of floats that are given for each channel.
+ */
+ void write(int32_t const * const * data, int channels, int frames);
+
bool finalize () override;
private:
friend class SoundAsset;
friend struct ::sync_test1;
+ byte_t* frame_buffer_data() const;
+ int frame_buffer_capacity() const;
+
+ template <class T>
+ void
+ do_write(T const * const * data, int data_channels, int frames)
+ {
+ DCP_ASSERT(!_finalized);
+ DCP_ASSERT(frames > 0);
+
+ auto const asset_channels = _asset->channels();
+ DCP_ASSERT(data_channels <= asset_channels);
+
+ if (!_started) {
+ start();
+ }
+
+ for (int i = 0; i < frames; ++i) {
+
+ auto out = frame_buffer_data() + _frame_buffer_offset;
+
+ /* Write one sample per asset channel */
+ for (int j = 0; j < asset_channels; ++j) {
+ int32_t s = 0;
+ if (j == 13 && _sync) {
+ s = _fsk.get();
+ } else if (j < data_channels) {
+ s = sound_asset_writer::convert(data[j][i]);
+ }
+ *out++ = (s & 0xff);
+ *out++ = (s & 0xff00) >> 8;
+ *out++ = (s & 0xff0000) >> 16;
+ }
+ _frame_buffer_offset += 3 * asset_channels;
+
+ DCP_ASSERT(_frame_buffer_offset <= frame_buffer_capacity());
+
+ /* Finish the MXF frame if required */
+ if (_frame_buffer_offset == frame_buffer_capacity()) {
+ write_current_frame();
+ _frame_buffer_offset = 0;
+ memset(frame_buffer_data(), 0, frame_buffer_capacity());
+ }
+ }
+ }
+
SoundAssetWriter(SoundAsset *, boost::filesystem::path, bool sync, bool include_mca_subdescriptors);
void start ();