blob: e069a42de1436d613ddc15d30197ff0585de52dd [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:251/*
leozwang@webrtc.org91b359e2012-02-28 17:26:142 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:253 *
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
Mirko Bonadei92ea95e2017-09-15 04:47:3111#include "modules/audio_coding/test/PCMFile.h"
kjellander@webrtc.org543c3ea2011-11-23 12:20:3512
pbos@webrtc.org12dc1a32013-08-05 16:22:5313#include <ctype.h>
niklase@google.com470e71d2011-07-07 08:21:2514#include <stdio.h>
15#include <string.h>
16
Ali Tofigh714e3cb2022-07-20 10:53:0717#include "absl/strings/string_view.h"
Danil Chapovalov8aba6b42018-04-17 08:10:5718#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3119#include "test/gtest.h"
niklase@google.com470e71d2011-07-07 08:21:2520
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:0421namespace webrtc {
22
niklase@google.com470e71d2011-07-07 08:21:2523#define MAX_FILE_NAME_LENGTH_BYTE 500
24
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:3025PCMFile::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) {
Yves Gerey665174f2018-06-19 13:03:0534 timestamp_ =
35 (((uint32_t)rand() & 0x0000FFFF) << 16) | ((uint32_t)rand() & 0x0000FFFF);
niklase@google.com470e71d2011-07-07 08:21:2536}
37
pbos@webrtc.org0946a562013-04-09 00:28:0638PCMFile::PCMFile(uint32_t timestamp)
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:3039 : 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;
niklase@google.com470e71d2011-07-07 08:21:2548}
49
kwiberg65fc8b92016-08-29 17:05:2450PCMFile::~PCMFile() {
51 if (pcm_file_) {
52 fclose(pcm_file_);
53 }
54}
55
Yves Gerey665174f2018-06-19 13:03:0556int16_t PCMFile::ChooseFile(std::string* file_name,
57 int16_t max_len,
pbos@webrtc.org0946a562013-04-09 00:28:0658 uint16_t* frequency_hz) {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:3059 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';
pbos@webrtc.org0946a562013-04-09 00:28:0663 int16_t n = 0;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:3064
65 // Removing trailing spaces.
Niels Möllere66b83f2022-05-30 10:57:4166 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) &&
Yves Gerey665174f2018-06-19 13:03:0569 (n < MAX_FILE_NAME_LENGTH_BYTE)) {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:3070 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.
pbos@webrtc.org0946a562013-04-09 00:28:0677 n = (int16_t)(strlen(tmp_name) - 1);
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:3078 if (n >= 0) {
Niels Möllere66b83f2022-05-30 10:57:4179 while ((isspace(static_cast<unsigned char>(tmp_name[n])) ||
80 iscntrl(static_cast<unsigned char>(tmp_name[n]))) &&
81 (n >= 0)) {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:3082 n--;
niklase@google.com470e71d2011-07-07 08:21:2583 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:3084 }
85 if (n >= 0) {
86 tmp_name[n + 1] = '\0';
87 }
niklase@google.com470e71d2011-07-07 08:21:2588
Yves Gerey665174f2018-06-19 13:03:0589 int16_t len = (int16_t)strlen(tmp_name);
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:3090 if (len > max_len) {
91 return -1;
92 }
93 if (len > 0) {
tina.legrand@webrtc.orgba468042012-08-17 10:38:2894 std::string tmp_string(tmp_name, len + 1);
95 *file_name = tmp_string;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:3096 }
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);
Yves Gerey665174f2018-06-19 13:03:05100 uint16_t tmp_frequency = (uint16_t)atoi(tmp_name);
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30101 if (tmp_frequency > 0) {
102 *frequency_hz = tmp_frequency;
103 }
104 return 0;
105}
106
Ali Tofigh714e3cb2022-07-20 10:53:07107void PCMFile::Open(absl::string_view file_name,
Yves Gerey665174f2018-06-19 13:03:05108 uint16_t frequency,
Ali Tofigh714e3cb2022-07-20 10:53:07109 absl::string_view mode,
Yves Gerey665174f2018-06-19 13:03:05110 bool auto_rewind) {
Ali Tofigh714e3cb2022-07-20 10:53:07111 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());
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30114 ADD_FAILURE() << "Unable to read file";
115 }
116 frequency_ = frequency;
pbos@webrtc.org0946a562013-04-09 00:28:06117 samples_10ms_ = (uint16_t)(frequency_ / 100);
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30118 auto_rewind_ = auto_rewind;
119 end_of_file_ = false;
120 rewinded_ = false;
121}
122
pbos@webrtc.org0946a562013-04-09 00:28:06123int32_t PCMFile::SamplingFrequency() const {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30124 return frequency_;
125}
126
pbos@webrtc.org0946a562013-04-09 00:28:06127uint16_t PCMFile::PayloadLength10Ms() const {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30128 return samples_10ms_;
129}
130
pbos@webrtc.org0946a562013-04-09 00:28:06131int32_t PCMFile::Read10MsData(AudioFrame& audio_frame) {
132 uint16_t channels = 1;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30133 if (read_stereo_) {
134 channels = 2;
135 }
136
Yves Gerey665174f2018-06-19 13:03:05137 int32_t payload_size =
138 (int32_t)fread(audio_frame.mutable_data(), sizeof(uint16_t),
139 samples_10ms_ * channels, pcm_file_);
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30140 if (payload_size < samples_10ms_ * channels) {
yujo36b1a5f2017-06-12 19:45:32141 int16_t* frame_data = audio_frame.mutable_data();
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30142 for (int k = payload_size; k < samples_10ms_ * channels; k++) {
yujo36b1a5f2017-06-12 19:45:32143 frame_data[k] = 0;
niklase@google.com470e71d2011-07-07 08:21:25144 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30145 if (auto_rewind_) {
146 rewind(pcm_file_);
147 rewinded_ = true;
148 } else {
149 end_of_file_ = true;
niklase@google.com470e71d2011-07-07 08:21:25150 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30151 }
andrew@webrtc.org63a50982012-05-02 23:56:37152 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_;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30156 timestamp_ += samples_10ms_;
Henrik Lundin4d682082015-12-10 15:24:39157 ++blocks_read_;
158 if (num_10ms_blocks_to_read_ && blocks_read_ >= *num_10ms_blocks_to_read_)
159 end_of_file_ = true;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30160 return samples_10ms_;
161}
niklase@google.com470e71d2011-07-07 08:21:25162
yujo36b1a5f2017-06-12 19:45:32163void PCMFile::Write10MsData(const AudioFrame& audio_frame) {
andrew@webrtc.org63a50982012-05-02 23:56:37164 if (audio_frame.num_channels_ == 1) {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30165 if (!save_stereo_) {
yujo36b1a5f2017-06-12 19:45:32166 if (fwrite(audio_frame.data(), sizeof(uint16_t),
leozwang@webrtc.org354b0ed2012-06-01 17:46:21167 audio_frame.samples_per_channel_, pcm_file_) !=
168 static_cast<size_t>(audio_frame.samples_per_channel_)) {
169 return;
170 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30171 } else {
yujo36b1a5f2017-06-12 19:45:32172 const int16_t* frame_data = audio_frame.data();
tina.legrand@webrtc.orgd5726a122013-05-03 07:34:12173 int16_t* stereo_audio = new int16_t[2 * audio_frame.samples_per_channel_];
Peter Kastingdce40cf2015-08-24 21:52:23174 for (size_t k = 0; k < audio_frame.samples_per_channel_; k++) {
yujo36b1a5f2017-06-12 19:45:32175 stereo_audio[k << 1] = frame_data[k];
176 stereo_audio[(k << 1) + 1] = frame_data[k];
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30177 }
pbos@webrtc.org0946a562013-04-09 00:28:06178 if (fwrite(stereo_audio, sizeof(int16_t),
leozwang@webrtc.org354b0ed2012-06-01 17:46:21179 2 * audio_frame.samples_per_channel_, pcm_file_) !=
180 static_cast<size_t>(2 * audio_frame.samples_per_channel_)) {
181 return;
182 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30183 delete[] stereo_audio;
niklase@google.com470e71d2011-07-07 08:21:25184 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30185 } else {
yujo36b1a5f2017-06-12 19:45:32186 if (fwrite(audio_frame.data(), sizeof(int16_t),
leozwang@webrtc.org354b0ed2012-06-01 17:46:21187 audio_frame.num_channels_ * audio_frame.samples_per_channel_,
tina.legrand@webrtc.orgd5726a122013-05-03 07:34:12188 pcm_file_) !=
189 static_cast<size_t>(audio_frame.num_channels_ *
190 audio_frame.samples_per_channel_)) {
leozwang@webrtc.org354b0ed2012-06-01 17:46:21191 return;
192 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30193 }
niklase@google.com470e71d2011-07-07 08:21:25194}
195
yujo36b1a5f2017-06-12 19:45:32196void PCMFile::Write10MsData(const int16_t* playout_buffer,
197 size_t length_smpls) {
tina.legrand@webrtc.orgd5726a122013-05-03 07:34:12198 if (fwrite(playout_buffer, sizeof(uint16_t), length_smpls, pcm_file_) !=
199 length_smpls) {
leozwang@webrtc.org354b0ed2012-06-01 17:46:21200 return;
201 }
niklase@google.com470e71d2011-07-07 08:21:25202}
203
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30204void PCMFile::Close() {
205 fclose(pcm_file_);
206 pcm_file_ = NULL;
Henrik Lundin4d682082015-12-10 15:24:39207 blocks_read_ = 0;
208}
209
210void 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);
niklase@google.com470e71d2011-07-07 08:21:25216}
217
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30218void PCMFile::Rewind() {
219 rewind(pcm_file_);
220 end_of_file_ = false;
Henrik Lundin4d682082015-12-10 15:24:39221 blocks_read_ = 0;
niklase@google.com470e71d2011-07-07 08:21:25222}
223
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30224bool PCMFile::Rewinded() {
225 return rewinded_;
niklase@google.com470e71d2011-07-07 08:21:25226}
227
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30228void PCMFile::SaveStereo(bool is_stereo) {
229 save_stereo_ = is_stereo;
niklase@google.com470e71d2011-07-07 08:21:25230}
231
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30232void PCMFile::ReadStereo(bool is_stereo) {
233 read_stereo_ = is_stereo;
niklase@google.com470e71d2011-07-07 08:21:25234}
235
Henrik Lundin4d682082015-12-10 15:24:39236void PCMFile::SetNum10MsBlocksToRead(int value) {
Oskar Sundbom12ab00b2017-11-16 14:31:38237 num_10ms_blocks_to_read_ = value;
Henrik Lundin4d682082015-12-10 15:24:39238}
239
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30240} // namespace webrtc