1e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org/* 2e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org * 4e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org */ 10e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org 1129841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org#include <limits> 1229841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org 13b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org#include "webrtc/audio_processing/debug.pb.h" 1429841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org#include "webrtc/common_audio/include/audio_util.h" 1529841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org#include "webrtc/common_audio/wav_writer.h" 16467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org#include "webrtc/modules/audio_processing/common.h" 17e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org#include "webrtc/modules/audio_processing/include/audio_processing.h" 18e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org#include "webrtc/modules/interface/module_common_types.h" 19b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org#include "webrtc/system_wrappers/interface/scoped_ptr.h" 20b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org 21b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.orgnamespace webrtc { 22b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org 23b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.orgstatic const AudioProcessing::Error kNoErr = AudioProcessing::kNoError; 24b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org#define EXPECT_NOERR(expr) EXPECT_EQ(kNoErr, (expr)) 25e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org 2629841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.orgclass RawFile { 2729841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org public: 2829841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org RawFile(const std::string& filename) 2929841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org : file_handle_(fopen(filename.c_str(), "wb")) {} 3029841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org 3129841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org ~RawFile() { 3229841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org fclose(file_handle_); 3329841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org } 3429841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org 3529841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org void WriteSamples(const int16_t* samples, size_t num_samples) { 3629841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org#ifndef WEBRTC_ARCH_LITTLE_ENDIAN 3729841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org#error "Need to convert samples to little-endian when writing to PCM file" 3829841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org#endif 3929841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org fwrite(samples, sizeof(*samples), num_samples, file_handle_); 4029841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org } 4129841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org 4229841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org void WriteSamples(const float* samples, size_t num_samples) { 4329841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org fwrite(samples, sizeof(*samples), num_samples, file_handle_); 4429841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org } 4529841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org 4629841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org private: 4729841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org FILE* file_handle_; 4829841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org}; 4929841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org 5029841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.orgstatic inline void WriteIntData(const int16_t* data, 5129841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org size_t length, 5229841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org WavFile* wav_file, 5329841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org RawFile* raw_file) { 5429841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org if (wav_file) { 5529841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org wav_file->WriteSamples(data, length); 5629841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org } 5729841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org if (raw_file) { 5829841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org raw_file->WriteSamples(data, length); 5929841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org } 6029841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org} 6129841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org 6229841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.orgstatic inline void WriteFloatData(const float* const* data, 6329841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org size_t samples_per_channel, 6429841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org int num_channels, 6529841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org WavFile* wav_file, 6629841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org RawFile* raw_file) { 6729841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org size_t length = num_channels * samples_per_channel; 6829841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org scoped_ptr<float[]> buffer(new float[length]); 6929841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org Interleave(data, samples_per_channel, num_channels, buffer.get()); 7029841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org if (raw_file) { 7129841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org raw_file->WriteSamples(buffer.get(), length); 7229841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org } 7329841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org // TODO(aluebs): Use ScaleToInt16Range() from audio_util 7429841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org for (size_t i = 0; i < length; ++i) { 7529841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org buffer[i] = buffer[i] > 0 ? 7629841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org buffer[i] * std::numeric_limits<int16_t>::max() : 7729841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org -buffer[i] * std::numeric_limits<int16_t>::min(); 7829841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org } 7929841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org if (wav_file) { 8029841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org wav_file->WriteSamples(buffer.get(), length); 8129841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org } 8229841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org} 8329841cb8d3a1101cc878debdbc481cee63e75a19aluebs@webrtc.org 84b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org// Exits on failure; do not use in unit tests. 85b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.orgstatic inline FILE* OpenFile(const std::string& filename, const char* mode) { 86b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org FILE* file = fopen(filename.c_str(), mode); 87b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org if (!file) { 88b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org printf("Unable to open file %s\n", filename.c_str()); 89b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org exit(1); 90b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org } 91b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org return file; 92b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org} 93b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org 94467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.orgstatic inline int SamplesFromRate(int rate) { 95467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org return AudioProcessing::kChunkSizeMs * rate / 1000; 96467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org} 97467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org 98b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.orgstatic inline void SetFrameSampleRate(AudioFrame* frame, 99b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org int sample_rate_hz) { 100e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org frame->sample_rate_hz_ = sample_rate_hz; 101467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org frame->samples_per_channel_ = AudioProcessing::kChunkSizeMs * 102467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org sample_rate_hz / 1000; 103e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org} 104b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org 105b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.orgtemplate <typename T> 106b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.orgvoid SetContainerFormat(int sample_rate_hz, 107b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org int num_channels, 108b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org AudioFrame* frame, 109b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org scoped_ptr<ChannelBuffer<T> >* cb) { 110b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org SetFrameSampleRate(frame, sample_rate_hz); 111b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org frame->num_channels_ = num_channels; 112b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org cb->reset(new ChannelBuffer<T>(frame->samples_per_channel_, num_channels)); 113b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org} 114b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org 115b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.orgstatic inline AudioProcessing::ChannelLayout LayoutFromChannels( 116b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org int num_channels) { 117b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org switch (num_channels) { 118b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org case 1: 119b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org return AudioProcessing::kMono; 120b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org case 2: 121b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org return AudioProcessing::kStereo; 122b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org default: 123b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org assert(false); 124b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org return AudioProcessing::kMono; 125b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org } 126b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org} 127b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org 128b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org// Allocates new memory in the scoped_ptr to fit the raw message and returns the 129b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org// number of bytes read. 130b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.orgstatic inline size_t ReadMessageBytesFromFile(FILE* file, 131b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org scoped_ptr<uint8_t[]>* bytes) { 132b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org // The "wire format" for the size is little-endian. Assume we're running on 133b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org // a little-endian machine. 134b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org int32_t size = 0; 135b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org if (fread(&size, sizeof(size), 1, file) != 1) 136b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org return 0; 137b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org if (size <= 0) 138b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org return 0; 139b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org 140b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org bytes->reset(new uint8_t[size]); 141b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org return fread(bytes->get(), sizeof((*bytes)[0]), size, file); 142b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org} 143b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org 144b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org// Returns true on success, false on error or end-of-file. 145b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.orgstatic inline bool ReadMessageFromFile(FILE* file, 146b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org ::google::protobuf::MessageLite* msg) { 147b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org scoped_ptr<uint8_t[]> bytes; 148b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org size_t size = ReadMessageBytesFromFile(file, &bytes); 149b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org if (!size) 150b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org return false; 151b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org 152b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org msg->Clear(); 153b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org return msg->ParseFromArray(bytes.get(), size); 154b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org} 155b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org 156b5b49c0723428d30e68bc8edcc089049a29e0703andrew@webrtc.org} // namespace webrtc 157