Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / common_audio / wav_writer.cc
1 /*
2  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11 #include "webrtc/common_audio/wav_writer.h"
12
13 #include <algorithm>
14 #include <cstdio>
15 #include <limits>
16
17 #include "webrtc/base/checks.h"
18 #include "webrtc/common_audio/include/audio_util.h"
19 #include "webrtc/common_audio/wav_header.h"
20
21 namespace webrtc {
22
23 // We write 16-bit PCM WAV files.
24 static const WavFormat kWavFormat = kWavFormatPcm;
25 static const int kBytesPerSample = 2;
26
27 WavFile::WavFile(const std::string& filename, int sample_rate, int num_channels)
28     : sample_rate_(sample_rate),
29       num_channels_(num_channels),
30       num_samples_(0),
31       file_handle_(fopen(filename.c_str(), "wb")) {
32   CHECK(file_handle_);
33   CHECK(CheckWavParameters(num_channels_,
34                            sample_rate_,
35                            kWavFormat,
36                            kBytesPerSample,
37                            num_samples_));
38
39   // Write a blank placeholder header, since we need to know the total number
40   // of samples before we can fill in the real data.
41   static const uint8_t blank_header[kWavHeaderSize] = {0};
42   CHECK_EQ(1u, fwrite(blank_header, kWavHeaderSize, 1, file_handle_));
43 }
44
45 WavFile::~WavFile() {
46   Close();
47 }
48
49 void WavFile::WriteSamples(const int16_t* samples, size_t num_samples) {
50 #ifndef WEBRTC_ARCH_LITTLE_ENDIAN
51 #error "Need to convert samples to little-endian when writing to WAV file"
52 #endif
53   const size_t written =
54       fwrite(samples, sizeof(*samples), num_samples, file_handle_);
55   CHECK_EQ(num_samples, written);
56   num_samples_ += static_cast<uint32_t>(written);
57   CHECK(written <= std::numeric_limits<uint32_t>::max() ||
58         num_samples_ >= written);  // detect uint32_t overflow
59   CHECK(CheckWavParameters(num_channels_,
60                            sample_rate_,
61                            kWavFormat,
62                            kBytesPerSample,
63                            num_samples_));
64 }
65
66 void WavFile::WriteSamples(const float* samples, size_t num_samples) {
67   static const size_t kChunksize = 4096 / sizeof(uint16_t);
68   for (size_t i = 0; i < num_samples; i += kChunksize) {
69     int16_t isamples[kChunksize];
70     const size_t chunk = std::min(kChunksize, num_samples - i);
71     RoundToInt16(samples + i, chunk, isamples);
72     WriteSamples(isamples, chunk);
73   }
74 }
75
76 void WavFile::Close() {
77   CHECK_EQ(0, fseek(file_handle_, 0, SEEK_SET));
78   uint8_t header[kWavHeaderSize];
79   WriteWavHeader(header, num_channels_, sample_rate_, kWavFormat,
80                  kBytesPerSample, num_samples_);
81   CHECK_EQ(1u, fwrite(header, kWavHeaderSize, 1, file_handle_));
82   CHECK_EQ(0, fclose(file_handle_));
83   file_handle_ = NULL;
84 }
85
86 }  // namespace webrtc
87
88 rtc_WavFile* rtc_WavOpen(const char* filename,
89                          int sample_rate,
90                          int num_channels) {
91   return reinterpret_cast<rtc_WavFile*>(
92       new webrtc::WavFile(filename, sample_rate, num_channels));
93 }
94
95 void rtc_WavClose(rtc_WavFile* wf) {
96   delete reinterpret_cast<webrtc::WavFile*>(wf);
97 }
98
99 void rtc_WavWriteSamples(rtc_WavFile* wf,
100                          const float* samples,
101                          size_t num_samples) {
102   reinterpret_cast<webrtc::WavFile*>(wf)->WriteSamples(samples, num_samples);
103 }
104
105 int rtc_WavSampleRate(const rtc_WavFile* wf) {
106   return reinterpret_cast<const webrtc::WavFile*>(wf)->sample_rate();
107 }
108
109 int rtc_WavNumChannels(const rtc_WavFile* wf) {
110   return reinterpret_cast<const webrtc::WavFile*>(wf)->num_channels();
111 }
112
113 uint32_t rtc_WavNumSamples(const rtc_WavFile* wf) {
114   return reinterpret_cast<const webrtc::WavFile*>(wf)->num_samples();
115 }