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