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