PCMFile.cc (6799B)
1 /* 2 * Copyright (c) 2012 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 "modules/audio_coding/test/PCMFile.h" 12 13 #include <cctype> 14 #include <cstdint> 15 #include <cstdio> 16 #include <cstdlib> 17 #include <cstring> 18 #include <string> 19 20 #include "absl/strings/string_view.h" 21 #include "api/audio/audio_frame.h" 22 #include "rtc_base/checks.h" 23 #include "test/gtest.h" 24 25 namespace webrtc { 26 27 #define MAX_FILE_NAME_LENGTH_BYTE 500 28 29 PCMFile::PCMFile() 30 : pcm_file_(nullptr), 31 samples_10ms_(160), 32 frequency_(16000), 33 end_of_file_(false), 34 auto_rewind_(false), 35 rewinded_(false), 36 read_stereo_(false), 37 save_stereo_(false) { 38 timestamp_ = 39 (((uint32_t)rand() & 0x0000FFFF) << 16) | ((uint32_t)rand() & 0x0000FFFF); 40 } 41 42 PCMFile::PCMFile(uint32_t timestamp) 43 : pcm_file_(nullptr), 44 samples_10ms_(160), 45 frequency_(16000), 46 end_of_file_(false), 47 auto_rewind_(false), 48 rewinded_(false), 49 read_stereo_(false), 50 save_stereo_(false) { 51 timestamp_ = timestamp; 52 } 53 54 PCMFile::~PCMFile() { 55 if (pcm_file_) { 56 fclose(pcm_file_); 57 } 58 } 59 60 int16_t PCMFile::ChooseFile(std::string* file_name, 61 int16_t max_len, 62 uint16_t* frequency_hz) { 63 char tmp_name[MAX_FILE_NAME_LENGTH_BYTE]; 64 65 EXPECT_TRUE(fgets(tmp_name, MAX_FILE_NAME_LENGTH_BYTE, stdin) != nullptr); 66 tmp_name[MAX_FILE_NAME_LENGTH_BYTE - 1] = '\0'; 67 int16_t n = 0; 68 69 // Removing trailing spaces. 70 while ((isspace(static_cast<unsigned char>(tmp_name[n])) || 71 iscntrl(static_cast<unsigned char>(tmp_name[n]))) && 72 (static_cast<unsigned char>(tmp_name[n]) != 0) && 73 (n < MAX_FILE_NAME_LENGTH_BYTE)) { 74 n++; 75 } 76 if (n > 0) { 77 memmove(tmp_name, &tmp_name[n], MAX_FILE_NAME_LENGTH_BYTE - n); 78 } 79 80 // Removing trailing spaces. 81 n = (int16_t)(strlen(tmp_name) - 1); 82 if (n >= 0) { 83 while ((isspace(static_cast<unsigned char>(tmp_name[n])) || 84 iscntrl(static_cast<unsigned char>(tmp_name[n]))) && 85 (n >= 0)) { 86 n--; 87 } 88 } 89 if (n >= 0) { 90 tmp_name[n + 1] = '\0'; 91 } 92 93 int16_t len = (int16_t)strlen(tmp_name); 94 if (len > max_len) { 95 return -1; 96 } 97 if (len > 0) { 98 std::string tmp_string(tmp_name, len + 1); 99 *file_name = tmp_string; 100 } 101 printf("Enter the sampling frequency (in Hz) of the above file [%u]: ", 102 *frequency_hz); 103 EXPECT_TRUE(fgets(tmp_name, 10, stdin) != nullptr); 104 uint16_t tmp_frequency = (uint16_t)atoi(tmp_name); 105 if (tmp_frequency > 0) { 106 *frequency_hz = tmp_frequency; 107 } 108 return 0; 109 } 110 111 void PCMFile::Open(absl::string_view file_name, 112 uint16_t frequency, 113 absl::string_view mode, 114 bool auto_rewind) { 115 if ((pcm_file_ = fopen(std::string(file_name).c_str(), 116 std::string(mode).c_str())) == nullptr) { 117 printf("Cannot open file %s.\n", std::string(file_name).c_str()); 118 ADD_FAILURE() << "Unable to read file"; 119 } 120 frequency_ = frequency; 121 samples_10ms_ = (uint16_t)(frequency_ / 100); 122 auto_rewind_ = auto_rewind; 123 end_of_file_ = false; 124 rewinded_ = false; 125 } 126 127 int32_t PCMFile::SamplingFrequency() const { 128 return frequency_; 129 } 130 131 uint16_t PCMFile::PayloadLength10Ms() const { 132 return samples_10ms_; 133 } 134 135 int32_t PCMFile::Read10MsData(AudioFrame& audio_frame) { 136 uint16_t channels = 1; 137 if (read_stereo_) { 138 channels = 2; 139 } 140 141 int32_t payload_size = 142 (int32_t)fread(audio_frame.mutable_data(), sizeof(uint16_t), 143 samples_10ms_ * channels, pcm_file_); 144 if (payload_size < samples_10ms_ * channels) { 145 int16_t* frame_data = audio_frame.mutable_data(); 146 for (int k = payload_size; k < samples_10ms_ * channels; k++) { 147 frame_data[k] = 0; 148 } 149 if (auto_rewind_) { 150 rewind(pcm_file_); 151 rewinded_ = true; 152 } else { 153 end_of_file_ = true; 154 } 155 } 156 audio_frame.samples_per_channel_ = samples_10ms_; 157 audio_frame.sample_rate_hz_ = frequency_; 158 audio_frame.num_channels_ = channels; 159 audio_frame.timestamp_ = timestamp_; 160 timestamp_ += samples_10ms_; 161 ++blocks_read_; 162 if (num_10ms_blocks_to_read_ && blocks_read_ >= *num_10ms_blocks_to_read_) 163 end_of_file_ = true; 164 return samples_10ms_; 165 } 166 167 void PCMFile::Write10MsData(const AudioFrame& audio_frame) { 168 if (audio_frame.num_channels_ == 1) { 169 if (!save_stereo_) { 170 if (fwrite(audio_frame.data(), sizeof(uint16_t), 171 audio_frame.samples_per_channel_, pcm_file_) != 172 static_cast<size_t>(audio_frame.samples_per_channel_)) { 173 return; 174 } 175 } else { 176 const int16_t* frame_data = audio_frame.data(); 177 int16_t* stereo_audio = new int16_t[2 * audio_frame.samples_per_channel_]; 178 for (size_t k = 0; k < audio_frame.samples_per_channel_; k++) { 179 stereo_audio[k << 1] = frame_data[k]; 180 stereo_audio[(k << 1) + 1] = frame_data[k]; 181 } 182 if (fwrite(stereo_audio, sizeof(int16_t), 183 2 * audio_frame.samples_per_channel_, pcm_file_) != 184 static_cast<size_t>(2 * audio_frame.samples_per_channel_)) { 185 return; 186 } 187 delete[] stereo_audio; 188 } 189 } else { 190 if (fwrite(audio_frame.data(), sizeof(int16_t), 191 audio_frame.num_channels_ * audio_frame.samples_per_channel_, 192 pcm_file_) != 193 static_cast<size_t>(audio_frame.num_channels_ * 194 audio_frame.samples_per_channel_)) { 195 return; 196 } 197 } 198 } 199 200 void PCMFile::Write10MsData(const int16_t* playout_buffer, 201 size_t length_smpls) { 202 if (fwrite(playout_buffer, sizeof(uint16_t), length_smpls, pcm_file_) != 203 length_smpls) { 204 return; 205 } 206 } 207 208 void PCMFile::Close() { 209 fclose(pcm_file_); 210 pcm_file_ = nullptr; 211 blocks_read_ = 0; 212 } 213 214 void PCMFile::FastForward(int num_10ms_blocks) { 215 const int channels = read_stereo_ ? 2 : 1; 216 long num_bytes_to_move = 217 num_10ms_blocks * sizeof(int16_t) * samples_10ms_ * channels; 218 int error = fseek(pcm_file_, num_bytes_to_move, SEEK_CUR); 219 RTC_DCHECK_EQ(error, 0); 220 } 221 222 void PCMFile::Rewind() { 223 rewind(pcm_file_); 224 end_of_file_ = false; 225 blocks_read_ = 0; 226 } 227 228 bool PCMFile::Rewinded() { 229 return rewinded_; 230 } 231 232 void PCMFile::SaveStereo(bool is_stereo) { 233 save_stereo_ = is_stereo; 234 } 235 236 void PCMFile::ReadStereo(bool is_stereo) { 237 read_stereo_ = is_stereo; 238 } 239 240 void PCMFile::SetNum10MsBlocksToRead(int value) { 241 num_10ms_blocks_to_read_ = value; 242 } 243 244 } // namespace webrtc