Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
Index: webrtc/common_audio/wav_file.cc
===================================================================
--- webrtc/common_audio/wav_file.cc	(nonexistent)
+++ webrtc/common_audio/wav_file.cc	(revision 62)
@@ -0,0 +1,192 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/common_audio/wav_file.h"
+
+#include <algorithm>
+#include <cstdio>
+#include <limits>
+
+#include "webrtc/base/checks.h"
+#include "webrtc/base/safe_conversions.h"
+#include "webrtc/common_audio/include/audio_util.h"
+#include "webrtc/common_audio/wav_header.h"
+
+namespace webrtc {
+
+// We write 16-bit PCM WAV files.
+static const WavFormat kWavFormat = kWavFormatPcm;
+static const int kBytesPerSample = 2;
+
+// Doesn't take ownership of the file handle and won't close it.
+class ReadableWavFile : public ReadableWav {
+ public:
+  explicit ReadableWavFile(FILE* file) : file_(file) {}
+  virtual size_t Read(void* buf, size_t num_bytes) {
+    return fread(buf, 1, num_bytes, file_);
+  }
+
+ private:
+  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.";
+
+  ReadableWavFile readable(file_handle_);
+  WavFormat format;
+  int bytes_per_sample;
+  RTC_CHECK(ReadWavHeader(&readable, &num_channels_, &sample_rate_, &format,
+                          &bytes_per_sample, &num_samples_));
+  num_samples_remaining_ = num_samples_;
+  RTC_CHECK_EQ(kWavFormat, format);
+  RTC_CHECK_EQ(kBytesPerSample, bytes_per_sample);
+}
+
+WavReader::~WavReader() {
+  Close();
+}
+
+size_t WavReader::ReadSamples(size_t num_samples, int16_t* samples) {
+  // 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_);
+  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);
+#ifndef WEBRTC_ARCH_LITTLE_ENDIAN
+  //convert to big-endian
+  for(size_t idx = 0; idx < num_samples; idx++) {
+    samples[idx] = (samples[idx]<<8) | (samples[idx]>>8);
+  }
+#endif
+  return read;
+}
+
+size_t WavReader::ReadSamples(size_t num_samples, float* samples) {
+  static const size_t kChunksize = 4096 / sizeof(uint16_t);
+  size_t read = 0;
+  for (size_t i = 0; i < num_samples; i += kChunksize) {
+    int16_t isamples[kChunksize];
+    size_t chunk = std::min(kChunksize, num_samples - i);
+    chunk = ReadSamples(chunk, isamples);
+    for (size_t j = 0; j < chunk; ++j)
+      samples[i + j] = isamples[j];
+    read += chunk;
+  }
+  return read;
+}
+
+void WavReader::Close() {
+  RTC_CHECK_EQ(0, fclose(file_handle_));
+  file_handle_ = NULL;
+}
+
+WavWriter::WavWriter(const std::string& filename, int sample_rate,
+                     int 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(CheckWavParameters(num_channels_, sample_rate_, kWavFormat,
+                               kBytesPerSample, num_samples_));
+
+  // Write a blank placeholder header, since we need to know the total number
+  // of samples before we can fill in the real data.
+  static const uint8_t blank_header[kWavHeaderSize] = {0};
+  RTC_CHECK_EQ(1u, fwrite(blank_header, kWavHeaderSize, 1, file_handle_));
+}
+
+WavWriter::~WavWriter() {
+  Close();
+}
+
+void WavWriter::WriteSamples(const int16_t* samples, size_t num_samples) {
+#ifndef WEBRTC_ARCH_LITTLE_ENDIAN
+  int16_t * le_samples = new int16_t[num_samples];
+  for(size_t idx = 0; idx < num_samples; idx++) {
+    le_samples[idx] = (samples[idx]<<8) | (samples[idx]>>8);
+  }
+  const size_t written =
+      fwrite(le_samples, sizeof(*le_samples), num_samples, file_handle_);
+  delete []le_samples;
+#else
+  const size_t written =
+      fwrite(samples, sizeof(*samples), num_samples, file_handle_);
+#endif
+  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
+}
+
+void WavWriter::WriteSamples(const float* samples, size_t num_samples) {
+  static const size_t kChunksize = 4096 / sizeof(uint16_t);
+  for (size_t i = 0; i < num_samples; i += kChunksize) {
+    int16_t isamples[kChunksize];
+    const size_t chunk = std::min(kChunksize, num_samples - i);
+    FloatS16ToS16(samples + i, chunk, isamples);
+    WriteSamples(isamples, chunk);
+  }
+}
+
+void WavWriter::Close() {
+  RTC_CHECK_EQ(0, fseek(file_handle_, 0, SEEK_SET));
+  uint8_t header[kWavHeaderSize];
+  WriteWavHeader(header, num_channels_, sample_rate_, kWavFormat,
+                 kBytesPerSample, num_samples_);
+  RTC_CHECK_EQ(1u, fwrite(header, kWavHeaderSize, 1, file_handle_));
+  RTC_CHECK_EQ(0, fclose(file_handle_));
+  file_handle_ = NULL;
+}
+
+}  // namespace webrtc
+
+rtc_WavWriter* rtc_WavOpen(const char* filename,
+                           int sample_rate,
+                           int num_channels) {
+  return reinterpret_cast<rtc_WavWriter*>(
+      new webrtc::WavWriter(filename, sample_rate, num_channels));
+}
+
+void rtc_WavClose(rtc_WavWriter* wf) {
+  delete reinterpret_cast<webrtc::WavWriter*>(wf);
+}
+
+void rtc_WavWriteSamples(rtc_WavWriter* wf,
+                         const float* samples,
+                         size_t num_samples) {
+  reinterpret_cast<webrtc::WavWriter*>(wf)->WriteSamples(samples, num_samples);
+}
+
+int rtc_WavSampleRate(const rtc_WavWriter* wf) {
+  return reinterpret_cast<const webrtc::WavWriter*>(wf)->sample_rate();
+}
+
+int rtc_WavNumChannels(const rtc_WavWriter* wf) {
+  return reinterpret_cast<const webrtc::WavWriter*>(wf)->num_channels();
+}
+
+uint32_t rtc_WavNumSamples(const rtc_WavWriter* wf) {
+  return reinterpret_cast<const webrtc::WavWriter*>(wf)->num_samples();
+}
Index: webrtc/common_audio/wav_header.cc
===================================================================
--- webrtc/common_audio/wav_header.cc	(nonexistent)
+++ webrtc/common_audio/wav_header.cc	(revision 62)
@@ -0,0 +1,274 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+// Based on the WAV file format documentation at
+// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ and
+// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
+
+#include "webrtc/common_audio/wav_header.h"
+
+#include <algorithm>
+#include <cstring>
+#include <limits>
+#include <string>
+
+#include "webrtc/base/checks.h"
+#include "webrtc/common_audio/include/audio_util.h"
+
+namespace webrtc {
+namespace {
+
+struct ChunkHeader {
+  uint32_t ID;
+  uint32_t Size;
+};
+static_assert(sizeof(ChunkHeader) == 8, "ChunkHeader size");
+
+// We can't nest this definition in WavHeader, because VS2013 gives an error
+// on sizeof(WavHeader::fmt): "error C2070: 'unknown': illegal sizeof operand".
+struct FmtSubchunk {
+  ChunkHeader header;
+  uint16_t AudioFormat;
+  uint16_t NumChannels;
+  uint32_t SampleRate;
+  uint32_t ByteRate;
+  uint16_t BlockAlign;
+  uint16_t BitsPerSample;
+};
+static_assert(sizeof(FmtSubchunk) == 24, "FmtSubchunk size");
+const uint32_t kFmtSubchunkSize = sizeof(FmtSubchunk) - sizeof(ChunkHeader);
+
+struct WavHeader {
+  struct {
+    ChunkHeader header;
+    uint32_t Format;
+  } riff;
+  FmtSubchunk fmt;
+  struct {
+    ChunkHeader header;
+  } data;
+};
+static_assert(sizeof(WavHeader) == kWavHeaderSize, "no padding in header");
+
+}  // namespace
+
+bool CheckWavParameters(int num_channels,
+                        int sample_rate,
+                        WavFormat format,
+                        int bytes_per_sample,
+                        uint32_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)
+    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())
+    return false;
+  if (static_cast<uint64_t>(bytes_per_sample) * 8 >
+      std::numeric_limits<uint16_t>::max())
+    return false;
+  if (static_cast<uint64_t>(sample_rate) * num_channels * bytes_per_sample >
+      std::numeric_limits<uint32_t>::max())
+    return false;
+
+  // format and bytes_per_sample must agree.
+  switch (format) {
+    case kWavFormatPcm:
+      // Other values may be OK, but for now we're conservative:
+      if (bytes_per_sample != 1 && bytes_per_sample != 2)
+        return false;
+      break;
+    case kWavFormatALaw:
+    case kWavFormatMuLaw:
+      if (bytes_per_sample != 1)
+        return false;
+      break;
+    default:
+      return false;
+  }
+
+  // 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;
+  if (num_samples > max_samples)
+    return false;
+
+  // Each channel must have the same number of samples.
+  if (num_samples % num_channels != 0)
+    return false;
+
+  return true;
+}
+
+#ifdef WEBRTC_ARCH_LITTLE_ENDIAN
+static inline void WriteLE16(uint16_t* f, uint16_t x) { *f = x; }
+static inline void WriteLE32(uint32_t* f, uint32_t x) { *f = x; }
+static inline void WriteFourCC(uint32_t* f, char a, char b, char c, char d) {
+  *f = static_cast<uint32_t>(a)
+      | static_cast<uint32_t>(b) << 8
+      | static_cast<uint32_t>(c) << 16
+      | static_cast<uint32_t>(d) << 24;
+}
+
+static inline uint16_t ReadLE16(uint16_t x) { return x; }
+static inline uint32_t ReadLE32(uint32_t x) { return x; }
+static inline std::string ReadFourCC(uint32_t x) {
+  return std::string(reinterpret_cast<char*>(&x), 4);
+}
+#else
+static inline void WriteLE16(uint16_t* f, uint16_t x) {
+  *f = ((x << 8) & 0xff00)  | ( ( x >> 8) & 0x00ff);
+}
+
+static inline void WriteLE32(uint32_t* f, uint32_t x) {
+    *f = ( (x & 0x000000ff) << 24 )
+      | ((x & 0x0000ff00) << 8)
+      | ((x & 0x00ff0000) >> 8)
+      | ((x & 0xff000000) >> 24 );
+}
+
+static inline void WriteFourCC(uint32_t* f, char a, char b, char c, char d) {
+    *f = (static_cast<uint32_t>(a) << 24 )
+      |  (static_cast<uint32_t>(b) << 16)
+      |  (static_cast<uint32_t>(c) << 8)
+      |  (static_cast<uint32_t>(d) );
+}
+
+static inline uint16_t ReadLE16(uint16_t x) {
+  return  (( x & 0x00ff) << 8 )| ((x & 0xff00)>>8);
+}
+
+static inline uint32_t ReadLE32(uint32_t x) {
+  return   ( (x & 0x000000ff) << 24 )
+         | ( (x & 0x0000ff00) << 8 )
+         | ( (x & 0x00ff0000) >> 8)
+         | ( (x & 0xff000000) >> 24 );
+}
+
+static inline std::string ReadFourCC(uint32_t x) {
+  x = ReadLE32(x);
+  return std::string(reinterpret_cast<char*>(&x), 4);
+}
+#endif
+
+static inline uint32_t RiffChunkSize(uint32_t bytes_in_payload) {
+  return 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 uint16_t BlockAlign(int num_channels, int bytes_per_sample) {
+  return num_channels * bytes_per_sample;
+}
+
+void WriteWavHeader(uint8_t* buf,
+                    int num_channels,
+                    int sample_rate,
+                    WavFormat format,
+                    int bytes_per_sample,
+                    uint32_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;
+
+  WriteFourCC(&header.riff.header.ID, 'R', 'I', 'F', 'F');
+  WriteLE32(&header.riff.header.Size, RiffChunkSize(bytes_in_payload));
+  WriteFourCC(&header.riff.Format, 'W', 'A', 'V', 'E');
+
+  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);
+  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);
+
+  WriteFourCC(&header.data.header.ID, 'd', 'a', 't', 'a');
+  WriteLE32(&header.data.header.Size, bytes_in_payload);
+
+  // Do an extra copy rather than writing everything to buf directly, since buf
+  // might not be correctly aligned.
+  memcpy(buf, &header, kWavHeaderSize);
+}
+
+bool ReadWavHeader(ReadableWav* readable,
+                   int* num_channels,
+                   int* sample_rate,
+                   WavFormat* format,
+                   int* bytes_per_sample,
+                   uint32_t* num_samples) {
+  WavHeader header;
+  if (readable->Read(&header, kWavHeaderSize - sizeof(header.data)) !=
+      kWavHeaderSize - sizeof(header.data))
+    return false;
+
+  const uint32_t fmt_size = ReadLE32(header.fmt.header.Size);
+  if (fmt_size != kFmtSubchunkSize) {
+    // There is an optional two-byte extension field permitted to be present
+    // with PCM, but which must be zero.
+    int16_t ext_size;
+    if (kFmtSubchunkSize + sizeof(ext_size) != fmt_size)
+      return false;
+    if (readable->Read(&ext_size, sizeof(ext_size)) != sizeof(ext_size))
+      return false;
+    if (ext_size != 0)
+      return false;
+  }
+  if (readable->Read(&header.data, sizeof(header.data)) != sizeof(header.data))
+    return false;
+
+  // Parse needed fields.
+  *format = static_cast<WavFormat>(ReadLE16(header.fmt.AudioFormat));
+  *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)
+    return false;
+  *num_samples = bytes_in_payload / *bytes_per_sample;
+
+  // Sanity check remaining fields.
+  if (ReadFourCC(header.riff.header.ID) != "RIFF")
+    return false;
+  if (ReadFourCC(header.riff.Format) != "WAVE")
+    return false;
+  if (ReadFourCC(header.fmt.header.ID) != "fmt ")
+    return false;
+  if (ReadFourCC(header.data.header.ID) != "data")
+    return false;
+
+  if (ReadLE32(header.riff.header.Size) < RiffChunkSize(bytes_in_payload))
+    return false;
+  if (ReadLE32(header.fmt.ByteRate) !=
+      ByteRate(*num_channels, *sample_rate, *bytes_per_sample))
+    return false;
+  if (ReadLE16(header.fmt.BlockAlign) !=
+      BlockAlign(*num_channels, *bytes_per_sample))
+    return false;
+
+  return CheckWavParameters(*num_channels, *sample_rate, *format,
+                            *bytes_per_sample, *num_samples);
+}
+
+
+}  // namespace webrtc