summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2023-03-16 19:51:27 +0100
committerCarl Hetherington <cth@carlh.net>2023-03-16 19:52:06 +0100
commitc1d296b163ddf88a5b387f98e7e77988a242a996 (patch)
tree4edbcca02dd8bfebdd9530eaad7004dfbb79d125
parent53b444191fddd72416647ec9d24aff1e317a1824 (diff)
Specify number of channels in the data passed to SoundAssetWriter, and pad channels that aren't there.
-rw-r--r--examples/make_dcp.cc2
-rw-r--r--src/sound_asset_writer.cc15
-rw-r--r--src/sound_asset_writer.h4
-rw-r--r--test/dcp_test.cc6
-rw-r--r--test/decryption_test.cc2
-rw-r--r--test/encryption_test.cc2
-rw-r--r--test/mca_test.cc2
-rw-r--r--test/sound_asset_writer_test.cc117
-rw-r--r--test/sync_test.cc2
-rw-r--r--test/test.cc2
-rw-r--r--test/wscript1
11 files changed, 138 insertions, 17 deletions
diff --git a/examples/make_dcp.cc b/examples/make_dcp.cc
index bbe29545..7f387db2 100644
--- a/examples/make_dcp.cc
+++ b/examples/make_dcp.cc
@@ -86,7 +86,7 @@ main ()
std::array<float*, 2> audio;
audio[0] = left.data();
audio[1] = right.data();
- sound_writer->write (audio.data(), 48000);
+ sound_writer->write(audio.data(), 2, 48000);
/* And finish off */
sound_writer->finalize ();
diff --git a/src/sound_asset_writer.cc b/src/sound_asset_writer.cc
index a0414aba..f789eb3b 100644
--- a/src/sound_asset_writer.cc
+++ b/src/sound_asset_writer.cc
@@ -200,29 +200,30 @@ LIBDCP_ENABLE_WARNINGS
void
-SoundAssetWriter::write (float const * const * data, int frames)
+SoundAssetWriter::write(float 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);
+
static float const clip = 1.0f - (1.0f / pow (2, 23));
if (!_started) {
start ();
}
- int const ch = _asset->channels ();
-
for (int i = 0; i < frames; ++i) {
byte_t* out = _state->frame_buffer.Data() + _frame_buffer_offset;
- /* Write one sample per channel */
- for (int j = 0; j < ch; ++j) {
+ /* 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 {
+ } else if (j < data_channels) {
/* Convert sample to 24-bit int, clipping if necessary. */
float x = data[j][i];
if (x > clip) {
@@ -236,7 +237,7 @@ SoundAssetWriter::write (float const * const * data, int frames)
*out++ = (s & 0xff00) >> 8;
*out++ = (s & 0xff0000) >> 16;
}
- _frame_buffer_offset += 3 * ch;
+ _frame_buffer_offset += 3 * asset_channels;
DCP_ASSERT (_frame_buffer_offset <= int(_state->frame_buffer.Capacity()));
diff --git a/src/sound_asset_writer.h b/src/sound_asset_writer.h
index 0435b85f..6d8191c7 100644
--- a/src/sound_asset_writer.h
+++ b/src/sound_asset_writer.h
@@ -70,9 +70,11 @@ public:
~SoundAssetWriter();
/** @param data Pointer an array of float pointers, one for each channel.
+ * @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 (float const * const *, int);
+ void write(float const * const * data, int channels, int frames);
bool finalize () override;
diff --git a/test/dcp_test.cc b/test/dcp_test.cc
index 7618f2ee..71564238 100644
--- a/test/dcp_test.cc
+++ b/test/dcp_test.cc
@@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE (dcp_test2)
channels[0] = buffer;
while (true) {
auto N = sf_readf_float (sndfile, buffer, 4096);
- sound_writer->write (channels, N);
+ sound_writer->write(channels, 1, N);
if (N < 4096) {
break;
}
@@ -224,7 +224,7 @@ test_rewriting_sound(string name, bool modify)
}
}
}
- writer->write (out, sf->samples());
+ writer->write(out, sf->channels(), sf->samples());
for (int j = 0; j < sf->channels(); ++j) {
delete[] out[j];
}
@@ -308,7 +308,7 @@ BOOST_AUTO_TEST_CASE (dcp_test5)
channels[0] = buffer;
while (true) {
sf_count_t N = sf_readf_float (sndfile, buffer, 4096);
- sound_writer->write (channels, N);
+ sound_writer->write(channels, 1, N);
if (N < 4096) {
break;
}
diff --git a/test/decryption_test.cc b/test/decryption_test.cc
index be688908..c24402bf 100644
--- a/test/decryption_test.cc
+++ b/test/decryption_test.cc
@@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE (decryption_test2)
std::array<float*, 2> audio;
audio[0] = left.data();
audio[1] = right.data();
- sound_writer->write (audio.data(), 48000);
+ sound_writer->write(audio.data(), 2, 48000);
sound_writer->finalize ();
auto subs_asset = std::make_shared<dcp::SMPTESubtitleAsset>();
diff --git a/test/encryption_test.cc b/test/encryption_test.cc
index 93cea8dc..2b9a6bea 100644
--- a/test/encryption_test.cc
+++ b/test/encryption_test.cc
@@ -114,7 +114,7 @@ BOOST_AUTO_TEST_CASE (encryption_test)
channels[0] = buffer;
while (true) {
auto N = sf_readf_float (sndfile, buffer, 4096);
- sound_writer->write (channels, N);
+ sound_writer->write(channels, 1, N);
if (N < 4096) {
break;
}
diff --git a/test/mca_test.cc b/test/mca_test.cc
index 12b4f2c6..fc5dda25 100644
--- a/test/mca_test.cc
+++ b/test/mca_test.cc
@@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE (write_mca_descriptors_to_mxf_test)
memset (samples[i], 0, 2000 * sizeof(float));
}
for (int i = 0; i < 24; ++i) {
- writer->write(samples, 2000);
+ writer->write(samples, 6, 2000);
}
for (int i = 0; i < 6; ++i) {
delete[] samples[i];
diff --git a/test/sound_asset_writer_test.cc b/test/sound_asset_writer_test.cc
new file mode 100644
index 00000000..32ab06b5
--- /dev/null
+++ b/test/sound_asset_writer_test.cc
@@ -0,0 +1,117 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "sound_asset.h"
+#include "sound_asset_writer.h"
+#include <boost/filesystem.hpp>
+#include <boost/random.hpp>
+#include <boost/test/unit_test.hpp>
+
+
+BOOST_AUTO_TEST_CASE(sound_asset_writer_no_padding_test)
+{
+ auto path = boost::filesystem::path("build/test/sound_asset_writer_no_padding_test.mxf");
+ dcp::SoundAsset asset({24, 1}, 48000, 6, dcp::LanguageTag{"en-GB"}, dcp::Standard::SMPTE);
+ auto writer = asset.start_write(path);
+
+ boost::random::mt19937 rng(1);
+ boost::random::uniform_int_distribution<> dist(0, 32767);
+
+ std::vector<std::vector<float>> buffers(6);
+ float* pointers[6];
+ for (auto channel = 0; channel < 6; ++channel) {
+ buffers[channel].resize(2000);
+ for (int sample = 0; sample < 2000; ++sample) {
+ buffers[channel][sample] = static_cast<float>(dist(rng)) / (1 << 23);
+ }
+ pointers[channel] = buffers[channel].data();
+ }
+
+ writer->write(pointers, 6, 2000);
+ writer->finalize();
+
+ dcp::SoundAsset check(path);
+ auto reader = check.start_read();
+ auto frame = reader->get_frame(0);
+
+ rng.seed(1);
+
+ for (auto channel = 0; channel < 6; ++channel) {
+ for (auto sample = 0; sample < 2000; ++sample) {
+ BOOST_REQUIRE_EQUAL(frame->get(channel, sample), dist(rng));
+ }
+ }
+}
+
+
+BOOST_AUTO_TEST_CASE(sound_asset_writer_padding_test)
+{
+ auto path = boost::filesystem::path("build/test/sound_asset_writer_padding_test.mxf");
+ dcp::SoundAsset asset({24, 1}, 48000, 14, dcp::LanguageTag{"en-GB"}, dcp::Standard::SMPTE);
+ auto writer = asset.start_write(path);
+
+ boost::random::mt19937 rng(1);
+ boost::random::uniform_int_distribution<> dist(0, 32767);
+
+ std::vector<std::vector<float>> buffers(6);
+ float* pointers[6];
+ for (auto channel = 0; channel < 6; ++channel) {
+ buffers[channel].resize(2000);
+ for (int sample = 0; sample < 2000; ++sample) {
+ buffers[channel][sample] = static_cast<float>(dist(rng)) / (1 << 23);
+ }
+ pointers[channel] = buffers[channel].data();
+ }
+
+ writer->write(pointers, 6, 2000);
+ writer->finalize();
+
+ dcp::SoundAsset check(path);
+ auto reader = check.start_read();
+ auto frame = reader->get_frame(0);
+
+ rng.seed(1);
+
+ for (auto channel = 0; channel < 6; ++channel) {
+ for (auto sample = 0; sample < 2000; ++sample) {
+ BOOST_REQUIRE_EQUAL(frame->get(channel, sample), dist(rng));
+ }
+ }
+
+ for (auto channel = 7; channel < 14; ++channel) {
+ for (auto sample = 0; sample < 2000; ++sample) {
+ BOOST_REQUIRE_EQUAL(frame->get(channel, sample), 0);
+ }
+ }
+}
diff --git a/test/sync_test.cc b/test/sync_test.cc
index 79e678b5..ba235bd4 100644
--- a/test/sync_test.cc
+++ b/test/sync_test.cc
@@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE (sync_test2)
}
}
- writer->write (junk, frames);
+ writer->write(junk, channels, frames);
for (int i = 0; i < channels; ++i) {
delete[] junk[i];
}
diff --git a/test/test.cc b/test/test.cc
index fb4f48c5..1b23b177 100644
--- a/test/test.cc
+++ b/test/test.cc
@@ -312,7 +312,7 @@ simple_sound(boost::filesystem::path path, string suffix, dcp::MXFMetadata mxf_m
}
for (auto i = 0; i < frames; ++i) {
- sound_writer->write (silence, samples_per_frame);
+ sound_writer->write(silence, channels, samples_per_frame);
}
sound_writer->finalize ();
diff --git a/test/wscript b/test/wscript
index b6cec631..22ae2ad4 100644
--- a/test/wscript
+++ b/test/wscript
@@ -105,6 +105,7 @@ def build(bld):
shared_subtitle_test.cc
smpte_load_font_test.cc
smpte_subtitle_test.cc
+ sound_asset_writer_test.cc
sound_frame_test.cc
stream_operators.cc
sync_test.cc