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