LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/common_audio - wav_file.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 102 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 29 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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_file.h"
      12             : 
      13             : #include <algorithm>
      14             : #include <cstdio>
      15             : #include <limits>
      16             : #include <sstream>
      17             : 
      18             : #include "webrtc/base/checks.h"
      19             : #include "webrtc/base/safe_conversions.h"
      20             : #include "webrtc/common_audio/include/audio_util.h"
      21             : #include "webrtc/common_audio/wav_header.h"
      22             : 
      23             : namespace webrtc {
      24             : 
      25             : // We write 16-bit PCM WAV files.
      26             : static const WavFormat kWavFormat = kWavFormatPcm;
      27             : static const size_t kBytesPerSample = 2;
      28             : 
      29             : // Doesn't take ownership of the file handle and won't close it.
      30           0 : class ReadableWavFile : public ReadableWav {
      31             :  public:
      32           0 :   explicit ReadableWavFile(FILE* file) : file_(file) {}
      33           0 :   virtual size_t Read(void* buf, size_t num_bytes) {
      34           0 :     return fread(buf, 1, num_bytes, file_);
      35             :   }
      36             : 
      37             :  private:
      38             :   FILE* file_;
      39             : };
      40             : 
      41           0 : std::string WavFile::FormatAsString() const {
      42           0 :   std::ostringstream s;
      43           0 :   s << "Sample rate: " << sample_rate() << " Hz, Channels: " << num_channels()
      44           0 :     << ", Duration: "
      45           0 :     << (1.f * num_samples()) / (num_channels() * sample_rate()) << " s";
      46           0 :   return s.str();
      47             : }
      48             : 
      49           0 : WavReader::WavReader(const std::string& filename)
      50           0 :     : file_handle_(fopen(filename.c_str(), "rb")) {
      51           0 :   RTC_CHECK(file_handle_) << "Could not open wav file for reading.";
      52             : 
      53           0 :   ReadableWavFile readable(file_handle_);
      54             :   WavFormat format;
      55             :   size_t bytes_per_sample;
      56           0 :   RTC_CHECK(ReadWavHeader(&readable, &num_channels_, &sample_rate_, &format,
      57           0 :                           &bytes_per_sample, &num_samples_));
      58           0 :   num_samples_remaining_ = num_samples_;
      59           0 :   RTC_CHECK_EQ(kWavFormat, format);
      60           0 :   RTC_CHECK_EQ(kBytesPerSample, bytes_per_sample);
      61           0 : }
      62             : 
      63           0 : WavReader::~WavReader() {
      64           0 :   Close();
      65           0 : }
      66             : 
      67           0 : int WavReader::sample_rate() const {
      68           0 :   return sample_rate_;
      69             : }
      70             : 
      71           0 : size_t WavReader::num_channels() const {
      72           0 :   return num_channels_;
      73             : }
      74             : 
      75           0 : size_t WavReader::num_samples() const {
      76           0 :   return num_samples_;
      77             : }
      78             : 
      79           0 : size_t WavReader::ReadSamples(size_t num_samples, int16_t* samples) {
      80             :   // There could be metadata after the audio; ensure we don't read it.
      81           0 :   num_samples = std::min(num_samples, num_samples_remaining_);
      82             :   const size_t read =
      83           0 :       fread(samples, sizeof(*samples), num_samples, file_handle_);
      84             :   // If we didn't read what was requested, ensure we've reached the EOF.
      85           0 :   RTC_CHECK(read == num_samples || feof(file_handle_));
      86           0 :   RTC_CHECK_LE(read, num_samples_remaining_);
      87           0 :   num_samples_remaining_ -= read;
      88             : #ifndef WEBRTC_ARCH_LITTLE_ENDIAN
      89             :   //convert to big-endian
      90             :   for (size_t idx = 0; idx < num_samples; idx++) {
      91             :     samples[idx] = (samples[idx]<<8) | (samples[idx]>>8);
      92             :   }
      93             : #endif
      94           0 :   return read;
      95             : }
      96             : 
      97           0 : size_t WavReader::ReadSamples(size_t num_samples, float* samples) {
      98             :   static const size_t kChunksize = 4096 / sizeof(uint16_t);
      99           0 :   size_t read = 0;
     100           0 :   for (size_t i = 0; i < num_samples; i += kChunksize) {
     101             :     int16_t isamples[kChunksize];
     102           0 :     size_t chunk = std::min(kChunksize, num_samples - i);
     103           0 :     chunk = ReadSamples(chunk, isamples);
     104           0 :     for (size_t j = 0; j < chunk; ++j)
     105           0 :       samples[i + j] = isamples[j];
     106           0 :     read += chunk;
     107             :   }
     108           0 :   return read;
     109             : }
     110             : 
     111           0 : void WavReader::Close() {
     112           0 :   RTC_CHECK_EQ(0, fclose(file_handle_));
     113           0 :   file_handle_ = NULL;
     114           0 : }
     115             : 
     116           0 : WavWriter::WavWriter(const std::string& filename, int sample_rate,
     117           0 :                      size_t num_channels)
     118             :     : sample_rate_(sample_rate),
     119             :       num_channels_(num_channels),
     120             :       num_samples_(0),
     121           0 :       file_handle_(fopen(filename.c_str(), "wb")) {
     122           0 :   if (file_handle_) {
     123           0 :     RTC_CHECK(CheckWavParameters(num_channels_, sample_rate_, kWavFormat,
     124           0 :                                  kBytesPerSample, num_samples_));
     125             : 
     126             :     // Write a blank placeholder header, since we need to know the total number
     127             :     // of samples before we can fill in the real data.
     128             :     static const uint8_t blank_header[kWavHeaderSize] = {0};
     129           0 :     RTC_CHECK_EQ(1, fwrite(blank_header, kWavHeaderSize, 1, file_handle_));
     130             :   }
     131           0 : }
     132             : 
     133           0 : WavWriter::~WavWriter() {
     134           0 :   Close();
     135           0 : }
     136             : 
     137           0 : int WavWriter::sample_rate() const {
     138           0 :   return sample_rate_;
     139             : }
     140             : 
     141           0 : size_t WavWriter::num_channels() const {
     142           0 :   return num_channels_;
     143             : }
     144             : 
     145           0 : size_t WavWriter::num_samples() const {
     146           0 :   return num_samples_;
     147             : }
     148             : 
     149           0 : void WavWriter::WriteSamples(const int16_t* samples, size_t num_samples) {
     150           0 :   if (!file_handle_) {
     151           0 :     return;
     152             :   }
     153             : #ifndef WEBRTC_ARCH_LITTLE_ENDIAN
     154             :   int16_t * le_samples = new int16_t[num_samples];
     155             :   for(size_t idx = 0; idx < num_samples; idx++) {
     156             :     le_samples[idx] = (samples[idx]<<8) | (samples[idx]>>8);
     157             :   }
     158             :   const size_t written =
     159             :       fwrite(le_samples, sizeof(*le_samples), num_samples, file_handle_);
     160             :   delete []le_samples;
     161             : #else
     162             :   const size_t written =
     163           0 :       fwrite(samples, sizeof(*samples), num_samples, file_handle_);
     164             : #endif
     165           0 :   RTC_CHECK_EQ(num_samples, written);
     166           0 :   num_samples_ += written;
     167           0 :   RTC_CHECK(num_samples_ >= written);  // detect size_t overflow
     168             : }
     169             : 
     170           0 : void WavWriter::WriteSamples(const float* samples, size_t num_samples) {
     171             :   static const size_t kChunksize = 4096 / sizeof(uint16_t);
     172           0 :   for (size_t i = 0; i < num_samples; i += kChunksize) {
     173             :     int16_t isamples[kChunksize];
     174           0 :     const size_t chunk = std::min(kChunksize, num_samples - i);
     175           0 :     FloatS16ToS16(samples + i, chunk, isamples);
     176           0 :     WriteSamples(isamples, chunk);
     177             :   }
     178           0 : }
     179             : 
     180           0 : void WavWriter::Close() {
     181           0 :   if (!file_handle_) {
     182           0 :     return;
     183             :   }
     184           0 :   RTC_CHECK_EQ(0, fseek(file_handle_, 0, SEEK_SET));
     185             :   uint8_t header[kWavHeaderSize];
     186           0 :   WriteWavHeader(header, num_channels_, sample_rate_, kWavFormat,
     187           0 :                  kBytesPerSample, num_samples_);
     188           0 :   RTC_CHECK_EQ(1, fwrite(header, kWavHeaderSize, 1, file_handle_));
     189           0 :   RTC_CHECK_EQ(0, fclose(file_handle_));
     190           0 :   file_handle_ = NULL;
     191             : }
     192             : 
     193             : }  // namespace webrtc
     194             : 
     195           0 : rtc_WavWriter* rtc_WavOpen(const char* filename,
     196             :                            int sample_rate,
     197             :                            size_t num_channels) {
     198             :   return reinterpret_cast<rtc_WavWriter*>(
     199           0 :       new webrtc::WavWriter(filename, sample_rate, num_channels));
     200             : }
     201             : 
     202           0 : void rtc_WavClose(rtc_WavWriter* wf) {
     203           0 :   delete reinterpret_cast<webrtc::WavWriter*>(wf);
     204           0 : }
     205             : 
     206           0 : void rtc_WavWriteSamples(rtc_WavWriter* wf,
     207             :                          const float* samples,
     208             :                          size_t num_samples) {
     209           0 :   reinterpret_cast<webrtc::WavWriter*>(wf)->WriteSamples(samples, num_samples);
     210           0 : }
     211             : 
     212           0 : int rtc_WavSampleRate(const rtc_WavWriter* wf) {
     213           0 :   return reinterpret_cast<const webrtc::WavWriter*>(wf)->sample_rate();
     214             : }
     215             : 
     216           0 : size_t rtc_WavNumChannels(const rtc_WavWriter* wf) {
     217           0 :   return reinterpret_cast<const webrtc::WavWriter*>(wf)->num_channels();
     218             : }
     219             : 
     220           0 : size_t rtc_WavNumSamples(const rtc_WavWriter* wf) {
     221           0 :   return reinterpret_cast<const webrtc::WavWriter*>(wf)->num_samples();
     222             : }

Generated by: LCOV version 1.13