diff options
Diffstat (limited to 'webrtc/common_audio')
31 files changed, 745 insertions, 293 deletions
diff --git a/webrtc/common_audio/BUILD.gn b/webrtc/common_audio/BUILD.gn index b01b31816b..b4ec1d71ef 100644 --- a/webrtc/common_audio/BUILD.gn +++ b/webrtc/common_audio/BUILD.gn @@ -87,6 +87,7 @@ source_set("common_audio") { "signal_processing/vector_scaling_operations.c", "sparse_fir_filter.cc", "sparse_fir_filter.h", + "swap_queue.h", "vad/include/vad.h", "vad/include/webrtc_vad.h", "vad/vad.cc", diff --git a/webrtc/common_audio/OWNERS b/webrtc/common_audio/OWNERS index 20f640041e..208a7c5635 100644 --- a/webrtc/common_audio/OWNERS +++ b/webrtc/common_audio/OWNERS @@ -1,4 +1,3 @@ -andrew@webrtc.org henrik.lundin@webrtc.org jan.skoglund@webrtc.org kwiberg@webrtc.org diff --git a/webrtc/common_audio/audio_converter.cc b/webrtc/common_audio/audio_converter.cc index f1709ae653..9ebfabc286 100644 --- a/webrtc/common_audio/audio_converter.cc +++ b/webrtc/common_audio/audio_converter.cc @@ -11,6 +11,7 @@ #include "webrtc/common_audio/audio_converter.h" #include <cstring> +#include <utility> #include "webrtc/base/checks.h" #include "webrtc/base/safe_conversions.h" @@ -24,7 +25,7 @@ namespace webrtc { class CopyConverter : public AudioConverter { public: - CopyConverter(int src_channels, size_t src_frames, int dst_channels, + CopyConverter(size_t src_channels, size_t src_frames, size_t dst_channels, size_t dst_frames) : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {} ~CopyConverter() override {}; @@ -33,7 +34,7 @@ class CopyConverter : public AudioConverter { size_t dst_capacity) override { CheckSizes(src_size, dst_capacity); if (src != dst) { - for (int i = 0; i < src_channels(); ++i) + for (size_t i = 0; i < src_channels(); ++i) std::memcpy(dst[i], src[i], dst_frames() * sizeof(*dst[i])); } } @@ -41,7 +42,7 @@ class CopyConverter : public AudioConverter { class UpmixConverter : public AudioConverter { public: - UpmixConverter(int src_channels, size_t src_frames, int dst_channels, + UpmixConverter(size_t src_channels, size_t src_frames, size_t dst_channels, size_t dst_frames) : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {} ~UpmixConverter() override {}; @@ -51,7 +52,7 @@ class UpmixConverter : public AudioConverter { CheckSizes(src_size, dst_capacity); for (size_t i = 0; i < dst_frames(); ++i) { const float value = src[0][i]; - for (int j = 0; j < dst_channels(); ++j) + for (size_t j = 0; j < dst_channels(); ++j) dst[j][i] = value; } } @@ -59,7 +60,7 @@ class UpmixConverter : public AudioConverter { class DownmixConverter : public AudioConverter { public: - DownmixConverter(int src_channels, size_t src_frames, int dst_channels, + DownmixConverter(size_t src_channels, size_t src_frames, size_t dst_channels, size_t dst_frames) : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) { } @@ -71,7 +72,7 @@ class DownmixConverter : public AudioConverter { float* dst_mono = dst[0]; for (size_t i = 0; i < src_frames(); ++i) { float sum = 0; - for (int j = 0; j < src_channels(); ++j) + for (size_t j = 0; j < src_channels(); ++j) sum += src[j][i]; dst_mono[i] = sum / src_channels(); } @@ -80,11 +81,11 @@ class DownmixConverter : public AudioConverter { class ResampleConverter : public AudioConverter { public: - ResampleConverter(int src_channels, size_t src_frames, int dst_channels, + ResampleConverter(size_t src_channels, size_t src_frames, size_t dst_channels, size_t dst_frames) : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) { resamplers_.reserve(src_channels); - for (int i = 0; i < src_channels; ++i) + for (size_t i = 0; i < src_channels; ++i) resamplers_.push_back(new PushSincResampler(src_frames, dst_frames)); } ~ResampleConverter() override {}; @@ -105,7 +106,7 @@ class ResampleConverter : public AudioConverter { class CompositionConverter : public AudioConverter { public: CompositionConverter(ScopedVector<AudioConverter> converters) - : converters_(converters.Pass()) { + : converters_(std::move(converters)) { RTC_CHECK_GE(converters_.size(), 2u); // We need an intermediate buffer after every converter. for (auto it = converters_.begin(); it != converters_.end() - 1; ++it) @@ -135,9 +136,9 @@ class CompositionConverter : public AudioConverter { ScopedVector<ChannelBuffer<float>> buffers_; }; -rtc::scoped_ptr<AudioConverter> AudioConverter::Create(int src_channels, +rtc::scoped_ptr<AudioConverter> AudioConverter::Create(size_t src_channels, size_t src_frames, - int dst_channels, + size_t dst_channels, size_t dst_frames) { rtc::scoped_ptr<AudioConverter> sp; if (src_channels > dst_channels) { @@ -147,7 +148,7 @@ rtc::scoped_ptr<AudioConverter> AudioConverter::Create(int src_channels, dst_channels, src_frames)); converters.push_back(new ResampleConverter(dst_channels, src_frames, dst_channels, dst_frames)); - sp.reset(new CompositionConverter(converters.Pass())); + sp.reset(new CompositionConverter(std::move(converters))); } else { sp.reset(new DownmixConverter(src_channels, src_frames, dst_channels, dst_frames)); @@ -159,7 +160,7 @@ rtc::scoped_ptr<AudioConverter> AudioConverter::Create(int src_channels, src_channels, dst_frames)); converters.push_back(new UpmixConverter(src_channels, dst_frames, dst_channels, dst_frames)); - sp.reset(new CompositionConverter(converters.Pass())); + sp.reset(new CompositionConverter(std::move(converters))); } else { sp.reset(new UpmixConverter(src_channels, src_frames, dst_channels, dst_frames)); @@ -172,7 +173,7 @@ rtc::scoped_ptr<AudioConverter> AudioConverter::Create(int src_channels, dst_frames)); } - return sp.Pass(); + return sp; } // For CompositionConverter. @@ -182,8 +183,8 @@ AudioConverter::AudioConverter() dst_channels_(0), dst_frames_(0) {} -AudioConverter::AudioConverter(int src_channels, size_t src_frames, - int dst_channels, size_t dst_frames) +AudioConverter::AudioConverter(size_t src_channels, size_t src_frames, + size_t dst_channels, size_t dst_frames) : src_channels_(src_channels), src_frames_(src_frames), dst_channels_(dst_channels), diff --git a/webrtc/common_audio/audio_converter.h b/webrtc/common_audio/audio_converter.h index 7d1513bc02..c5f08c1d9b 100644 --- a/webrtc/common_audio/audio_converter.h +++ b/webrtc/common_audio/audio_converter.h @@ -26,9 +26,9 @@ class AudioConverter { public: // Returns a new AudioConverter, which will use the supplied format for its // lifetime. Caller is responsible for the memory. - static rtc::scoped_ptr<AudioConverter> Create(int src_channels, + static rtc::scoped_ptr<AudioConverter> Create(size_t src_channels, size_t src_frames, - int dst_channels, + size_t dst_channels, size_t dst_frames); virtual ~AudioConverter() {}; @@ -39,23 +39,23 @@ class AudioConverter { virtual void Convert(const float* const* src, size_t src_size, float* const* dst, size_t dst_capacity) = 0; - int src_channels() const { return src_channels_; } + size_t src_channels() const { return src_channels_; } size_t src_frames() const { return src_frames_; } - int dst_channels() const { return dst_channels_; } + size_t dst_channels() const { return dst_channels_; } size_t dst_frames() const { return dst_frames_; } protected: AudioConverter(); - AudioConverter(int src_channels, size_t src_frames, int dst_channels, + AudioConverter(size_t src_channels, size_t src_frames, size_t dst_channels, size_t dst_frames); // Helper to RTC_CHECK that inputs are correctly sized. void CheckSizes(size_t src_size, size_t dst_capacity) const; private: - const int src_channels_; + const size_t src_channels_; const size_t src_frames_; - const int dst_channels_; + const size_t dst_channels_; const size_t dst_frames_; RTC_DISALLOW_COPY_AND_ASSIGN(AudioConverter); diff --git a/webrtc/common_audio/audio_converter_unittest.cc b/webrtc/common_audio/audio_converter_unittest.cc index c85b96e285..dace0bdccf 100644 --- a/webrtc/common_audio/audio_converter_unittest.cc +++ b/webrtc/common_audio/audio_converter_unittest.cc @@ -13,6 +13,7 @@ #include <vector> #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/arraysize.h" #include "webrtc/base/format_macros.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/common_audio/audio_converter.h" @@ -24,11 +25,11 @@ namespace webrtc { typedef rtc::scoped_ptr<ChannelBuffer<float>> ScopedBuffer; // Sets the signal value to increase by |data| with every sample. -ScopedBuffer CreateBuffer(const std::vector<float>& data, int frames) { - const int num_channels = static_cast<int>(data.size()); +ScopedBuffer CreateBuffer(const std::vector<float>& data, size_t frames) { + const size_t num_channels = data.size(); ScopedBuffer sb(new ChannelBuffer<float>(frames, num_channels)); - for (int i = 0; i < num_channels; ++i) - for (int j = 0; j < frames; ++j) + for (size_t i = 0; i < num_channels; ++i) + for (size_t j = 0; j < frames; ++j) sb->channels()[i][j] = data[i] * j; return sb; } @@ -56,7 +57,7 @@ float ComputeSNR(const ChannelBuffer<float>& ref, float mse = 0; float variance = 0; float mean = 0; - for (int i = 0; i < ref.num_channels(); ++i) { + for (size_t i = 0; i < ref.num_channels(); ++i) { for (size_t j = 0; j < ref.num_frames() - delay; ++j) { float error = ref.channels()[i][j] - test.channels()[i][j + delay]; mse += error * error; @@ -85,9 +86,9 @@ float ComputeSNR(const ChannelBuffer<float>& ref, // Sets the source to a linearly increasing signal for which we can easily // generate a reference. Runs the AudioConverter and ensures the output has // sufficiently high SNR relative to the reference. -void RunAudioConverterTest(int src_channels, +void RunAudioConverterTest(size_t src_channels, int src_sample_rate_hz, - int dst_channels, + size_t dst_channels, int dst_sample_rate_hz) { const float kSrcLeft = 0.0002f; const float kSrcRight = 0.0001f; @@ -96,8 +97,8 @@ void RunAudioConverterTest(int src_channels, const float dst_left = resampling_factor * kSrcLeft; const float dst_right = resampling_factor * kSrcRight; const float dst_mono = (dst_left + dst_right) / 2; - const int src_frames = src_sample_rate_hz / 100; - const int dst_frames = dst_sample_rate_hz / 100; + const size_t src_frames = static_cast<size_t>(src_sample_rate_hz / 100); + const size_t dst_frames = static_cast<size_t>(dst_sample_rate_hz / 100); std::vector<float> src_data(1, kSrcLeft); if (src_channels == 2) @@ -127,8 +128,9 @@ void RunAudioConverterTest(int src_channels, static_cast<size_t>( PushSincResampler::AlgorithmicDelaySeconds(src_sample_rate_hz) * dst_sample_rate_hz); - printf("(%d, %d Hz) -> (%d, %d Hz) ", // SNR reported on the same line later. - src_channels, src_sample_rate_hz, dst_channels, dst_sample_rate_hz); + // SNR reported on the same line later. + printf("(%" PRIuS ", %d Hz) -> (%" PRIuS ", %d Hz) ", + src_channels, src_sample_rate_hz, dst_channels, dst_sample_rate_hz); rtc::scoped_ptr<AudioConverter> converter = AudioConverter::Create( src_channels, src_frames, dst_channels, dst_frames); @@ -141,13 +143,13 @@ void RunAudioConverterTest(int src_channels, TEST(AudioConverterTest, ConversionsPassSNRThreshold) { const int kSampleRates[] = {8000, 16000, 32000, 44100, 48000}; - const int kSampleRatesSize = sizeof(kSampleRates) / sizeof(*kSampleRates); - const int kChannels[] = {1, 2}; - const int kChannelsSize = sizeof(kChannels) / sizeof(*kChannels); - for (int src_rate = 0; src_rate < kSampleRatesSize; ++src_rate) { - for (int dst_rate = 0; dst_rate < kSampleRatesSize; ++dst_rate) { - for (int src_channel = 0; src_channel < kChannelsSize; ++src_channel) { - for (int dst_channel = 0; dst_channel < kChannelsSize; ++dst_channel) { + const size_t kChannels[] = {1, 2}; + for (size_t src_rate = 0; src_rate < arraysize(kSampleRates); ++src_rate) { + for (size_t dst_rate = 0; dst_rate < arraysize(kSampleRates); ++dst_rate) { + for (size_t src_channel = 0; src_channel < arraysize(kChannels); + ++src_channel) { + for (size_t dst_channel = 0; dst_channel < arraysize(kChannels); + ++dst_channel) { RunAudioConverterTest(kChannels[src_channel], kSampleRates[src_rate], kChannels[dst_channel], kSampleRates[dst_rate]); } diff --git a/webrtc/common_audio/blocker.cc b/webrtc/common_audio/blocker.cc index 0133550beb..13432f2e7a 100644 --- a/webrtc/common_audio/blocker.cc +++ b/webrtc/common_audio/blocker.cc @@ -22,10 +22,10 @@ void AddFrames(const float* const* a, const float* const* b, int b_start_index, size_t num_frames, - int num_channels, + size_t num_channels, float* const* result, size_t result_start_index) { - for (int i = 0; i < num_channels; ++i) { + for (size_t i = 0; i < num_channels; ++i) { for (size_t j = 0; j < num_frames; ++j) { result[i][j + result_start_index] = a[i][j + a_start_index] + b[i][j + b_start_index]; @@ -37,10 +37,10 @@ void AddFrames(const float* const* a, void CopyFrames(const float* const* src, size_t src_start_index, size_t num_frames, - int num_channels, + size_t num_channels, float* const* dst, size_t dst_start_index) { - for (int i = 0; i < num_channels; ++i) { + for (size_t i = 0; i < num_channels; ++i) { memcpy(&dst[i][dst_start_index], &src[i][src_start_index], num_frames * sizeof(dst[i][dst_start_index])); @@ -51,10 +51,10 @@ void CopyFrames(const float* const* src, void MoveFrames(const float* const* src, size_t src_start_index, size_t num_frames, - int num_channels, + size_t num_channels, float* const* dst, size_t dst_start_index) { - for (int i = 0; i < num_channels; ++i) { + for (size_t i = 0; i < num_channels; ++i) { memmove(&dst[i][dst_start_index], &src[i][src_start_index], num_frames * sizeof(dst[i][dst_start_index])); @@ -64,8 +64,8 @@ void MoveFrames(const float* const* src, void ZeroOut(float* const* buffer, size_t starting_idx, size_t num_frames, - int num_channels) { - for (int i = 0; i < num_channels; ++i) { + size_t num_channels) { + for (size_t i = 0; i < num_channels; ++i) { memset(&buffer[i][starting_idx], 0, num_frames * sizeof(buffer[i][starting_idx])); } @@ -75,9 +75,9 @@ void ZeroOut(float* const* buffer, // stored in |frames|. void ApplyWindow(const float* window, size_t num_frames, - int num_channels, + size_t num_channels, float* const* frames) { - for (int i = 0; i < num_channels; ++i) { + for (size_t i = 0; i < num_channels; ++i) { for (size_t j = 0; j < num_frames; ++j) { frames[i][j] = frames[i][j] * window[j]; } @@ -100,8 +100,8 @@ namespace webrtc { Blocker::Blocker(size_t chunk_size, size_t block_size, - int num_input_channels, - int num_output_channels, + size_t num_input_channels, + size_t num_output_channels, const float* window, size_t shift_amount, BlockerCallback* callback) @@ -166,8 +166,8 @@ Blocker::Blocker(size_t chunk_size, // TODO(claguna): Look at using ring buffers to eliminate some copies. void Blocker::ProcessChunk(const float* const* input, size_t chunk_size, - int num_input_channels, - int num_output_channels, + size_t num_input_channels, + size_t num_output_channels, float* const* output) { RTC_CHECK_EQ(chunk_size, chunk_size_); RTC_CHECK_EQ(num_input_channels, num_input_channels_); diff --git a/webrtc/common_audio/blocker.h b/webrtc/common_audio/blocker.h index 025638ae8c..3a67c134d0 100644 --- a/webrtc/common_audio/blocker.h +++ b/webrtc/common_audio/blocker.h @@ -26,8 +26,8 @@ class BlockerCallback { virtual void ProcessBlock(const float* const* input, size_t num_frames, - int num_input_channels, - int num_output_channels, + size_t num_input_channels, + size_t num_output_channels, float* const* output) = 0; }; @@ -65,23 +65,23 @@ class Blocker { public: Blocker(size_t chunk_size, size_t block_size, - int num_input_channels, - int num_output_channels, + size_t num_input_channels, + size_t num_output_channels, const float* window, size_t shift_amount, BlockerCallback* callback); void ProcessChunk(const float* const* input, size_t chunk_size, - int num_input_channels, - int num_output_channels, + size_t num_input_channels, + size_t num_output_channels, float* const* output); private: const size_t chunk_size_; const size_t block_size_; - const int num_input_channels_; - const int num_output_channels_; + const size_t num_input_channels_; + const size_t num_output_channels_; // The number of frames of delay to add at the beginning of the first chunk. const size_t initial_delay_; diff --git a/webrtc/common_audio/blocker_unittest.cc b/webrtc/common_audio/blocker_unittest.cc index 397e269239..a5a7b56282 100644 --- a/webrtc/common_audio/blocker_unittest.cc +++ b/webrtc/common_audio/blocker_unittest.cc @@ -11,6 +11,7 @@ #include "webrtc/common_audio/blocker.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/arraysize.h" namespace { @@ -19,10 +20,10 @@ class PlusThreeBlockerCallback : public webrtc::BlockerCallback { public: void ProcessBlock(const float* const* input, size_t num_frames, - int num_input_channels, - int num_output_channels, + size_t num_input_channels, + size_t num_output_channels, float* const* output) override { - for (int i = 0; i < num_output_channels; ++i) { + for (size_t i = 0; i < num_output_channels; ++i) { for (size_t j = 0; j < num_frames; ++j) { output[i][j] = input[i][j] + 3; } @@ -35,10 +36,10 @@ class CopyBlockerCallback : public webrtc::BlockerCallback { public: void ProcessBlock(const float* const* input, size_t num_frames, - int num_input_channels, - int num_output_channels, + size_t num_input_channels, + size_t num_output_channels, float* const* output) override { - for (int i = 0; i < num_output_channels; ++i) { + for (size_t i = 0; i < num_output_channels; ++i) { for (size_t j = 0; j < num_frames; ++j) { output[i][j] = input[i][j]; } @@ -56,16 +57,16 @@ namespace webrtc { class BlockerTest : public ::testing::Test { protected: void RunTest(Blocker* blocker, - int chunk_size, - int num_frames, + size_t chunk_size, + size_t num_frames, const float* const* input, float* const* input_chunk, float* const* output, float* const* output_chunk, - int num_input_channels, - int num_output_channels) { - int start = 0; - int end = chunk_size - 1; + size_t num_input_channels, + size_t num_output_channels) { + size_t start = 0; + size_t end = chunk_size - 1; while (end < num_frames) { CopyTo(input_chunk, 0, start, num_input_channels, chunk_size, input); blocker->ProcessChunk(input_chunk, @@ -75,28 +76,28 @@ class BlockerTest : public ::testing::Test { output_chunk); CopyTo(output, start, 0, num_output_channels, chunk_size, output_chunk); - start = start + chunk_size; - end = end + chunk_size; + start += chunk_size; + end += chunk_size; } } void ValidateSignalEquality(const float* const* expected, const float* const* actual, - int num_channels, - int num_frames) { - for (int i = 0; i < num_channels; ++i) { - for (int j = 0; j < num_frames; ++j) { + size_t num_channels, + size_t num_frames) { + for (size_t i = 0; i < num_channels; ++i) { + for (size_t j = 0; j < num_frames; ++j) { EXPECT_FLOAT_EQ(expected[i][j], actual[i][j]); } } } void ValidateInitialDelay(const float* const* output, - int num_channels, - int num_frames, - int initial_delay) { - for (int i = 0; i < num_channels; ++i) { - for (int j = 0; j < num_frames; ++j) { + size_t num_channels, + size_t num_frames, + size_t initial_delay) { + for (size_t i = 0; i < num_channels; ++i) { + for (size_t j = 0; j < num_frames; ++j) { if (j < initial_delay) { EXPECT_FLOAT_EQ(output[i][j], 0.f); } else { @@ -107,12 +108,12 @@ class BlockerTest : public ::testing::Test { } static void CopyTo(float* const* dst, - int start_index_dst, - int start_index_src, - int num_channels, - int num_frames, + size_t start_index_dst, + size_t start_index_src, + size_t num_channels, + size_t num_frames, const float* const* src) { - for (int i = 0; i < num_channels; ++i) { + for (size_t i = 0; i < num_channels; ++i) { memcpy(&dst[i][start_index_dst], &src[i][start_index_src], num_frames * sizeof(float)); @@ -121,12 +122,12 @@ class BlockerTest : public ::testing::Test { }; TEST_F(BlockerTest, TestBlockerMutuallyPrimeChunkandBlockSize) { - const int kNumInputChannels = 3; - const int kNumOutputChannels = 2; - const int kNumFrames = 10; - const int kBlockSize = 4; - const int kChunkSize = 5; - const int kShiftAmount = 2; + const size_t kNumInputChannels = 3; + const size_t kNumOutputChannels = 2; + const size_t kNumFrames = 10; + const size_t kBlockSize = 4; + const size_t kChunkSize = 5; + const size_t kShiftAmount = 2; const float kInput[kNumInputChannels][kNumFrames] = { {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, @@ -174,12 +175,12 @@ TEST_F(BlockerTest, TestBlockerMutuallyPrimeChunkandBlockSize) { } TEST_F(BlockerTest, TestBlockerMutuallyPrimeShiftAndBlockSize) { - const int kNumInputChannels = 3; - const int kNumOutputChannels = 2; - const int kNumFrames = 12; - const int kBlockSize = 4; - const int kChunkSize = 6; - const int kShiftAmount = 3; + const size_t kNumInputChannels = 3; + const size_t kNumOutputChannels = 2; + const size_t kNumFrames = 12; + const size_t kBlockSize = 4; + const size_t kChunkSize = 6; + const size_t kShiftAmount = 3; const float kInput[kNumInputChannels][kNumFrames] = { {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, @@ -227,12 +228,12 @@ TEST_F(BlockerTest, TestBlockerMutuallyPrimeShiftAndBlockSize) { } TEST_F(BlockerTest, TestBlockerNoOverlap) { - const int kNumInputChannels = 3; - const int kNumOutputChannels = 2; - const int kNumFrames = 12; - const int kBlockSize = 4; - const int kChunkSize = 4; - const int kShiftAmount = 4; + const size_t kNumInputChannels = 3; + const size_t kNumOutputChannels = 2; + const size_t kNumFrames = 12; + const size_t kBlockSize = 4; + const size_t kChunkSize = 4; + const size_t kShiftAmount = 4; const float kInput[kNumInputChannels][kNumFrames] = { {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, @@ -280,21 +281,21 @@ TEST_F(BlockerTest, TestBlockerNoOverlap) { } TEST_F(BlockerTest, InitialDelaysAreMinimum) { - const int kNumInputChannels = 3; - const int kNumOutputChannels = 2; - const int kNumFrames = 1280; - const int kChunkSize[] = + const size_t kNumInputChannels = 3; + const size_t kNumOutputChannels = 2; + const size_t kNumFrames = 1280; + const size_t kChunkSize[] = {80, 80, 80, 80, 80, 80, 160, 160, 160, 160, 160, 160}; - const int kBlockSize[] = + const size_t kBlockSize[] = {64, 64, 64, 128, 128, 128, 128, 128, 128, 256, 256, 256}; - const int kShiftAmount[] = + const size_t kShiftAmount[] = {16, 32, 64, 32, 64, 128, 32, 64, 128, 64, 128, 256}; - const int kInitialDelay[] = + const size_t kInitialDelay[] = {48, 48, 48, 112, 112, 112, 96, 96, 96, 224, 224, 224}; float input[kNumInputChannels][kNumFrames]; - for (int i = 0; i < kNumInputChannels; ++i) { - for (int j = 0; j < kNumFrames; ++j) { + for (size_t i = 0; i < kNumInputChannels; ++i) { + for (size_t j = 0; j < kNumFrames; ++j) { input[i][j] = i + 1; } } @@ -305,9 +306,9 @@ TEST_F(BlockerTest, InitialDelaysAreMinimum) { CopyBlockerCallback callback; - for (size_t i = 0; i < (sizeof(kChunkSize) / sizeof(*kChunkSize)); ++i) { + for (size_t i = 0; i < arraysize(kChunkSize); ++i) { rtc::scoped_ptr<float[]> window(new float[kBlockSize[i]]); - for (int j = 0; j < kBlockSize[i]; ++j) { + for (size_t j = 0; j < kBlockSize[i]; ++j) { window[j] = 1.f; } diff --git a/webrtc/common_audio/channel_buffer.cc b/webrtc/common_audio/channel_buffer.cc index d3dc7c04f7..44520c6100 100644 --- a/webrtc/common_audio/channel_buffer.cc +++ b/webrtc/common_audio/channel_buffer.cc @@ -13,7 +13,7 @@ namespace webrtc { IFChannelBuffer::IFChannelBuffer(size_t num_frames, - int num_channels, + size_t num_channels, size_t num_bands) : ivalid_(true), ibuf_(num_frames, num_channels, num_bands), @@ -47,7 +47,7 @@ void IFChannelBuffer::RefreshF() const { assert(ivalid_); const int16_t* const* int_channels = ibuf_.channels(); float* const* float_channels = fbuf_.channels(); - for (int i = 0; i < ibuf_.num_channels(); ++i) { + for (size_t i = 0; i < ibuf_.num_channels(); ++i) { for (size_t j = 0; j < ibuf_.num_frames(); ++j) { float_channels[i][j] = int_channels[i][j]; } @@ -61,7 +61,7 @@ void IFChannelBuffer::RefreshI() const { assert(fvalid_); int16_t* const* int_channels = ibuf_.channels(); const float* const* float_channels = fbuf_.channels(); - for (int i = 0; i < ibuf_.num_channels(); ++i) { + for (size_t i = 0; i < ibuf_.num_channels(); ++i) { FloatS16ToS16(float_channels[i], ibuf_.num_frames(), int_channels[i]); diff --git a/webrtc/common_audio/channel_buffer.h b/webrtc/common_audio/channel_buffer.h index 6050090876..d9069163fa 100644 --- a/webrtc/common_audio/channel_buffer.h +++ b/webrtc/common_audio/channel_buffer.h @@ -40,7 +40,7 @@ template <typename T> class ChannelBuffer { public: ChannelBuffer(size_t num_frames, - int num_channels, + size_t num_channels, size_t num_bands = 1) : data_(new T[num_frames * num_channels]()), channels_(new T*[num_channels * num_bands]), @@ -49,7 +49,7 @@ class ChannelBuffer { num_frames_per_band_(num_frames / num_bands), num_channels_(num_channels), num_bands_(num_bands) { - for (int i = 0; i < num_channels_; ++i) { + for (size_t i = 0; i < num_channels_; ++i) { for (size_t j = 0; j < num_bands_; ++j) { channels_[j * num_channels_ + i] = &data_[i * num_frames_ + j * num_frames_per_band_]; @@ -90,12 +90,12 @@ class ChannelBuffer { // 0 <= channel < |num_channels_| // 0 <= band < |num_bands_| // 0 <= sample < |num_frames_per_band_| - const T* const* bands(int channel) const { + const T* const* bands(size_t channel) const { RTC_DCHECK_LT(channel, num_channels_); - RTC_DCHECK_GE(channel, 0); + RTC_DCHECK_GE(channel, 0u); return &bands_[channel * num_bands_]; } - T* const* bands(int channel) { + T* const* bands(size_t channel) { const ChannelBuffer<T>* t = this; return const_cast<T* const*>(t->bands(channel)); } @@ -104,7 +104,7 @@ class ChannelBuffer { // Returns |slice| for convenience. const T* const* Slice(T** slice, size_t start_frame) const { RTC_DCHECK_LT(start_frame, num_frames_); - for (int i = 0; i < num_channels_; ++i) + for (size_t i = 0; i < num_channels_; ++i) slice[i] = &channels_[i][start_frame]; return slice; } @@ -115,7 +115,7 @@ class ChannelBuffer { size_t num_frames() const { return num_frames_; } size_t num_frames_per_band() const { return num_frames_per_band_; } - int num_channels() const { return num_channels_; } + size_t num_channels() const { return num_channels_; } size_t num_bands() const { return num_bands_; } size_t size() const {return num_frames_ * num_channels_; } @@ -130,7 +130,7 @@ class ChannelBuffer { rtc::scoped_ptr<T* []> bands_; const size_t num_frames_; const size_t num_frames_per_band_; - const int num_channels_; + const size_t num_channels_; const size_t num_bands_; }; @@ -142,7 +142,7 @@ class ChannelBuffer { // fbuf() until the next call to any of the other functions. class IFChannelBuffer { public: - IFChannelBuffer(size_t num_frames, int num_channels, size_t num_bands = 1); + IFChannelBuffer(size_t num_frames, size_t num_channels, size_t num_bands = 1); ChannelBuffer<int16_t>* ibuf(); ChannelBuffer<float>* fbuf(); @@ -151,7 +151,7 @@ class IFChannelBuffer { size_t num_frames() const { return ibuf_.num_frames(); } size_t num_frames_per_band() const { return ibuf_.num_frames_per_band(); } - int num_channels() const { return ibuf_.num_channels(); } + size_t num_channels() const { return ibuf_.num_channels(); } size_t num_bands() const { return ibuf_.num_bands(); } private: diff --git a/webrtc/common_audio/common_audio.gyp b/webrtc/common_audio/common_audio.gyp index 884a8afcf8..f0a6fc9473 100644 --- a/webrtc/common_audio/common_audio.gyp +++ b/webrtc/common_audio/common_audio.gyp @@ -101,6 +101,7 @@ 'signal_processing/vector_scaling_operations.c', 'sparse_fir_filter.cc', 'sparse_fir_filter.h', + 'swap_queue.h', 'vad/include/vad.h', 'vad/include/webrtc_vad.h', 'vad/vad.cc', @@ -227,9 +228,10 @@ }, ], # targets }], - ['include_tests==1', { + ['include_tests==1 and OS!="ios"', { 'targets' : [ { + # Does not compile on iOS: webrtc:4755. 'target_name': 'common_audio_unittests', 'type': '<(gtest_target_type)', 'dependencies': [ @@ -256,6 +258,7 @@ 'signal_processing/real_fft_unittest.cc', 'signal_processing/signal_processing_unittest.cc', 'sparse_fir_filter_unittest.cc', + 'swap_queue_unittest.cc', 'vad/vad_core_unittest.cc', 'vad/vad_filterbank_unittest.cc', 'vad/vad_gmm_unittest.cc', diff --git a/webrtc/common_audio/include/audio_util.h b/webrtc/common_audio/include/audio_util.h index 2c0028ce90..55dfc06a31 100644 --- a/webrtc/common_audio/include/audio_util.h +++ b/webrtc/common_audio/include/audio_util.h @@ -87,11 +87,11 @@ void CopyAudioIfNeeded(const T* const* src, template <typename T> void Deinterleave(const T* interleaved, size_t samples_per_channel, - int num_channels, + size_t num_channels, T* const* deinterleaved) { - for (int i = 0; i < num_channels; ++i) { + for (size_t i = 0; i < num_channels; ++i) { T* channel = deinterleaved[i]; - int interleaved_idx = i; + size_t interleaved_idx = i; for (size_t j = 0; j < samples_per_channel; ++j) { channel[j] = interleaved[interleaved_idx]; interleaved_idx += num_channels; @@ -105,11 +105,11 @@ void Deinterleave(const T* interleaved, template <typename T> void Interleave(const T* const* deinterleaved, size_t samples_per_channel, - int num_channels, + size_t num_channels, T* interleaved) { - for (int i = 0; i < num_channels; ++i) { + for (size_t i = 0; i < num_channels; ++i) { const T* channel = deinterleaved[i]; - int interleaved_idx = i; + size_t interleaved_idx = i; for (size_t j = 0; j < samples_per_channel; ++j) { interleaved[interleaved_idx] = channel[j]; interleaved_idx += num_channels; diff --git a/webrtc/common_audio/lapped_transform.cc b/webrtc/common_audio/lapped_transform.cc index c01f1d9d8c..5ab1db1b25 100644 --- a/webrtc/common_audio/lapped_transform.cc +++ b/webrtc/common_audio/lapped_transform.cc @@ -21,14 +21,14 @@ namespace webrtc { void LappedTransform::BlockThunk::ProcessBlock(const float* const* input, size_t num_frames, - int num_input_channels, - int num_output_channels, + size_t num_input_channels, + size_t num_output_channels, float* const* output) { RTC_CHECK_EQ(num_input_channels, parent_->num_in_channels_); RTC_CHECK_EQ(num_output_channels, parent_->num_out_channels_); RTC_CHECK_EQ(parent_->block_length_, num_frames); - for (int i = 0; i < num_input_channels; ++i) { + for (size_t i = 0; i < num_input_channels; ++i) { memcpy(parent_->real_buf_.Row(i), input[i], num_frames * sizeof(*input[0])); parent_->fft_->Forward(parent_->real_buf_.Row(i), @@ -44,7 +44,7 @@ void LappedTransform::BlockThunk::ProcessBlock(const float* const* input, num_output_channels, parent_->cplx_post_.Array()); - for (int i = 0; i < num_output_channels; ++i) { + for (size_t i = 0; i < num_output_channels; ++i) { parent_->fft_->Inverse(parent_->cplx_post_.Row(i), parent_->real_buf_.Row(i)); memcpy(output[i], parent_->real_buf_.Row(i), @@ -52,8 +52,8 @@ void LappedTransform::BlockThunk::ProcessBlock(const float* const* input, } } -LappedTransform::LappedTransform(int num_in_channels, - int num_out_channels, +LappedTransform::LappedTransform(size_t num_in_channels, + size_t num_out_channels, size_t chunk_length, const float* window, size_t block_length, diff --git a/webrtc/common_audio/lapped_transform.h b/webrtc/common_audio/lapped_transform.h index 21e10e3911..1373ca10e1 100644 --- a/webrtc/common_audio/lapped_transform.h +++ b/webrtc/common_audio/lapped_transform.h @@ -35,8 +35,8 @@ class LappedTransform { virtual ~Callback() {} virtual void ProcessAudioBlock(const std::complex<float>* const* in_block, - int num_in_channels, size_t frames, - int num_out_channels, + size_t num_in_channels, size_t frames, + size_t num_out_channels, std::complex<float>* const* out_block) = 0; }; @@ -46,8 +46,8 @@ class LappedTransform { // |block_length| defines the length of a block, in samples. // |shift_amount| is in samples. |callback| is the caller-owned audio // processing function called for each block of the input chunk. - LappedTransform(int num_in_channels, - int num_out_channels, + LappedTransform(size_t num_in_channels, + size_t num_out_channels, size_t chunk_length, const float* window, size_t block_length, @@ -75,7 +75,7 @@ class LappedTransform { // in_chunk. // // Returns the same num_in_channels passed to the LappedTransform constructor. - int num_in_channels() const { return num_in_channels_; } + size_t num_in_channels() const { return num_in_channels_; } // Get the number of output channels. // @@ -84,7 +84,7 @@ class LappedTransform { // // Returns the same num_out_channels passed to the LappedTransform // constructor. - int num_out_channels() const { return num_out_channels_; } + size_t num_out_channels() const { return num_out_channels_; } private: // Internal middleware callback, given to the blocker. Transforms each block @@ -93,16 +93,18 @@ class LappedTransform { public: explicit BlockThunk(LappedTransform* parent) : parent_(parent) {} - virtual void ProcessBlock(const float* const* input, size_t num_frames, - int num_input_channels, int num_output_channels, + virtual void ProcessBlock(const float* const* input, + size_t num_frames, + size_t num_input_channels, + size_t num_output_channels, float* const* output); private: LappedTransform* const parent_; } blocker_callback_; - const int num_in_channels_; - const int num_out_channels_; + const size_t num_in_channels_; + const size_t num_out_channels_; const size_t block_length_; const size_t chunk_length_; diff --git a/webrtc/common_audio/lapped_transform_unittest.cc b/webrtc/common_audio/lapped_transform_unittest.cc index f688cc240a..a78488e326 100644 --- a/webrtc/common_audio/lapped_transform_unittest.cc +++ b/webrtc/common_audio/lapped_transform_unittest.cc @@ -25,23 +25,23 @@ class NoopCallback : public webrtc::LappedTransform::Callback { NoopCallback() : block_num_(0) {} virtual void ProcessAudioBlock(const complex<float>* const* in_block, - int in_channels, + size_t in_channels, size_t frames, - int out_channels, + size_t out_channels, complex<float>* const* out_block) { RTC_CHECK_EQ(in_channels, out_channels); - for (int i = 0; i < out_channels; ++i) { + for (size_t i = 0; i < out_channels; ++i) { memcpy(out_block[i], in_block[i], sizeof(**in_block) * frames); } ++block_num_; } - int block_num() { + size_t block_num() { return block_num_; } private: - int block_num_; + size_t block_num_; }; class FftCheckerCallback : public webrtc::LappedTransform::Callback { @@ -49,9 +49,9 @@ class FftCheckerCallback : public webrtc::LappedTransform::Callback { FftCheckerCallback() : block_num_(0) {} virtual void ProcessAudioBlock(const complex<float>* const* in_block, - int in_channels, + size_t in_channels, size_t frames, - int out_channels, + size_t out_channels, complex<float>* const* out_block) { RTC_CHECK_EQ(in_channels, out_channels); @@ -69,12 +69,12 @@ class FftCheckerCallback : public webrtc::LappedTransform::Callback { } } - int block_num() { + size_t block_num() { return block_num_; } private: - int block_num_; + size_t block_num_; }; void SetFloatArray(float value, int rows, int cols, float* const* array) { @@ -90,10 +90,10 @@ void SetFloatArray(float value, int rows, int cols, float* const* array) { namespace webrtc { TEST(LappedTransformTest, Windowless) { - const int kChannels = 3; - const int kChunkLength = 512; - const int kBlockLength = 64; - const int kShiftAmount = 64; + const size_t kChannels = 3; + const size_t kChunkLength = 512; + const size_t kBlockLength = 64; + const size_t kShiftAmount = 64; NoopCallback noop; // Rectangular window. @@ -118,8 +118,8 @@ TEST(LappedTransformTest, Windowless) { trans.ProcessChunk(in_chunk, out_chunk); - for (int i = 0; i < kChannels; ++i) { - for (int j = 0; j < kChunkLength; ++j) { + for (size_t i = 0; i < kChannels; ++i) { + for (size_t j = 0; j < kChunkLength; ++j) { ASSERT_NEAR(out_chunk[i][j], 2.0f, 1e-5f); } } @@ -128,9 +128,9 @@ TEST(LappedTransformTest, Windowless) { } TEST(LappedTransformTest, IdentityProcessor) { - const int kChunkLength = 512; - const int kBlockLength = 64; - const int kShiftAmount = 32; + const size_t kChunkLength = 512; + const size_t kBlockLength = 64; + const size_t kShiftAmount = 32; NoopCallback noop; // Identity window for |overlap = block_size / 2|. @@ -149,7 +149,7 @@ TEST(LappedTransformTest, IdentityProcessor) { trans.ProcessChunk(&in_chunk, &out_chunk); - for (int i = 0; i < kChunkLength; ++i) { + for (size_t i = 0; i < kChunkLength; ++i) { ASSERT_NEAR(out_chunk[i], (i < kBlockLength - kShiftAmount) ? 0.0f : 2.0f, 1e-5f); @@ -159,8 +159,8 @@ TEST(LappedTransformTest, IdentityProcessor) { } TEST(LappedTransformTest, Callbacks) { - const int kChunkLength = 512; - const int kBlockLength = 64; + const size_t kChunkLength = 512; + const size_t kBlockLength = 64; FftCheckerCallback call; // Rectangular window. @@ -183,7 +183,7 @@ TEST(LappedTransformTest, Callbacks) { } TEST(LappedTransformTest, chunk_length) { - const int kBlockLength = 64; + const size_t kBlockLength = 64; FftCheckerCallback call; const float window[kBlockLength] = {}; diff --git a/webrtc/common_audio/real_fourier.cc b/webrtc/common_audio/real_fourier.cc index fef3c60c4c..55ec49cba2 100644 --- a/webrtc/common_audio/real_fourier.cc +++ b/webrtc/common_audio/real_fourier.cc @@ -19,7 +19,7 @@ namespace webrtc { using std::complex; -const int RealFourier::kFftBufferAlignment = 32; +const size_t RealFourier::kFftBufferAlignment = 32; rtc::scoped_ptr<RealFourier> RealFourier::Create(int fft_order) { #if defined(RTC_USE_OPENMAX_DL) diff --git a/webrtc/common_audio/real_fourier.h b/webrtc/common_audio/real_fourier.h index ce3bbff679..0be56a58b0 100644 --- a/webrtc/common_audio/real_fourier.h +++ b/webrtc/common_audio/real_fourier.h @@ -30,7 +30,7 @@ class RealFourier { fft_cplx_scoper; // The alignment required for all input and output buffers, in bytes. - static const int kFftBufferAlignment; + static const size_t kFftBufferAlignment; // Construct a wrapper instance for the given input order, which must be // between 1 and kMaxFftOrder, inclusively. diff --git a/webrtc/common_audio/real_fourier_unittest.cc b/webrtc/common_audio/real_fourier_unittest.cc index 5c8542138b..eb5880ee8a 100644 --- a/webrtc/common_audio/real_fourier_unittest.cc +++ b/webrtc/common_audio/real_fourier_unittest.cc @@ -26,15 +26,15 @@ TEST(RealFourierStaticsTest, AllocatorAlignment) { RealFourier::fft_real_scoper real; real = RealFourier::AllocRealBuffer(3); ASSERT_TRUE(real.get() != nullptr); - int64_t ptr_value = reinterpret_cast<int64_t>(real.get()); - EXPECT_EQ(0, ptr_value % RealFourier::kFftBufferAlignment); + uintptr_t ptr_value = reinterpret_cast<uintptr_t>(real.get()); + EXPECT_EQ(0u, ptr_value % RealFourier::kFftBufferAlignment); } { RealFourier::fft_cplx_scoper cplx; cplx = RealFourier::AllocCplxBuffer(3); ASSERT_TRUE(cplx.get() != nullptr); - int64_t ptr_value = reinterpret_cast<int64_t>(cplx.get()); - EXPECT_EQ(0, ptr_value % RealFourier::kFftBufferAlignment); + uintptr_t ptr_value = reinterpret_cast<uintptr_t>(cplx.get()); + EXPECT_EQ(0u, ptr_value % RealFourier::kFftBufferAlignment); } } diff --git a/webrtc/common_audio/resampler/include/push_resampler.h b/webrtc/common_audio/resampler/include/push_resampler.h index b5c0003615..eeda790497 100644 --- a/webrtc/common_audio/resampler/include/push_resampler.h +++ b/webrtc/common_audio/resampler/include/push_resampler.h @@ -29,7 +29,7 @@ class PushResampler { // Must be called whenever the parameters change. Free to be called at any // time as it is a no-op if parameters have not changed since the last call. int InitializeIfNeeded(int src_sample_rate_hz, int dst_sample_rate_hz, - int num_channels); + size_t num_channels); // Returns the total number of samples provided in destination (e.g. 32 kHz, // 2 channel audio gives 640 samples). @@ -40,7 +40,7 @@ class PushResampler { rtc::scoped_ptr<PushSincResampler> sinc_resampler_right_; int src_sample_rate_hz_; int dst_sample_rate_hz_; - int num_channels_; + size_t num_channels_; rtc::scoped_ptr<T[]> src_left_; rtc::scoped_ptr<T[]> src_right_; rtc::scoped_ptr<T[]> dst_left_; diff --git a/webrtc/common_audio/resampler/include/resampler.h b/webrtc/common_audio/resampler/include/resampler.h index 0d4c1afe4e..e26ac904c0 100644 --- a/webrtc/common_audio/resampler/include/resampler.h +++ b/webrtc/common_audio/resampler/include/resampler.h @@ -28,14 +28,14 @@ class Resampler public: Resampler(); - Resampler(int inFreq, int outFreq, int num_channels); + Resampler(int inFreq, int outFreq, size_t num_channels); ~Resampler(); // Reset all states - int Reset(int inFreq, int outFreq, int num_channels); + int Reset(int inFreq, int outFreq, size_t num_channels); // Reset all states if any parameter has changed - int ResetIfNeeded(int inFreq, int outFreq, int num_channels); + int ResetIfNeeded(int inFreq, int outFreq, size_t num_channels); // Resample samplesIn to samplesOut. int Push(const int16_t* samplesIn, size_t lengthIn, int16_t* samplesOut, @@ -83,7 +83,7 @@ private: int my_in_frequency_khz_; int my_out_frequency_khz_; ResamplerMode my_mode_; - int num_channels_; + size_t num_channels_; // Extra instance for stereo Resampler* slave_left_; diff --git a/webrtc/common_audio/resampler/push_resampler.cc b/webrtc/common_audio/resampler/push_resampler.cc index 566acdeaa3..f654e9a397 100644 --- a/webrtc/common_audio/resampler/push_resampler.cc +++ b/webrtc/common_audio/resampler/push_resampler.cc @@ -32,7 +32,7 @@ PushResampler<T>::~PushResampler() { template <typename T> int PushResampler<T>::InitializeIfNeeded(int src_sample_rate_hz, int dst_sample_rate_hz, - int num_channels) { + size_t num_channels) { if (src_sample_rate_hz == src_sample_rate_hz_ && dst_sample_rate_hz == dst_sample_rate_hz_ && num_channels == num_channels_) @@ -68,10 +68,8 @@ int PushResampler<T>::InitializeIfNeeded(int src_sample_rate_hz, template <typename T> int PushResampler<T>::Resample(const T* src, size_t src_length, T* dst, size_t dst_capacity) { - const size_t src_size_10ms = - static_cast<size_t>(src_sample_rate_hz_ * num_channels_ / 100); - const size_t dst_size_10ms = - static_cast<size_t>(dst_sample_rate_hz_ * num_channels_ / 100); + const size_t src_size_10ms = src_sample_rate_hz_ * num_channels_ / 100; + const size_t dst_size_10ms = dst_sample_rate_hz_ * num_channels_ / 100; if (src_length != src_size_10ms || dst_capacity < dst_size_10ms) return -1; diff --git a/webrtc/common_audio/resampler/resampler.cc b/webrtc/common_audio/resampler/resampler.cc index c9e7a1fb96..7c690fc47a 100644 --- a/webrtc/common_audio/resampler/resampler.cc +++ b/webrtc/common_audio/resampler/resampler.cc @@ -39,7 +39,7 @@ Resampler::Resampler() slave_right_(nullptr) { } -Resampler::Resampler(int inFreq, int outFreq, int num_channels) +Resampler::Resampler(int inFreq, int outFreq, size_t num_channels) : Resampler() { Reset(inFreq, outFreq, num_channels); } @@ -76,7 +76,7 @@ Resampler::~Resampler() } } -int Resampler::ResetIfNeeded(int inFreq, int outFreq, int num_channels) +int Resampler::ResetIfNeeded(int inFreq, int outFreq, size_t num_channels) { int tmpInFreq_kHz = inFreq / 1000; int tmpOutFreq_kHz = outFreq / 1000; @@ -91,7 +91,7 @@ int Resampler::ResetIfNeeded(int inFreq, int outFreq, int num_channels) } } -int Resampler::Reset(int inFreq, int outFreq, int num_channels) +int Resampler::Reset(int inFreq, int outFreq, size_t num_channels) { if (num_channels != 1 && num_channels != 2) { return -1; diff --git a/webrtc/common_audio/signal_processing/real_fft_unittest.cc b/webrtc/common_audio/signal_processing/real_fft_unittest.cc index 9bd35cd68b..fa98836b9a 100644 --- a/webrtc/common_audio/signal_processing/real_fft_unittest.cc +++ b/webrtc/common_audio/signal_processing/real_fft_unittest.cc @@ -10,7 +10,6 @@ #include "webrtc/common_audio/signal_processing/include/real_fft.h" #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" -#include "webrtc/test/testsupport/gtest_disable.h" #include "webrtc/typedefs.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/webrtc/common_audio/swap_queue.h b/webrtc/common_audio/swap_queue.h new file mode 100644 index 0000000000..d8bb5c024e --- /dev/null +++ b/webrtc/common_audio/swap_queue.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2015 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. + */ + +#ifndef WEBRTC_COMMON_AUDIO_SWAP_QUEUE_H_ +#define WEBRTC_COMMON_AUDIO_SWAP_QUEUE_H_ + +#include <algorithm> +#include <utility> +#include <vector> + +#include "webrtc/base/checks.h" +#include "webrtc/base/criticalsection.h" + +namespace webrtc { + +namespace internal { + +// (Internal; please don't use outside this file.) +template <typename T> +bool NoopSwapQueueItemVerifierFunction(const T&) { + return true; +} + +} // namespace internal + +// Functor to use when supplying a verifier function for the queue. +template <typename T, + bool (*QueueItemVerifierFunction)(const T&) = + internal::NoopSwapQueueItemVerifierFunction> +class SwapQueueItemVerifier { + public: + bool operator()(const T& t) const { return QueueItemVerifierFunction(t); } +}; + +// This class is a fixed-size queue. A producer calls Insert() to insert +// an element of type T at the back of the queue, and a consumer calls +// Remove() to remove an element from the front of the queue. It's safe +// for the producer(s) and the consumer(s) to access the queue +// concurrently, from different threads. +// +// To avoid the construction, copying, and destruction of Ts that a naive +// queue implementation would require, for each "full" T passed from +// producer to consumer, SwapQueue<T> passes an "empty" T in the other +// direction (an "empty" T is one that contains nothing of value for the +// consumer). This bidirectional movement is implemented with swap(). +// +// // Create queue: +// Bottle proto(568); // Prepare an empty Bottle. Heap allocates space for +// // 568 ml. +// SwapQueue<Bottle> q(N, proto); // Init queue with N copies of proto. +// // Each copy allocates on the heap. +// // Producer pseudo-code: +// Bottle b(568); // Prepare an empty Bottle. Heap allocates space for 568 ml. +// loop { +// b.Fill(amount); // Where amount <= 568 ml. +// q.Insert(&b); // Swap our full Bottle for an empty one from q. +// } +// +// // Consumer pseudo-code: +// Bottle b(568); // Prepare an empty Bottle. Heap allocates space for 568 ml. +// loop { +// q.Remove(&b); // Swap our empty Bottle for the next-in-line full Bottle. +// Drink(&b); +// } +// +// For a well-behaved Bottle class, there are no allocations in the +// producer, since it just fills an empty Bottle that's already large +// enough; no deallocations in the consumer, since it returns each empty +// Bottle to the queue after having drunk it; and no copies along the +// way, since the queue uses swap() everywhere to move full Bottles in +// one direction and empty ones in the other. +template <typename T, typename QueueItemVerifier = SwapQueueItemVerifier<T>> +class SwapQueue { + public: + // Creates a queue of size size and fills it with default constructed Ts. + explicit SwapQueue(size_t size) : queue_(size) { + RTC_DCHECK(VerifyQueueSlots()); + } + + // Same as above and accepts an item verification functor. + SwapQueue(size_t size, const QueueItemVerifier& queue_item_verifier) + : queue_item_verifier_(queue_item_verifier), queue_(size) { + RTC_DCHECK(VerifyQueueSlots()); + } + + // Creates a queue of size size and fills it with copies of prototype. + SwapQueue(size_t size, const T& prototype) : queue_(size, prototype) { + RTC_DCHECK(VerifyQueueSlots()); + } + + // Same as above and accepts an item verification functor. + SwapQueue(size_t size, + const T& prototype, + const QueueItemVerifier& queue_item_verifier) + : queue_item_verifier_(queue_item_verifier), queue_(size, prototype) { + RTC_DCHECK(VerifyQueueSlots()); + } + + // Resets the queue to have zero content wile maintaining the queue size. + void Clear() { + rtc::CritScope cs(&crit_queue_); + next_write_index_ = 0; + next_read_index_ = 0; + num_elements_ = 0; + } + + // Inserts a "full" T at the back of the queue by swapping *input with an + // "empty" T from the queue. + // Returns true if the item was inserted or false if not (the queue was full). + // When specified, the T given in *input must pass the ItemVerifier() test. + // The contents of *input after the call are then also guaranteed to pass the + // ItemVerifier() test. + bool Insert(T* input) WARN_UNUSED_RESULT { + RTC_DCHECK(input); + + rtc::CritScope cs(&crit_queue_); + + RTC_DCHECK(queue_item_verifier_(*input)); + + if (num_elements_ == queue_.size()) { + return false; + } + + using std::swap; + swap(*input, queue_[next_write_index_]); + + ++next_write_index_; + if (next_write_index_ == queue_.size()) { + next_write_index_ = 0; + } + + ++num_elements_; + + RTC_DCHECK_LT(next_write_index_, queue_.size()); + RTC_DCHECK_LE(num_elements_, queue_.size()); + + return true; + } + + // Removes the frontmost "full" T from the queue by swapping it with + // the "empty" T in *output. + // Returns true if an item could be removed or false if not (the queue was + // empty). When specified, The T given in *output must pass the ItemVerifier() + // test and the contents of *output after the call are then also guaranteed to + // pass the ItemVerifier() test. + bool Remove(T* output) WARN_UNUSED_RESULT { + RTC_DCHECK(output); + + rtc::CritScope cs(&crit_queue_); + + RTC_DCHECK(queue_item_verifier_(*output)); + + if (num_elements_ == 0) { + return false; + } + + using std::swap; + swap(*output, queue_[next_read_index_]); + + ++next_read_index_; + if (next_read_index_ == queue_.size()) { + next_read_index_ = 0; + } + + --num_elements_; + + RTC_DCHECK_LT(next_read_index_, queue_.size()); + RTC_DCHECK_LE(num_elements_, queue_.size()); + + return true; + } + + private: + // Verify that the queue slots complies with the ItemVerifier test. + bool VerifyQueueSlots() { + rtc::CritScope cs(&crit_queue_); + for (const auto& v : queue_) { + RTC_DCHECK(queue_item_verifier_(v)); + } + return true; + } + + rtc::CriticalSection crit_queue_; + + // TODO(peah): Change this to use std::function() once we can use C++11 std + // lib. + QueueItemVerifier queue_item_verifier_ GUARDED_BY(crit_queue_); + + // (next_read_index_ + num_elements_) % queue_.size() = + // next_write_index_ + size_t next_write_index_ GUARDED_BY(crit_queue_) = 0; + size_t next_read_index_ GUARDED_BY(crit_queue_) = 0; + size_t num_elements_ GUARDED_BY(crit_queue_) = 0; + + // queue_.size() is constant. + std::vector<T> queue_ GUARDED_BY(crit_queue_); + + RTC_DISALLOW_COPY_AND_ASSIGN(SwapQueue); +}; + +} // namespace webrtc + +#endif // WEBRTC_COMMON_AUDIO_SWAP_QUEUE_H_ diff --git a/webrtc/common_audio/swap_queue_unittest.cc b/webrtc/common_audio/swap_queue_unittest.cc new file mode 100644 index 0000000000..104e494bc6 --- /dev/null +++ b/webrtc/common_audio/swap_queue_unittest.cc @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/common_audio/swap_queue.h" + +#include <vector> + +#include "testing/gtest/include/gtest/gtest.h" + +namespace webrtc { + +namespace { + +// Test parameter for the basic sample based SwapQueue Tests. +const size_t kChunkSize = 3; + +// Queue item verification function for the vector test. +bool LengthVerifierFunction(const std::vector<int>& v) { + return v.size() == kChunkSize; +} + +// Queue item verifier for the vector test. +class LengthVerifierFunctor { + public: + explicit LengthVerifierFunctor(size_t length) : length_(length) {} + + bool operator()(const std::vector<int>& v) const { + return v.size() == length_; + } + + private: + size_t length_; +}; + +} // anonymous namespace + +TEST(SwapQueueTest, BasicOperation) { + std::vector<int> i(kChunkSize, 0); + SwapQueue<std::vector<int>> queue(2, i); + + EXPECT_TRUE(queue.Insert(&i)); + EXPECT_EQ(i.size(), kChunkSize); + EXPECT_TRUE(queue.Insert(&i)); + EXPECT_EQ(i.size(), kChunkSize); + EXPECT_TRUE(queue.Remove(&i)); + EXPECT_EQ(i.size(), kChunkSize); + EXPECT_TRUE(queue.Remove(&i)); + EXPECT_EQ(i.size(), kChunkSize); +} + +TEST(SwapQueueTest, FullQueue) { + SwapQueue<int> queue(2); + + // Fill the queue. + int i = 0; + EXPECT_TRUE(queue.Insert(&i)); + i = 1; + EXPECT_TRUE(queue.Insert(&i)); + + // Ensure that the value is not swapped when doing an Insert + // on a full queue. + i = 2; + EXPECT_FALSE(queue.Insert(&i)); + EXPECT_EQ(i, 2); + + // Ensure that the Insert didn't overwrite anything in the queue. + EXPECT_TRUE(queue.Remove(&i)); + EXPECT_EQ(i, 0); + EXPECT_TRUE(queue.Remove(&i)); + EXPECT_EQ(i, 1); +} + +TEST(SwapQueueTest, EmptyQueue) { + SwapQueue<int> queue(2); + int i = 0; + EXPECT_FALSE(queue.Remove(&i)); + EXPECT_TRUE(queue.Insert(&i)); + EXPECT_TRUE(queue.Remove(&i)); + EXPECT_FALSE(queue.Remove(&i)); +} + +TEST(SwapQueueTest, Clear) { + SwapQueue<int> queue(2); + int i = 0; + + // Fill the queue. + EXPECT_TRUE(queue.Insert(&i)); + EXPECT_TRUE(queue.Insert(&i)); + + // Ensure full queue. + EXPECT_FALSE(queue.Insert(&i)); + + // Empty the queue. + queue.Clear(); + + // Ensure that the queue is empty + EXPECT_FALSE(queue.Remove(&i)); + + // Ensure that the queue is no longer full. + EXPECT_TRUE(queue.Insert(&i)); +} + +TEST(SwapQueueTest, SuccessfulItemVerifyFunction) { + std::vector<int> template_element(kChunkSize); + SwapQueue<std::vector<int>, + SwapQueueItemVerifier<std::vector<int>, LengthVerifierFunction>> + queue(2, template_element); + std::vector<int> valid_chunk(kChunkSize, 0); + + EXPECT_TRUE(queue.Insert(&valid_chunk)); + EXPECT_EQ(valid_chunk.size(), kChunkSize); + EXPECT_TRUE(queue.Remove(&valid_chunk)); + EXPECT_EQ(valid_chunk.size(), kChunkSize); +} + +TEST(SwapQueueTest, SuccessfulItemVerifyFunctor) { + std::vector<int> template_element(kChunkSize); + LengthVerifierFunctor verifier(kChunkSize); + SwapQueue<std::vector<int>, LengthVerifierFunctor> queue(2, template_element, + verifier); + std::vector<int> valid_chunk(kChunkSize, 0); + + EXPECT_TRUE(queue.Insert(&valid_chunk)); + EXPECT_EQ(valid_chunk.size(), kChunkSize); + EXPECT_TRUE(queue.Remove(&valid_chunk)); + EXPECT_EQ(valid_chunk.size(), kChunkSize); +} + +#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) +TEST(SwapQueueTest, UnsuccessfulItemVerifyFunctor) { + // Queue item verifier for the test. + auto minus_2_verifier = [](const int& i) { return i > -2; }; + SwapQueue<int, decltype(minus_2_verifier)> queue(2, minus_2_verifier); + + int valid_value = 1; + int invalid_value = -4; + EXPECT_TRUE(queue.Insert(&valid_value)); + EXPECT_TRUE(queue.Remove(&valid_value)); + bool result; + EXPECT_DEATH(result = queue.Insert(&invalid_value), ""); +} + +TEST(SwapQueueTest, UnSuccessfulItemVerifyInsert) { + std::vector<int> template_element(kChunkSize); + SwapQueue<std::vector<int>, + SwapQueueItemVerifier<std::vector<int>, &LengthVerifierFunction>> + queue(2, template_element); + std::vector<int> invalid_chunk(kChunkSize - 1, 0); + bool result; + EXPECT_DEATH(result = queue.Insert(&invalid_chunk), ""); +} + +TEST(SwapQueueTest, UnSuccessfulItemVerifyRemove) { + std::vector<int> template_element(kChunkSize); + SwapQueue<std::vector<int>, + SwapQueueItemVerifier<std::vector<int>, &LengthVerifierFunction>> + queue(2, template_element); + std::vector<int> invalid_chunk(kChunkSize - 1, 0); + std::vector<int> valid_chunk(kChunkSize, 0); + EXPECT_TRUE(queue.Insert(&valid_chunk)); + EXPECT_EQ(valid_chunk.size(), kChunkSize); + bool result; + EXPECT_DEATH(result = queue.Remove(&invalid_chunk), ""); +} +#endif + +TEST(SwapQueueTest, VectorContentTest) { + const size_t kQueueSize = 10; + const size_t kFrameLength = 160; + const size_t kDataLength = kQueueSize * kFrameLength; + std::vector<int16_t> buffer_reader(kFrameLength, 0); + std::vector<int16_t> buffer_writer(kFrameLength, 0); + SwapQueue<std::vector<int16_t>> queue(kQueueSize, + std::vector<int16_t>(kFrameLength)); + std::vector<int16_t> samples(kDataLength); + + for (size_t k = 0; k < kDataLength; k++) { + samples[k] = k % 9; + } + + for (size_t k = 0; k < kQueueSize; k++) { + buffer_writer.clear(); + buffer_writer.insert(buffer_writer.end(), &samples[0] + k * kFrameLength, + &samples[0] + (k + 1) * kFrameLength); + + EXPECT_TRUE(queue.Insert(&buffer_writer)); + } + + for (size_t k = 0; k < kQueueSize; k++) { + EXPECT_TRUE(queue.Remove(&buffer_reader)); + + for (size_t j = 0; j < buffer_reader.size(); j++) { + EXPECT_EQ(buffer_reader[j], samples[k * kFrameLength + j]); + } + } +} + +TEST(SwapQueueTest, ZeroSlotQueue) { + SwapQueue<int> queue(0); + int i = 42; + EXPECT_FALSE(queue.Insert(&i)); + EXPECT_FALSE(queue.Remove(&i)); + EXPECT_EQ(i, 42); +} + +TEST(SwapQueueTest, OneSlotQueue) { + SwapQueue<int> queue(1); + int i = 42; + EXPECT_TRUE(queue.Insert(&i)); + i = 43; + EXPECT_FALSE(queue.Insert(&i)); + EXPECT_EQ(i, 43); + EXPECT_TRUE(queue.Remove(&i)); + EXPECT_EQ(i, 42); + EXPECT_FALSE(queue.Remove(&i)); +} + +} // namespace webrtc diff --git a/webrtc/common_audio/wav_file.cc b/webrtc/common_audio/wav_file.cc index 8dae7d6e98..94b7a3c2c0 100644 --- a/webrtc/common_audio/wav_file.cc +++ b/webrtc/common_audio/wav_file.cc @@ -13,6 +13,7 @@ #include <algorithm> #include <cstdio> #include <limits> +#include <sstream> #include "webrtc/base/checks.h" #include "webrtc/base/safe_conversions.h" @@ -23,7 +24,7 @@ namespace webrtc { // We write 16-bit PCM WAV files. static const WavFormat kWavFormat = kWavFormatPcm; -static const int kBytesPerSample = 2; +static const size_t kBytesPerSample = 2; // Doesn't take ownership of the file handle and won't close it. class ReadableWavFile : public ReadableWav { @@ -37,13 +38,21 @@ class ReadableWavFile : public ReadableWav { FILE* file_; }; +std::string WavFile::FormatAsString() const { + std::ostringstream s; + s << "Sample rate: " << sample_rate() << " Hz, Channels: " << num_channels() + << ", Duration: " + << (1.f * num_samples()) / (num_channels() * sample_rate()) << " s"; + return s.str(); +} + WavReader::WavReader(const std::string& filename) : file_handle_(fopen(filename.c_str(), "rb")) { - RTC_CHECK(file_handle_ && "Could not open wav file for reading."); + RTC_CHECK(file_handle_) << "Could not open wav file for reading."; ReadableWavFile readable(file_handle_); WavFormat format; - int bytes_per_sample; + size_t bytes_per_sample; RTC_CHECK(ReadWavHeader(&readable, &num_channels_, &sample_rate_, &format, &bytes_per_sample, &num_samples_)); num_samples_remaining_ = num_samples_; @@ -60,14 +69,13 @@ size_t WavReader::ReadSamples(size_t num_samples, int16_t* samples) { #error "Need to convert samples to big-endian when reading from WAV file" #endif // There could be metadata after the audio; ensure we don't read it. - num_samples = std::min(rtc::checked_cast<uint32_t>(num_samples), - num_samples_remaining_); + num_samples = std::min(num_samples, num_samples_remaining_); const size_t read = fread(samples, sizeof(*samples), num_samples, file_handle_); // If we didn't read what was requested, ensure we've reached the EOF. RTC_CHECK(read == num_samples || feof(file_handle_)); RTC_CHECK_LE(read, num_samples_remaining_); - num_samples_remaining_ -= rtc::checked_cast<uint32_t>(read); + num_samples_remaining_ -= read; return read; } @@ -91,12 +99,12 @@ void WavReader::Close() { } WavWriter::WavWriter(const std::string& filename, int sample_rate, - int num_channels) + size_t num_channels) : sample_rate_(sample_rate), num_channels_(num_channels), num_samples_(0), file_handle_(fopen(filename.c_str(), "wb")) { - RTC_CHECK(file_handle_ && "Could not open wav file for writing."); + RTC_CHECK(file_handle_) << "Could not open wav file for writing."; RTC_CHECK(CheckWavParameters(num_channels_, sample_rate_, kWavFormat, kBytesPerSample, num_samples_)); @@ -117,9 +125,8 @@ void WavWriter::WriteSamples(const int16_t* samples, size_t num_samples) { const size_t written = fwrite(samples, sizeof(*samples), num_samples, file_handle_); RTC_CHECK_EQ(num_samples, written); - num_samples_ += static_cast<uint32_t>(written); - RTC_CHECK(written <= std::numeric_limits<uint32_t>::max() || - num_samples_ >= written); // detect uint32_t overflow + num_samples_ += written; + RTC_CHECK(num_samples_ >= written); // detect size_t overflow } void WavWriter::WriteSamples(const float* samples, size_t num_samples) { @@ -146,7 +153,7 @@ void WavWriter::Close() { rtc_WavWriter* rtc_WavOpen(const char* filename, int sample_rate, - int num_channels) { + size_t num_channels) { return reinterpret_cast<rtc_WavWriter*>( new webrtc::WavWriter(filename, sample_rate, num_channels)); } @@ -165,10 +172,10 @@ int rtc_WavSampleRate(const rtc_WavWriter* wf) { return reinterpret_cast<const webrtc::WavWriter*>(wf)->sample_rate(); } -int rtc_WavNumChannels(const rtc_WavWriter* wf) { +size_t rtc_WavNumChannels(const rtc_WavWriter* wf) { return reinterpret_cast<const webrtc::WavWriter*>(wf)->num_channels(); } -uint32_t rtc_WavNumSamples(const rtc_WavWriter* wf) { +size_t rtc_WavNumSamples(const rtc_WavWriter* wf) { return reinterpret_cast<const webrtc::WavWriter*>(wf)->num_samples(); } diff --git a/webrtc/common_audio/wav_file.h b/webrtc/common_audio/wav_file.h index 2eadd3f775..e656eb8643 100644 --- a/webrtc/common_audio/wav_file.h +++ b/webrtc/common_audio/wav_file.h @@ -27,8 +27,11 @@ class WavFile { virtual ~WavFile() {} virtual int sample_rate() const = 0; - virtual int num_channels() const = 0; - virtual uint32_t num_samples() const = 0; + virtual size_t num_channels() const = 0; + virtual size_t num_samples() const = 0; + + // Returns a human-readable string containing the audio format. + std::string FormatAsString() const; }; // Simple C++ class for writing 16-bit PCM WAV files. All error handling is @@ -36,7 +39,7 @@ class WavFile { class WavWriter final : public WavFile { public: // Open a new WAV file for writing. - WavWriter(const std::string& filename, int sample_rate, int num_channels); + WavWriter(const std::string& filename, int sample_rate, size_t num_channels); // Close the WAV file, after writing its header. ~WavWriter(); @@ -48,14 +51,14 @@ class WavWriter final : public WavFile { void WriteSamples(const int16_t* samples, size_t num_samples); int sample_rate() const override { return sample_rate_; } - int num_channels() const override { return num_channels_; } - uint32_t num_samples() const override { return num_samples_; } + size_t num_channels() const override { return num_channels_; } + size_t num_samples() const override { return num_samples_; } private: void Close(); const int sample_rate_; - const int num_channels_; - uint32_t num_samples_; // Total number of samples written to file. + const size_t num_channels_; + size_t num_samples_; // Total number of samples written to file. FILE* file_handle_; // Output file, owned by this class RTC_DISALLOW_COPY_AND_ASSIGN(WavWriter); @@ -76,15 +79,15 @@ class WavReader final : public WavFile { size_t ReadSamples(size_t num_samples, int16_t* samples); int sample_rate() const override { return sample_rate_; } - int num_channels() const override { return num_channels_; } - uint32_t num_samples() const override { return num_samples_; } + size_t num_channels() const override { return num_channels_; } + size_t num_samples() const override { return num_samples_; } private: void Close(); int sample_rate_; - int num_channels_; - uint32_t num_samples_; // Total number of samples in the file. - uint32_t num_samples_remaining_; + size_t num_channels_; + size_t num_samples_; // Total number of samples in the file. + size_t num_samples_remaining_; FILE* file_handle_; // Input file, owned by this class. RTC_DISALLOW_COPY_AND_ASSIGN(WavReader); @@ -99,14 +102,14 @@ extern "C" { typedef struct rtc_WavWriter rtc_WavWriter; rtc_WavWriter* rtc_WavOpen(const char* filename, int sample_rate, - int num_channels); + size_t num_channels); void rtc_WavClose(rtc_WavWriter* wf); void rtc_WavWriteSamples(rtc_WavWriter* wf, const float* samples, size_t num_samples); int rtc_WavSampleRate(const rtc_WavWriter* wf); -int rtc_WavNumChannels(const rtc_WavWriter* wf); -uint32_t rtc_WavNumSamples(const rtc_WavWriter* wf); +size_t rtc_WavNumChannels(const rtc_WavWriter* wf); +size_t rtc_WavNumSamples(const rtc_WavWriter* wf); #ifdef __cplusplus } // extern "C" diff --git a/webrtc/common_audio/wav_file_unittest.cc b/webrtc/common_audio/wav_file_unittest.cc index 78b0a34de9..ba1db1c296 100644 --- a/webrtc/common_audio/wav_file_unittest.cc +++ b/webrtc/common_audio/wav_file_unittest.cc @@ -26,11 +26,11 @@ static const float kSamples[] = {0.0, 10.0, 4e4, -1e9}; // Write a tiny WAV file with the C++ interface and verify the result. TEST(WavWriterTest, CPP) { const std::string outfile = test::OutputPath() + "wavtest1.wav"; - static const uint32_t kNumSamples = 3; + static const size_t kNumSamples = 3; { WavWriter w(outfile, 14099, 1); EXPECT_EQ(14099, w.sample_rate()); - EXPECT_EQ(1, w.num_channels()); + EXPECT_EQ(1u, w.num_channels()); EXPECT_EQ(0u, w.num_samples()); w.WriteSamples(kSamples, kNumSamples); EXPECT_EQ(kNumSamples, w.num_samples()); @@ -64,10 +64,10 @@ TEST(WavWriterTest, CPP) { 0xff, 0x7f, // third sample: 4e4 (saturated) kMetadata[0], kMetadata[1], }; - static const int kContentSize = + static const size_t kContentSize = kWavHeaderSize + kNumSamples * sizeof(int16_t) + sizeof(kMetadata); static_assert(sizeof(kExpectedContents) == kContentSize, "content size"); - EXPECT_EQ(size_t(kContentSize), test::GetFileSize(outfile)); + EXPECT_EQ(kContentSize, test::GetFileSize(outfile)); FILE* f = fopen(outfile.c_str(), "rb"); ASSERT_TRUE(f); uint8_t contents[kContentSize]; @@ -78,7 +78,7 @@ TEST(WavWriterTest, CPP) { { WavReader r(outfile); EXPECT_EQ(14099, r.sample_rate()); - EXPECT_EQ(1, r.num_channels()); + 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]; @@ -93,9 +93,9 @@ TEST(WavWriterTest, C) { const std::string outfile = test::OutputPath() + "wavtest2.wav"; rtc_WavWriter* w = rtc_WavOpen(outfile.c_str(), 11904, 2); EXPECT_EQ(11904, rtc_WavSampleRate(w)); - EXPECT_EQ(2, rtc_WavNumChannels(w)); + EXPECT_EQ(2u, rtc_WavNumChannels(w)); EXPECT_EQ(0u, rtc_WavNumSamples(w)); - static const uint32_t kNumSamples = 4; + static const size_t kNumSamples = 4; rtc_WavWriteSamples(w, &kSamples[0], 2); EXPECT_EQ(2u, rtc_WavNumSamples(w)); rtc_WavWriteSamples(w, &kSamples[2], kNumSamples - 2); @@ -120,10 +120,10 @@ TEST(WavWriterTest, C) { 0xff, 0x7f, // third sample: 4e4 (saturated) 0, 0x80, // fourth sample: -1e9 (saturated) }; - static const int kContentSize = + static const size_t kContentSize = kWavHeaderSize + kNumSamples * sizeof(int16_t); static_assert(sizeof(kExpectedContents) == kContentSize, "content size"); - EXPECT_EQ(size_t(kContentSize), test::GetFileSize(outfile)); + EXPECT_EQ(kContentSize, test::GetFileSize(outfile)); FILE* f = fopen(outfile.c_str(), "rb"); ASSERT_TRUE(f); uint8_t contents[kContentSize]; @@ -136,10 +136,10 @@ TEST(WavWriterTest, C) { TEST(WavWriterTest, LargeFile) { std::string outfile = test::OutputPath() + "wavtest3.wav"; static const int kSampleRate = 8000; - static const int kNumChannels = 2; - static const uint32_t kNumSamples = 3 * kSampleRate * kNumChannels; + static const size_t kNumChannels = 2; + static const size_t kNumSamples = 3 * kSampleRate * kNumChannels; float samples[kNumSamples]; - for (uint32_t i = 0; i < kNumSamples; i += kNumChannels) { + 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); diff --git a/webrtc/common_audio/wav_header.cc b/webrtc/common_audio/wav_header.cc index 61cfffe62c..402ea17916 100644 --- a/webrtc/common_audio/wav_header.cc +++ b/webrtc/common_audio/wav_header.cc @@ -59,20 +59,19 @@ static_assert(sizeof(WavHeader) == kWavHeaderSize, "no padding in header"); } // namespace -bool CheckWavParameters(int num_channels, +bool CheckWavParameters(size_t num_channels, int sample_rate, WavFormat format, - int bytes_per_sample, - uint32_t num_samples) { + size_t bytes_per_sample, + size_t num_samples) { // num_channels, sample_rate, and bytes_per_sample must be positive, must fit // in their respective fields, and their product must fit in the 32-bit // ByteRate field. - if (num_channels <= 0 || sample_rate <= 0 || bytes_per_sample <= 0) + if (num_channels == 0 || sample_rate <= 0 || bytes_per_sample == 0) return false; if (static_cast<uint64_t>(sample_rate) > std::numeric_limits<uint32_t>::max()) return false; - if (static_cast<uint64_t>(num_channels) > - std::numeric_limits<uint16_t>::max()) + if (num_channels > std::numeric_limits<uint16_t>::max()) return false; if (static_cast<uint64_t>(bytes_per_sample) * 8 > std::numeric_limits<uint16_t>::max()) @@ -99,10 +98,9 @@ bool CheckWavParameters(int num_channels, // The number of bytes in the file, not counting the first ChunkHeader, must // be less than 2^32; otherwise, the ChunkSize field overflows. - const uint32_t max_samples = - (std::numeric_limits<uint32_t>::max() - - (kWavHeaderSize - sizeof(ChunkHeader))) / - bytes_per_sample; + const size_t header_size = kWavHeaderSize - sizeof(ChunkHeader); + const size_t max_samples = + (std::numeric_limits<uint32_t>::max() - header_size) / bytes_per_sample; if (num_samples > max_samples) return false; @@ -132,30 +130,32 @@ static inline std::string ReadFourCC(uint32_t x) { #error "Write be-to-le conversion functions" #endif -static inline uint32_t RiffChunkSize(uint32_t bytes_in_payload) { - return bytes_in_payload + kWavHeaderSize - sizeof(ChunkHeader); +static inline uint32_t RiffChunkSize(size_t bytes_in_payload) { + return static_cast<uint32_t>( + bytes_in_payload + kWavHeaderSize - sizeof(ChunkHeader)); } -static inline uint32_t ByteRate(int num_channels, int sample_rate, - int bytes_per_sample) { - return static_cast<uint32_t>(num_channels) * sample_rate * bytes_per_sample; +static inline uint32_t ByteRate(size_t num_channels, int sample_rate, + size_t bytes_per_sample) { + return static_cast<uint32_t>(num_channels * sample_rate * bytes_per_sample); } -static inline uint16_t BlockAlign(int num_channels, int bytes_per_sample) { - return num_channels * bytes_per_sample; +static inline uint16_t BlockAlign(size_t num_channels, + size_t bytes_per_sample) { + return static_cast<uint16_t>(num_channels * bytes_per_sample); } void WriteWavHeader(uint8_t* buf, - int num_channels, + size_t num_channels, int sample_rate, WavFormat format, - int bytes_per_sample, - uint32_t num_samples) { + size_t bytes_per_sample, + size_t num_samples) { RTC_CHECK(CheckWavParameters(num_channels, sample_rate, format, bytes_per_sample, num_samples)); WavHeader header; - const uint32_t bytes_in_payload = bytes_per_sample * num_samples; + const size_t bytes_in_payload = bytes_per_sample * num_samples; WriteFourCC(&header.riff.header.ID, 'R', 'I', 'F', 'F'); WriteLE32(&header.riff.header.Size, RiffChunkSize(bytes_in_payload)); @@ -164,15 +164,16 @@ void WriteWavHeader(uint8_t* buf, WriteFourCC(&header.fmt.header.ID, 'f', 'm', 't', ' '); WriteLE32(&header.fmt.header.Size, kFmtSubchunkSize); WriteLE16(&header.fmt.AudioFormat, format); - WriteLE16(&header.fmt.NumChannels, num_channels); + WriteLE16(&header.fmt.NumChannels, static_cast<uint16_t>(num_channels)); WriteLE32(&header.fmt.SampleRate, sample_rate); WriteLE32(&header.fmt.ByteRate, ByteRate(num_channels, sample_rate, bytes_per_sample)); WriteLE16(&header.fmt.BlockAlign, BlockAlign(num_channels, bytes_per_sample)); - WriteLE16(&header.fmt.BitsPerSample, 8 * bytes_per_sample); + WriteLE16(&header.fmt.BitsPerSample, + static_cast<uint16_t>(8 * bytes_per_sample)); WriteFourCC(&header.data.header.ID, 'd', 'a', 't', 'a'); - WriteLE32(&header.data.header.Size, bytes_in_payload); + WriteLE32(&header.data.header.Size, static_cast<uint32_t>(bytes_in_payload)); // Do an extra copy rather than writing everything to buf directly, since buf // might not be correctly aligned. @@ -180,11 +181,11 @@ void WriteWavHeader(uint8_t* buf, } bool ReadWavHeader(ReadableWav* readable, - int* num_channels, + size_t* num_channels, int* sample_rate, WavFormat* format, - int* bytes_per_sample, - uint32_t* num_samples) { + size_t* bytes_per_sample, + size_t* num_samples) { WavHeader header; if (readable->Read(&header, kWavHeaderSize - sizeof(header.data)) != kWavHeaderSize - sizeof(header.data)) @@ -210,8 +211,8 @@ bool ReadWavHeader(ReadableWav* readable, *num_channels = ReadLE16(header.fmt.NumChannels); *sample_rate = ReadLE32(header.fmt.SampleRate); *bytes_per_sample = ReadLE16(header.fmt.BitsPerSample) / 8; - const uint32_t bytes_in_payload = ReadLE32(header.data.header.Size); - if (*bytes_per_sample <= 0) + const size_t bytes_in_payload = ReadLE32(header.data.header.Size); + if (*bytes_per_sample == 0) return false; *num_samples = bytes_in_payload / *bytes_per_sample; diff --git a/webrtc/common_audio/wav_header.h b/webrtc/common_audio/wav_header.h index 1a0fd7c81d..6844306941 100644 --- a/webrtc/common_audio/wav_header.h +++ b/webrtc/common_audio/wav_header.h @@ -32,32 +32,32 @@ enum WavFormat { }; // Return true if the given parameters will make a well-formed WAV header. -bool CheckWavParameters(int num_channels, +bool CheckWavParameters(size_t num_channels, int sample_rate, WavFormat format, - int bytes_per_sample, - uint32_t num_samples); + size_t bytes_per_sample, + size_t num_samples); // Write a kWavHeaderSize bytes long WAV header to buf. The payload that // follows the header is supposed to have the specified number of interleaved // channels and contain the specified total number of samples of the specified // type. CHECKs the input parameters for validity. void WriteWavHeader(uint8_t* buf, - int num_channels, + size_t num_channels, int sample_rate, WavFormat format, - int bytes_per_sample, - uint32_t num_samples); + size_t bytes_per_sample, + size_t num_samples); // Read a WAV header from an implemented ReadableWav and parse the values into // the provided output parameters. ReadableWav is used because the header can // be variably sized. Returns false if the header is invalid. bool ReadWavHeader(ReadableWav* readable, - int* num_channels, + size_t* num_channels, int* sample_rate, WavFormat* format, - int* bytes_per_sample, - uint32_t* num_samples); + size_t* bytes_per_sample, + size_t* num_samples); } // namespace webrtc diff --git a/webrtc/common_audio/wav_header_unittest.cc b/webrtc/common_audio/wav_header_unittest.cc index e03cb303aa..8527939eac 100644 --- a/webrtc/common_audio/wav_header_unittest.cc +++ b/webrtc/common_audio/wav_header_unittest.cc @@ -70,7 +70,7 @@ TEST(WavHeaderTest, CheckWavParameters) { // Try some really stupid values for one parameter at a time. EXPECT_TRUE(CheckWavParameters(1, 8000, kWavFormatPcm, 1, 0)); EXPECT_FALSE(CheckWavParameters(0, 8000, kWavFormatPcm, 1, 0)); - EXPECT_FALSE(CheckWavParameters(-1, 8000, kWavFormatPcm, 1, 0)); + EXPECT_FALSE(CheckWavParameters(0x10000, 8000, kWavFormatPcm, 1, 0)); EXPECT_FALSE(CheckWavParameters(1, 0, kWavFormatPcm, 1, 0)); EXPECT_FALSE(CheckWavParameters(1, 8000, WavFormat(0), 1, 0)); EXPECT_FALSE(CheckWavParameters(1, 8000, kWavFormatPcm, 0, 0)); @@ -91,11 +91,11 @@ TEST(WavHeaderTest, CheckWavParameters) { } TEST(WavHeaderTest, ReadWavHeaderWithErrors) { - int num_channels = 0; + size_t num_channels = 0; int sample_rate = 0; WavFormat format = kWavFormatPcm; - int bytes_per_sample = 0; - uint32_t num_samples = 0; + size_t bytes_per_sample = 0; + size_t num_samples = 0; // Test a few ways the header can be invalid. We start with the valid header // used in WriteAndReadWavHeader, and invalidate one field per test. The @@ -268,19 +268,19 @@ TEST(WavHeaderTest, WriteAndReadWavHeader) { static_assert(sizeof(kExpectedBuf) == kSize, "buffer size"); EXPECT_EQ(0, memcmp(kExpectedBuf, buf, kSize)); - int num_channels = 0; + size_t num_channels = 0; int sample_rate = 0; WavFormat format = kWavFormatPcm; - int bytes_per_sample = 0; - uint32_t num_samples = 0; + size_t bytes_per_sample = 0; + size_t num_samples = 0; ReadableWavBuffer r(buf + 4, sizeof(buf) - 8); EXPECT_TRUE( ReadWavHeader(&r, &num_channels, &sample_rate, &format, &bytes_per_sample, &num_samples)); - EXPECT_EQ(17, num_channels); + EXPECT_EQ(17u, num_channels); EXPECT_EQ(12345, sample_rate); EXPECT_EQ(kWavFormatALaw, format); - EXPECT_EQ(1, bytes_per_sample); + EXPECT_EQ(1u, bytes_per_sample); EXPECT_EQ(123457689u, num_samples); } @@ -304,19 +304,19 @@ TEST(WavHeaderTest, ReadAtypicalWavHeader) { 0x99, 0xd0, 0x5b, 0x07, // size of payload: 123457689 }; - int num_channels = 0; + size_t num_channels = 0; int sample_rate = 0; WavFormat format = kWavFormatPcm; - int bytes_per_sample = 0; - uint32_t num_samples = 0; + size_t bytes_per_sample = 0; + size_t num_samples = 0; ReadableWavBuffer r(kBuf, sizeof(kBuf)); EXPECT_TRUE( ReadWavHeader(&r, &num_channels, &sample_rate, &format, &bytes_per_sample, &num_samples)); - EXPECT_EQ(17, num_channels); + EXPECT_EQ(17u, num_channels); EXPECT_EQ(12345, sample_rate); EXPECT_EQ(kWavFormatALaw, format); - EXPECT_EQ(1, bytes_per_sample); + EXPECT_EQ(1u, bytes_per_sample); EXPECT_EQ(123457689u, num_samples); } |