New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// MSVC++ requires this to be set before any other includes to get M_PI.
|
|
|
|
|
#define _USE_MATH_DEFINES
|
|
|
|
|
|
2019-07-05 19:08:33 +02:00
|
|
|
#include "common_audio/wav_file.h"
|
|
|
|
|
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
#include <cmath>
|
|
|
|
|
#include <limits>
|
|
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "common_audio/wav_header.h"
|
2024-11-20 14:30:17 +01:00
|
|
|
#include "rtc_base/logging.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "test/gtest.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "test/testsupport/file_utils.h"
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
|
2019-06-27 10:52:14 +02:00
|
|
|
// WavWriterTest.CPP flaky on Mac. See webrtc:9247.
|
2018-05-07 16:33:36 +02:00
|
|
|
#if defined(WEBRTC_MAC)
|
|
|
|
|
#define MAYBE_CPP DISABLED_CPP
|
2019-04-16 16:49:32 +02:00
|
|
|
#define MAYBE_CPPReset DISABLED_CPPReset
|
2018-05-07 16:33:36 +02:00
|
|
|
#else
|
|
|
|
|
#define MAYBE_CPP CPP
|
2019-04-16 16:49:32 +02:00
|
|
|
#define MAYBE_CPPReset CPPReset
|
2018-05-07 16:33:36 +02:00
|
|
|
#endif
|
|
|
|
|
|
2014-12-16 20:17:21 +00:00
|
|
|
namespace webrtc {
|
|
|
|
|
|
2024-11-20 14:30:17 +01:00
|
|
|
namespace {
|
|
|
|
|
const char* SampleFormatToStr(WavFile::SampleFormat format) {
|
|
|
|
|
switch (format) {
|
|
|
|
|
case WavFile::SampleFormat::kInt16:
|
|
|
|
|
return "int16";
|
|
|
|
|
case WavFile::SampleFormat::kFloat:
|
|
|
|
|
return "float";
|
|
|
|
|
}
|
|
|
|
|
RTC_CHECK_NOTREACHED();
|
|
|
|
|
}
|
|
|
|
|
} // namespace
|
|
|
|
|
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
static const float kSamples[] = {0.0, 10.0, 4e4, -1e9};
|
|
|
|
|
|
|
|
|
|
// Write a tiny WAV file with the C++ interface and verify the result.
|
2018-05-07 16:33:36 +02:00
|
|
|
TEST(WavWriterTest, MAYBE_CPP) {
|
2024-02-08 12:47:54 +02:00
|
|
|
const std::string outfile =
|
2024-02-14 10:07:56 +02:00
|
|
|
test::OutputPathWithRandomDirectory() + "wavtest1.wav";
|
Misc. small cleanups.
* Better param names
* Avoid using negative values for (bogus) placeholder channel counts (mostly in tests). Since channels will be changing to size_t, negative values will be illegal; it's sufficient to use 0 in these cases.
* Use arraysize()
* Use size_t for counting frames, samples, blocks, buffers, and bytes -- most of these are already size_t in most places, this just fixes some stragglers
* reinterpret_cast<int64_t>(void*) is not necessarily safe; use uintptr_t instead
* Remove unnecessary code, e.g. dead code, needlessly long/repetitive code, or function overrides that exactly match the base definition
* Fix indenting
* Use uint32_t for timestamps (matching how it's already a uint32_t in most places)
* Spelling
* RTC_CHECK_EQ(expected, actual)
* Rewrap
* Use .empty()
* Be more pedantic about matching int/int32_t/
* Remove pointless consts on input parameters to functions
* Add missing sanity checks
All this was found in the course of constructing https://codereview.webrtc.org/1316523002/ , and is being landed separately first.
BUG=none
TEST=none
Review URL: https://codereview.webrtc.org/1534193008
Cr-Commit-Position: refs/heads/master@{#11191}
2016-01-08 13:50:27 -08:00
|
|
|
static const size_t kNumSamples = 3;
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
{
|
2014-12-16 20:17:21 +00:00
|
|
|
WavWriter w(outfile, 14099, 1);
|
2014-08-25 06:26:04 +00:00
|
|
|
EXPECT_EQ(14099, w.sample_rate());
|
Convert channel counts to size_t.
IIRC, this was originally requested by ajm during review of the other size_t conversions I did over the past year, and I agreed it made sense, but wanted to do it separately since those changes were already gargantuan.
BUG=chromium:81439
TEST=none
R=henrik.lundin@webrtc.org, henrika@webrtc.org, kjellander@webrtc.org, minyue@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1316523002 .
Cr-Commit-Position: refs/heads/master@{#11229}
2016-01-12 16:26:35 -08:00
|
|
|
EXPECT_EQ(1u, w.num_channels());
|
2014-08-25 06:26:04 +00:00
|
|
|
EXPECT_EQ(0u, w.num_samples());
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
w.WriteSamples(kSamples, kNumSamples);
|
2014-08-25 06:26:04 +00:00
|
|
|
EXPECT_EQ(kNumSamples, w.num_samples());
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
}
|
2014-12-16 20:17:21 +00:00
|
|
|
// Write some extra "metadata" to the file that should be silently ignored
|
|
|
|
|
// by WavReader. We don't use WavWriter directly for this because it doesn't
|
|
|
|
|
// support metadata.
|
|
|
|
|
static const uint8_t kMetadata[] = {101, 202};
|
|
|
|
|
{
|
|
|
|
|
FILE* f = fopen(outfile.c_str(), "ab");
|
|
|
|
|
ASSERT_TRUE(f);
|
|
|
|
|
ASSERT_EQ(1u, fwrite(kMetadata, sizeof(kMetadata), 1, f));
|
|
|
|
|
fclose(f);
|
|
|
|
|
}
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
static const uint8_t kExpectedContents[] = {
|
2018-06-19 15:03:05 +02:00
|
|
|
// clang-format off
|
|
|
|
|
// clang formatting doesn't respect inline comments.
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
'R', 'I', 'F', 'F',
|
|
|
|
|
42, 0, 0, 0, // size of whole file - 8: 6 + 44 - 8
|
|
|
|
|
'W', 'A', 'V', 'E',
|
|
|
|
|
'f', 'm', 't', ' ',
|
|
|
|
|
16, 0, 0, 0, // size of fmt block - 8: 24 - 8
|
|
|
|
|
1, 0, // format: PCM (1)
|
|
|
|
|
1, 0, // channels: 1
|
|
|
|
|
0x13, 0x37, 0, 0, // sample rate: 14099
|
|
|
|
|
0x26, 0x6e, 0, 0, // byte rate: 2 * 14099
|
|
|
|
|
2, 0, // block align: NumChannels * BytesPerSample
|
|
|
|
|
16, 0, // bits per sample: 2 * 8
|
|
|
|
|
'd', 'a', 't', 'a',
|
|
|
|
|
6, 0, 0, 0, // size of payload: 6
|
|
|
|
|
0, 0, // first sample: 0.0
|
|
|
|
|
10, 0, // second sample: 10.0
|
|
|
|
|
0xff, 0x7f, // third sample: 4e4 (saturated)
|
2014-12-16 20:17:21 +00:00
|
|
|
kMetadata[0], kMetadata[1],
|
2018-06-19 15:03:05 +02:00
|
|
|
// clang-format on
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
};
|
Misc. small cleanups.
* Better param names
* Avoid using negative values for (bogus) placeholder channel counts (mostly in tests). Since channels will be changing to size_t, negative values will be illegal; it's sufficient to use 0 in these cases.
* Use arraysize()
* Use size_t for counting frames, samples, blocks, buffers, and bytes -- most of these are already size_t in most places, this just fixes some stragglers
* reinterpret_cast<int64_t>(void*) is not necessarily safe; use uintptr_t instead
* Remove unnecessary code, e.g. dead code, needlessly long/repetitive code, or function overrides that exactly match the base definition
* Fix indenting
* Use uint32_t for timestamps (matching how it's already a uint32_t in most places)
* Spelling
* RTC_CHECK_EQ(expected, actual)
* Rewrap
* Use .empty()
* Be more pedantic about matching int/int32_t/
* Remove pointless consts on input parameters to functions
* Add missing sanity checks
All this was found in the course of constructing https://codereview.webrtc.org/1316523002/ , and is being landed separately first.
BUG=none
TEST=none
Review URL: https://codereview.webrtc.org/1534193008
Cr-Commit-Position: refs/heads/master@{#11191}
2016-01-08 13:50:27 -08:00
|
|
|
static const size_t kContentSize =
|
2020-01-28 09:08:11 +01:00
|
|
|
kPcmWavHeaderSize + kNumSamples * sizeof(int16_t) + sizeof(kMetadata);
|
2015-01-14 10:51:54 +00:00
|
|
|
static_assert(sizeof(kExpectedContents) == kContentSize, "content size");
|
Misc. small cleanups.
* Better param names
* Avoid using negative values for (bogus) placeholder channel counts (mostly in tests). Since channels will be changing to size_t, negative values will be illegal; it's sufficient to use 0 in these cases.
* Use arraysize()
* Use size_t for counting frames, samples, blocks, buffers, and bytes -- most of these are already size_t in most places, this just fixes some stragglers
* reinterpret_cast<int64_t>(void*) is not necessarily safe; use uintptr_t instead
* Remove unnecessary code, e.g. dead code, needlessly long/repetitive code, or function overrides that exactly match the base definition
* Fix indenting
* Use uint32_t for timestamps (matching how it's already a uint32_t in most places)
* Spelling
* RTC_CHECK_EQ(expected, actual)
* Rewrap
* Use .empty()
* Be more pedantic about matching int/int32_t/
* Remove pointless consts on input parameters to functions
* Add missing sanity checks
All this was found in the course of constructing https://codereview.webrtc.org/1316523002/ , and is being landed separately first.
BUG=none
TEST=none
Review URL: https://codereview.webrtc.org/1534193008
Cr-Commit-Position: refs/heads/master@{#11191}
2016-01-08 13:50:27 -08:00
|
|
|
EXPECT_EQ(kContentSize, test::GetFileSize(outfile));
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
FILE* f = fopen(outfile.c_str(), "rb");
|
|
|
|
|
ASSERT_TRUE(f);
|
|
|
|
|
uint8_t contents[kContentSize];
|
|
|
|
|
ASSERT_EQ(1u, fread(contents, kContentSize, 1, f));
|
|
|
|
|
EXPECT_EQ(0, fclose(f));
|
|
|
|
|
EXPECT_EQ(0, memcmp(kExpectedContents, contents, kContentSize));
|
2014-10-31 21:51:03 +00:00
|
|
|
|
|
|
|
|
{
|
2014-12-16 20:17:21 +00:00
|
|
|
WavReader r(outfile);
|
2014-10-31 21:51:03 +00:00
|
|
|
EXPECT_EQ(14099, r.sample_rate());
|
Convert channel counts to size_t.
IIRC, this was originally requested by ajm during review of the other size_t conversions I did over the past year, and I agreed it made sense, but wanted to do it separately since those changes were already gargantuan.
BUG=chromium:81439
TEST=none
R=henrik.lundin@webrtc.org, henrika@webrtc.org, kjellander@webrtc.org, minyue@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1316523002 .
Cr-Commit-Position: refs/heads/master@{#11229}
2016-01-12 16:26:35 -08:00
|
|
|
EXPECT_EQ(1u, r.num_channels());
|
2014-10-31 21:51:03 +00:00
|
|
|
EXPECT_EQ(kNumSamples, r.num_samples());
|
|
|
|
|
static const float kTruncatedSamples[] = {0.0, 10.0, 32767.0};
|
|
|
|
|
float samples[kNumSamples];
|
|
|
|
|
EXPECT_EQ(kNumSamples, r.ReadSamples(kNumSamples, samples));
|
|
|
|
|
EXPECT_EQ(0, memcmp(kTruncatedSamples, samples, sizeof(samples)));
|
|
|
|
|
EXPECT_EQ(0u, r.ReadSamples(kNumSamples, samples));
|
|
|
|
|
}
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write a larger WAV file. You can listen to this file to sanity-check it.
|
|
|
|
|
TEST(WavWriterTest, LargeFile) {
|
2020-01-28 09:08:11 +01:00
|
|
|
constexpr int kSampleRate = 8000;
|
|
|
|
|
constexpr size_t kNumChannels = 2;
|
|
|
|
|
constexpr size_t kNumSamples = 3 * kSampleRate * kNumChannels;
|
|
|
|
|
for (WavFile::SampleFormat wav_format :
|
|
|
|
|
{WavFile::SampleFormat::kInt16, WavFile::SampleFormat::kFloat}) {
|
|
|
|
|
for (WavFile::SampleFormat write_format :
|
|
|
|
|
{WavFile::SampleFormat::kInt16, WavFile::SampleFormat::kFloat}) {
|
|
|
|
|
for (WavFile::SampleFormat read_format :
|
|
|
|
|
{WavFile::SampleFormat::kInt16, WavFile::SampleFormat::kFloat}) {
|
2024-11-21 10:23:19 +01:00
|
|
|
std::string outdir = test::OutputPathWithRandomDirectory();
|
|
|
|
|
std::string outfile = outdir + "wavtest3.wav";
|
2020-01-28 09:08:11 +01:00
|
|
|
float samples[kNumSamples];
|
|
|
|
|
for (size_t i = 0; i < kNumSamples; i += kNumChannels) {
|
|
|
|
|
// A nice periodic beeping sound.
|
|
|
|
|
static const double kToneHz = 440;
|
|
|
|
|
const double t =
|
|
|
|
|
static_cast<double>(i) / (kNumChannels * kSampleRate);
|
|
|
|
|
const double x = std::numeric_limits<int16_t>::max() *
|
|
|
|
|
std::sin(t * kToneHz * 2 * M_PI);
|
|
|
|
|
samples[i] = std::pow(std::sin(t * 2 * 2 * M_PI), 10) * x;
|
|
|
|
|
samples[i + 1] = std::pow(std::cos(t * 2 * 2 * M_PI), 10) * x;
|
2024-11-20 14:30:17 +01:00
|
|
|
// See https://issues.webrtc.org/issues/379973428
|
|
|
|
|
RTC_CHECK(isfinite(samples[i]));
|
|
|
|
|
RTC_CHECK(isfinite(samples[i + 1]));
|
2020-01-28 09:08:11 +01:00
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
WavWriter w(outfile, kSampleRate, kNumChannels, wav_format);
|
|
|
|
|
EXPECT_EQ(kSampleRate, w.sample_rate());
|
|
|
|
|
EXPECT_EQ(kNumChannels, w.num_channels());
|
|
|
|
|
EXPECT_EQ(0u, w.num_samples());
|
|
|
|
|
if (write_format == WavFile::SampleFormat::kFloat) {
|
2024-11-21 10:12:00 +01:00
|
|
|
int16_t truncated_samples[kNumSamples];
|
2020-01-28 09:08:11 +01:00
|
|
|
for (size_t k = 0; k < kNumSamples; ++k) {
|
|
|
|
|
truncated_samples[k] = static_cast<int16_t>(samples[k]);
|
|
|
|
|
}
|
|
|
|
|
w.WriteSamples(truncated_samples, kNumSamples);
|
|
|
|
|
} else {
|
|
|
|
|
w.WriteSamples(samples, kNumSamples);
|
|
|
|
|
}
|
|
|
|
|
EXPECT_EQ(kNumSamples, w.num_samples());
|
|
|
|
|
}
|
|
|
|
|
if (wav_format == WavFile::SampleFormat::kFloat) {
|
|
|
|
|
EXPECT_EQ(sizeof(float) * kNumSamples + kIeeeFloatWavHeaderSize,
|
|
|
|
|
test::GetFileSize(outfile));
|
|
|
|
|
} else {
|
|
|
|
|
EXPECT_EQ(sizeof(int16_t) * kNumSamples + kPcmWavHeaderSize,
|
|
|
|
|
test::GetFileSize(outfile));
|
|
|
|
|
}
|
2014-10-31 21:51:03 +00:00
|
|
|
|
2020-01-28 09:08:11 +01:00
|
|
|
{
|
|
|
|
|
WavReader r(outfile);
|
|
|
|
|
EXPECT_EQ(kSampleRate, r.sample_rate());
|
|
|
|
|
EXPECT_EQ(kNumChannels, r.num_channels());
|
|
|
|
|
EXPECT_EQ(kNumSamples, r.num_samples());
|
2014-10-31 21:51:03 +00:00
|
|
|
|
2020-01-28 09:08:11 +01:00
|
|
|
if (read_format == WavFile::SampleFormat::kFloat) {
|
|
|
|
|
float read_samples[kNumSamples];
|
|
|
|
|
EXPECT_EQ(kNumSamples, r.ReadSamples(kNumSamples, read_samples));
|
|
|
|
|
for (size_t i = 0; i < kNumSamples; ++i) {
|
|
|
|
|
EXPECT_NEAR(samples[i], read_samples[i], 1);
|
2024-11-20 14:30:17 +01:00
|
|
|
if (!isfinite(samples[i])) {
|
|
|
|
|
// See https://issues.webrtc.org/issues/379973428
|
|
|
|
|
RTC_LOG(LS_ERROR)
|
|
|
|
|
<< "samples[" << i << "] is not finite. "
|
|
|
|
|
<< "wav_format=" << SampleFormatToStr(wav_format)
|
|
|
|
|
<< ", write_format=" << SampleFormatToStr(write_format)
|
|
|
|
|
<< ", read_format=" << SampleFormatToStr(read_format);
|
|
|
|
|
}
|
2020-01-28 09:08:11 +01:00
|
|
|
}
|
|
|
|
|
EXPECT_EQ(0u, r.ReadSamples(kNumSamples, read_samples));
|
|
|
|
|
} else {
|
|
|
|
|
int16_t read_samples[kNumSamples];
|
|
|
|
|
EXPECT_EQ(kNumSamples, r.ReadSamples(kNumSamples, read_samples));
|
|
|
|
|
for (size_t i = 0; i < kNumSamples; ++i) {
|
|
|
|
|
EXPECT_NEAR(samples[i], static_cast<float>(read_samples[i]), 1);
|
2024-11-20 14:30:17 +01:00
|
|
|
if (!isfinite(samples[i])) {
|
|
|
|
|
// See https://issues.webrtc.org/issues/379973428
|
|
|
|
|
RTC_LOG(LS_ERROR)
|
|
|
|
|
<< "samples[" << i << "] is not finite. "
|
|
|
|
|
<< "wav_format=" << SampleFormatToStr(wav_format)
|
|
|
|
|
<< ", write_format=" << SampleFormatToStr(write_format)
|
|
|
|
|
<< ", read_format=" << SampleFormatToStr(read_format);
|
|
|
|
|
}
|
2020-01-28 09:08:11 +01:00
|
|
|
}
|
|
|
|
|
EXPECT_EQ(0u, r.ReadSamples(kNumSamples, read_samples));
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-21 10:23:19 +01:00
|
|
|
RTC_CHECK(test::RemoveFile(outfile));
|
|
|
|
|
RTC_CHECK(test::RemoveDir(outdir));
|
2020-01-28 09:08:11 +01:00
|
|
|
}
|
|
|
|
|
}
|
2014-10-31 21:51:03 +00:00
|
|
|
}
|
New utility class for easy debug dumping to WAV files
There are currently a number of places in the code where we dump audio
data in various stages of processing for debug purposes. Currently
these all write raw, uncompressed PCM files, which isn't supported by
the most common audio players, and requires the user to supply
metadata such as sample rate, sample size and endianness, etc.
This patch adds a simple class that makes it easy to write WAV files
instead. WAV files still contain the same uncompressed PCM data, but
they have a small header that contains all the requisite metadata, and
are supported by virtually all audio players.
Since some of the debug code that will be writing WAV files is written
in plain C, a C API is included as well.
R=andrew@webrtc.org, bjornv@webrtc.org, henrike@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/16809004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6932 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-08-20 07:42:46 +00:00
|
|
|
}
|
2014-12-16 20:17:21 +00:00
|
|
|
|
2019-04-16 16:49:32 +02:00
|
|
|
// Write a tiny WAV file with the C++ interface then read-reset-read.
|
|
|
|
|
TEST(WavReaderTest, MAYBE_CPPReset) {
|
2024-02-14 10:07:56 +02:00
|
|
|
const std::string outfile =
|
|
|
|
|
test::OutputPathWithRandomDirectory() + "wavtest4.wav";
|
2019-04-16 16:49:32 +02:00
|
|
|
static const size_t kNumSamples = 3;
|
|
|
|
|
{
|
|
|
|
|
WavWriter w(outfile, 14099, 1);
|
|
|
|
|
EXPECT_EQ(14099, w.sample_rate());
|
|
|
|
|
EXPECT_EQ(1u, w.num_channels());
|
|
|
|
|
EXPECT_EQ(0u, w.num_samples());
|
|
|
|
|
w.WriteSamples(kSamples, kNumSamples);
|
|
|
|
|
EXPECT_EQ(kNumSamples, w.num_samples());
|
|
|
|
|
}
|
|
|
|
|
// Write some extra "metadata" to the file that should be silently ignored
|
|
|
|
|
// by WavReader. We don't use WavWriter directly for this because it doesn't
|
|
|
|
|
// support metadata.
|
|
|
|
|
static const uint8_t kMetadata[] = {101, 202};
|
|
|
|
|
{
|
|
|
|
|
FILE* f = fopen(outfile.c_str(), "ab");
|
|
|
|
|
ASSERT_TRUE(f);
|
|
|
|
|
ASSERT_EQ(1u, fwrite(kMetadata, sizeof(kMetadata), 1, f));
|
|
|
|
|
fclose(f);
|
|
|
|
|
}
|
|
|
|
|
static const uint8_t kExpectedContents[] = {
|
|
|
|
|
// clang-format off
|
|
|
|
|
// clang formatting doesn't respect inline comments.
|
|
|
|
|
'R', 'I', 'F', 'F',
|
|
|
|
|
42, 0, 0, 0, // size of whole file - 8: 6 + 44 - 8
|
|
|
|
|
'W', 'A', 'V', 'E',
|
|
|
|
|
'f', 'm', 't', ' ',
|
|
|
|
|
16, 0, 0, 0, // size of fmt block - 8: 24 - 8
|
|
|
|
|
1, 0, // format: PCM (1)
|
|
|
|
|
1, 0, // channels: 1
|
|
|
|
|
0x13, 0x37, 0, 0, // sample rate: 14099
|
|
|
|
|
0x26, 0x6e, 0, 0, // byte rate: 2 * 14099
|
|
|
|
|
2, 0, // block align: NumChannels * BytesPerSample
|
|
|
|
|
16, 0, // bits per sample: 2 * 8
|
|
|
|
|
'd', 'a', 't', 'a',
|
|
|
|
|
6, 0, 0, 0, // size of payload: 6
|
|
|
|
|
0, 0, // first sample: 0.0
|
|
|
|
|
10, 0, // second sample: 10.0
|
|
|
|
|
0xff, 0x7f, // third sample: 4e4 (saturated)
|
|
|
|
|
kMetadata[0], kMetadata[1],
|
|
|
|
|
// clang-format on
|
|
|
|
|
};
|
|
|
|
|
static const size_t kContentSize =
|
2020-01-28 09:08:11 +01:00
|
|
|
kPcmWavHeaderSize + kNumSamples * sizeof(int16_t) + sizeof(kMetadata);
|
2019-04-16 16:49:32 +02:00
|
|
|
static_assert(sizeof(kExpectedContents) == kContentSize, "content size");
|
|
|
|
|
EXPECT_EQ(kContentSize, test::GetFileSize(outfile));
|
|
|
|
|
FILE* f = fopen(outfile.c_str(), "rb");
|
|
|
|
|
ASSERT_TRUE(f);
|
|
|
|
|
uint8_t contents[kContentSize];
|
|
|
|
|
ASSERT_EQ(1u, fread(contents, kContentSize, 1, f));
|
|
|
|
|
EXPECT_EQ(0, fclose(f));
|
|
|
|
|
EXPECT_EQ(0, memcmp(kExpectedContents, contents, kContentSize));
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
WavReader r(outfile);
|
|
|
|
|
EXPECT_EQ(14099, r.sample_rate());
|
|
|
|
|
EXPECT_EQ(1u, r.num_channels());
|
|
|
|
|
EXPECT_EQ(kNumSamples, r.num_samples());
|
|
|
|
|
static const float kTruncatedSamples[] = {0.0, 10.0, 32767.0};
|
|
|
|
|
float samples[kNumSamples];
|
|
|
|
|
EXPECT_EQ(kNumSamples, r.ReadSamples(kNumSamples, samples));
|
|
|
|
|
EXPECT_EQ(0, memcmp(kTruncatedSamples, samples, sizeof(samples)));
|
|
|
|
|
EXPECT_EQ(0u, r.ReadSamples(kNumSamples, samples));
|
|
|
|
|
|
|
|
|
|
r.Reset();
|
|
|
|
|
EXPECT_EQ(kNumSamples, r.ReadSamples(kNumSamples, samples));
|
|
|
|
|
EXPECT_EQ(0, memcmp(kTruncatedSamples, samples, sizeof(samples)));
|
|
|
|
|
EXPECT_EQ(0u, r.ReadSamples(kNumSamples, samples));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-16 20:17:21 +00:00
|
|
|
} // namespace webrtc
|