You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			206 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
			
		
		
	
	
			206 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
| /*
 | |
|  *  Copyright (c) 2012 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 "PCMFile.h"
 | |
| 
 | |
| #include <ctype.h>
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #include "gtest/gtest.h"
 | |
| #include "module_common_types.h"
 | |
| 
 | |
| namespace webrtc {
 | |
| 
 | |
| #define MAX_FILE_NAME_LENGTH_BYTE 500
 | |
| 
 | |
| PCMFile::PCMFile()
 | |
|     : pcm_file_(NULL),
 | |
|       samples_10ms_(160),
 | |
|       frequency_(16000),
 | |
|       end_of_file_(false),
 | |
|       auto_rewind_(false),
 | |
|       rewinded_(false),
 | |
|       read_stereo_(false),
 | |
|       save_stereo_(false) {
 | |
|   timestamp_ = (((uint32_t) rand() & 0x0000FFFF) << 16) |
 | |
|       ((uint32_t) rand() & 0x0000FFFF);
 | |
| }
 | |
| 
 | |
| PCMFile::PCMFile(uint32_t timestamp)
 | |
|     : pcm_file_(NULL),
 | |
|       samples_10ms_(160),
 | |
|       frequency_(16000),
 | |
|       end_of_file_(false),
 | |
|       auto_rewind_(false),
 | |
|       rewinded_(false),
 | |
|       read_stereo_(false),
 | |
|       save_stereo_(false) {
 | |
|   timestamp_ = timestamp;
 | |
| }
 | |
| 
 | |
| int16_t PCMFile::ChooseFile(std::string* file_name, int16_t max_len,
 | |
|                             uint16_t* frequency_hz) {
 | |
|   char tmp_name[MAX_FILE_NAME_LENGTH_BYTE];
 | |
| 
 | |
|   EXPECT_TRUE(fgets(tmp_name, MAX_FILE_NAME_LENGTH_BYTE, stdin) != NULL);
 | |
|   tmp_name[MAX_FILE_NAME_LENGTH_BYTE - 1] = '\0';
 | |
|   int16_t n = 0;
 | |
| 
 | |
|   // Removing trailing spaces.
 | |
|   while ((isspace(tmp_name[n]) || iscntrl(tmp_name[n])) && (tmp_name[n] != 0)
 | |
|       && (n < MAX_FILE_NAME_LENGTH_BYTE)) {
 | |
|     n++;
 | |
|   }
 | |
|   if (n > 0) {
 | |
|     memmove(tmp_name, &tmp_name[n], MAX_FILE_NAME_LENGTH_BYTE - n);
 | |
|   }
 | |
| 
 | |
|   // Removing trailing spaces.
 | |
|   n = (int16_t)(strlen(tmp_name) - 1);
 | |
|   if (n >= 0) {
 | |
|     while ((isspace(tmp_name[n]) || iscntrl(tmp_name[n])) && (n >= 0)) {
 | |
|       n--;
 | |
|     }
 | |
|   }
 | |
|   if (n >= 0) {
 | |
|     tmp_name[n + 1] = '\0';
 | |
|   }
 | |
| 
 | |
|   int16_t len = (int16_t) strlen(tmp_name);
 | |
|   if (len > max_len) {
 | |
|     return -1;
 | |
|   }
 | |
|   if (len > 0) {
 | |
|     std::string tmp_string(tmp_name, len + 1);
 | |
|     *file_name = tmp_string;
 | |
|   }
 | |
|   printf("Enter the sampling frequency (in Hz) of the above file [%u]: ",
 | |
|          *frequency_hz);
 | |
|   EXPECT_TRUE(fgets(tmp_name, 10, stdin) != NULL);
 | |
|   uint16_t tmp_frequency = (uint16_t) atoi(tmp_name);
 | |
|   if (tmp_frequency > 0) {
 | |
|     *frequency_hz = tmp_frequency;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| void PCMFile::Open(const std::string& file_name, uint16_t frequency,
 | |
|                    const char* mode, bool auto_rewind) {
 | |
|   if ((pcm_file_ = fopen(file_name.c_str(), mode)) == NULL) {
 | |
|     printf("Cannot open file %s.\n", file_name.c_str());
 | |
|     ADD_FAILURE() << "Unable to read file";
 | |
|   }
 | |
|   frequency_ = frequency;
 | |
|   samples_10ms_ = (uint16_t)(frequency_ / 100);
 | |
|   auto_rewind_ = auto_rewind;
 | |
|   end_of_file_ = false;
 | |
|   rewinded_ = false;
 | |
| }
 | |
| 
 | |
| int32_t PCMFile::SamplingFrequency() const {
 | |
|   return frequency_;
 | |
| }
 | |
| 
 | |
| uint16_t PCMFile::PayloadLength10Ms() const {
 | |
|   return samples_10ms_;
 | |
| }
 | |
| 
 | |
| int32_t PCMFile::Read10MsData(AudioFrame& audio_frame) {
 | |
|   uint16_t channels = 1;
 | |
|   if (read_stereo_) {
 | |
|     channels = 2;
 | |
|   }
 | |
| 
 | |
|   int32_t payload_size = (int32_t) fread(audio_frame.data_, sizeof(uint16_t),
 | |
|                                          samples_10ms_ * channels, pcm_file_);
 | |
|   if (payload_size < samples_10ms_ * channels) {
 | |
|     for (int k = payload_size; k < samples_10ms_ * channels; k++) {
 | |
|       audio_frame.data_[k] = 0;
 | |
|     }
 | |
|     if (auto_rewind_) {
 | |
|       rewind(pcm_file_);
 | |
|       rewinded_ = true;
 | |
|     } else {
 | |
|       end_of_file_ = true;
 | |
|     }
 | |
|   }
 | |
|   audio_frame.samples_per_channel_ = samples_10ms_;
 | |
|   audio_frame.sample_rate_hz_ = frequency_;
 | |
|   audio_frame.num_channels_ = channels;
 | |
|   audio_frame.timestamp_ = timestamp_;
 | |
|   timestamp_ += samples_10ms_;
 | |
|   return samples_10ms_;
 | |
| }
 | |
| 
 | |
| void PCMFile::Write10MsData(AudioFrame& audio_frame) {
 | |
|   if (audio_frame.num_channels_ == 1) {
 | |
|     if (!save_stereo_) {
 | |
|       if (fwrite(audio_frame.data_, sizeof(uint16_t),
 | |
|                  audio_frame.samples_per_channel_, pcm_file_) !=
 | |
|           static_cast<size_t>(audio_frame.samples_per_channel_)) {
 | |
|         return;
 | |
|       }
 | |
|     } else {
 | |
|       int16_t* stereo_audio = new int16_t[2 * audio_frame.samples_per_channel_];
 | |
|       int k;
 | |
|       for (k = 0; k < audio_frame.samples_per_channel_; k++) {
 | |
|         stereo_audio[k << 1] = audio_frame.data_[k];
 | |
|         stereo_audio[(k << 1) + 1] = audio_frame.data_[k];
 | |
|       }
 | |
|       if (fwrite(stereo_audio, sizeof(int16_t),
 | |
|                  2 * audio_frame.samples_per_channel_, pcm_file_) !=
 | |
|           static_cast<size_t>(2 * audio_frame.samples_per_channel_)) {
 | |
|         return;
 | |
|       }
 | |
|       delete[] stereo_audio;
 | |
|     }
 | |
|   } else {
 | |
|     if (fwrite(audio_frame.data_, sizeof(int16_t),
 | |
|                audio_frame.num_channels_ * audio_frame.samples_per_channel_,
 | |
|                pcm_file_) !=
 | |
|         static_cast<size_t>(audio_frame.num_channels_ *
 | |
|                             audio_frame.samples_per_channel_)) {
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void PCMFile::Write10MsData(int16_t* playout_buffer, uint16_t length_smpls) {
 | |
|   if (fwrite(playout_buffer, sizeof(uint16_t), length_smpls, pcm_file_) !=
 | |
|       length_smpls) {
 | |
|     return;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void PCMFile::Close() {
 | |
|   fclose(pcm_file_);
 | |
|   pcm_file_ = NULL;
 | |
| }
 | |
| 
 | |
| void PCMFile::Rewind() {
 | |
|   rewind(pcm_file_);
 | |
|   end_of_file_ = false;
 | |
| }
 | |
| 
 | |
| bool PCMFile::Rewinded() {
 | |
|   return rewinded_;
 | |
| }
 | |
| 
 | |
| void PCMFile::SaveStereo(bool is_stereo) {
 | |
|   save_stereo_ = is_stereo;
 | |
| }
 | |
| 
 | |
| void PCMFile::ReadStereo(bool is_stereo) {
 | |
|   read_stereo_ = is_stereo;
 | |
| }
 | |
| 
 | |
| }  // namespace webrtc
 |