1ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org/* 2ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org * 4ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org * Use of this source code is governed by a BSD-style license 5ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org * that can be found in the LICENSE file in the root of the source 6ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org * tree. An additional intellectual property rights grant can be found 7ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org * in the file PATENTS. All contributing project authors may 8ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org */ 10ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 11ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org// MSVC++ requires this to be set before any other includes to get M_PI. 12ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org#define _USE_MATH_DEFINES 13ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 14ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org#include <cmath> 15ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org#include <limits> 16ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 17ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org#include "testing/gtest/include/gtest/gtest.h" 18ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org#include "webrtc/base/compile_assert.h" 19ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org#include "webrtc/common_audio/wav_header.h" 20ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org#include "webrtc/common_audio/wav_writer.h" 21ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org#include "webrtc/test/testsupport/fileutils.h" 22ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 23ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.orgstatic const float kSamples[] = {0.0, 10.0, 4e4, -1e9}; 24ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 25ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org// Write a tiny WAV file with the C++ interface and verify the result. 26ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.orgTEST(WavWriterTest, CPP) { 27ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org const std::string outfile = webrtc::test::OutputPath() + "wavtest1.wav"; 28999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org static const uint32_t kNumSamples = 3; 29ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org { 30ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org webrtc::WavFile w(outfile, 14099, 1); 31999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(14099, w.sample_rate()); 32999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(1, w.num_channels()); 33999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(0u, w.num_samples()); 34ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org w.WriteSamples(kSamples, kNumSamples); 35999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(kNumSamples, w.num_samples()); 36ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org } 37ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org static const uint8_t kExpectedContents[] = { 38ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 'R', 'I', 'F', 'F', 39ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 42, 0, 0, 0, // size of whole file - 8: 6 + 44 - 8 40ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 'W', 'A', 'V', 'E', 41ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 'f', 'm', 't', ' ', 42ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 16, 0, 0, 0, // size of fmt block - 8: 24 - 8 43ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 1, 0, // format: PCM (1) 44ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 1, 0, // channels: 1 45ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 0x13, 0x37, 0, 0, // sample rate: 14099 46ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 0x26, 0x6e, 0, 0, // byte rate: 2 * 14099 47ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 2, 0, // block align: NumChannels * BytesPerSample 48ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 16, 0, // bits per sample: 2 * 8 49ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 'd', 'a', 't', 'a', 50ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 6, 0, 0, 0, // size of payload: 6 51ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 0, 0, // first sample: 0.0 52ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 10, 0, // second sample: 10.0 53ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 0xff, 0x7f, // third sample: 4e4 (saturated) 54ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org }; 55ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org static const int kContentSize = 56ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org webrtc::kWavHeaderSize + kNumSamples * sizeof(int16_t); 57ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org COMPILE_ASSERT(sizeof(kExpectedContents) == kContentSize, content_size); 58ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org EXPECT_EQ(size_t(kContentSize), webrtc::test::GetFileSize(outfile)); 59ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org FILE* f = fopen(outfile.c_str(), "rb"); 60ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org ASSERT_TRUE(f); 61ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org uint8_t contents[kContentSize]; 62ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org ASSERT_EQ(1u, fread(contents, kContentSize, 1, f)); 63ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org EXPECT_EQ(0, fclose(f)); 64ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org EXPECT_EQ(0, memcmp(kExpectedContents, contents, kContentSize)); 65ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org} 66ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 67ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org// Write a tiny WAV file with the C interface and verify the result. 68ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.orgTEST(WavWriterTest, C) { 69ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org const std::string outfile = webrtc::test::OutputPath() + "wavtest2.wav"; 70ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org rtc_WavFile *w = rtc_WavOpen(outfile.c_str(), 11904, 2); 71999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(11904, rtc_WavSampleRate(w)); 72999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(2, rtc_WavNumChannels(w)); 73999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(0u, rtc_WavNumSamples(w)); 74999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org static const uint32_t kNumSamples = 4; 75ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org rtc_WavWriteSamples(w, &kSamples[0], 2); 76999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(2u, rtc_WavNumSamples(w)); 77ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org rtc_WavWriteSamples(w, &kSamples[2], kNumSamples - 2); 78999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(kNumSamples, rtc_WavNumSamples(w)); 79ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org rtc_WavClose(w); 80ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org static const uint8_t kExpectedContents[] = { 81ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 'R', 'I', 'F', 'F', 82ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 44, 0, 0, 0, // size of whole file - 8: 8 + 44 - 8 83ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 'W', 'A', 'V', 'E', 84ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 'f', 'm', 't', ' ', 85ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 16, 0, 0, 0, // size of fmt block - 8: 24 - 8 86ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 1, 0, // format: PCM (1) 87ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 2, 0, // channels: 2 88ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 0x80, 0x2e, 0, 0, // sample rate: 11904 89ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 0, 0xba, 0, 0, // byte rate: 2 * 2 * 11904 90ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 4, 0, // block align: NumChannels * BytesPerSample 91ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 16, 0, // bits per sample: 2 * 8 92ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 'd', 'a', 't', 'a', 93ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 8, 0, 0, 0, // size of payload: 8 94ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 0, 0, // first sample: 0.0 95ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 10, 0, // second sample: 10.0 96ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 0xff, 0x7f, // third sample: 4e4 (saturated) 97ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 0, 0x80, // fourth sample: -1e9 (saturated) 98ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org }; 99ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org static const int kContentSize = 100ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org webrtc::kWavHeaderSize + kNumSamples * sizeof(int16_t); 101ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org COMPILE_ASSERT(sizeof(kExpectedContents) == kContentSize, content_size); 102ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org EXPECT_EQ(size_t(kContentSize), webrtc::test::GetFileSize(outfile)); 103ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org FILE* f = fopen(outfile.c_str(), "rb"); 104ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org ASSERT_TRUE(f); 105ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org uint8_t contents[kContentSize]; 106ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org ASSERT_EQ(1u, fread(contents, kContentSize, 1, f)); 107ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org EXPECT_EQ(0, fclose(f)); 108ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org EXPECT_EQ(0, memcmp(kExpectedContents, contents, kContentSize)); 109ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org} 110ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org 111ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org// Write a larger WAV file. You can listen to this file to sanity-check it. 112ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.orgTEST(WavWriterTest, LargeFile) { 113ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org std::string outfile = webrtc::test::OutputPath() + "wavtest3.wav"; 114ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org static const int kSampleRate = 8000; 115ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org static const int kNumChannels = 2; 116999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org static const uint32_t kNumSamples = 3 * kSampleRate * kNumChannels; 117ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org float samples[kNumSamples]; 118999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org for (uint32_t i = 0; i < kNumSamples; i += kNumChannels) { 119ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org // A nice periodic beeping sound. 120ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org static const double kToneHz = 440; 121ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org const double t = static_cast<double>(i) / (kNumChannels * kSampleRate); 122ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org const double x = 123ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org std::numeric_limits<int16_t>::max() * std::sin(t * kToneHz * 2 * M_PI); 124ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org samples[i] = std::pow(std::sin(t * 2 * 2 * M_PI), 10) * x; 125ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org samples[i + 1] = std::pow(std::cos(t * 2 * 2 * M_PI), 10) * x; 126ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org } 127ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org { 128ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org webrtc::WavFile w(outfile, kSampleRate, kNumChannels); 129999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(kSampleRate, w.sample_rate()); 130999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(kNumChannels, w.num_channels()); 131999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(0u, w.num_samples()); 132ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org w.WriteSamples(samples, kNumSamples); 133999bcbc7588ed449b0ee6db29aeb79f72007488bkwiberg@webrtc.org EXPECT_EQ(kNumSamples, w.num_samples()); 134ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org } 135ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org EXPECT_EQ(sizeof(int16_t) * kNumSamples + webrtc::kWavHeaderSize, 136ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org webrtc::test::GetFileSize(outfile)); 137ddd80b5eacf50958c4335eb5a535e07aa8b05369kwiberg@webrtc.org} 138