blob: 9ccfa491178f2527b10965172a8274dc62454a5f [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
leozwang@webrtc.org91b359e2012-02-28 17:26:14 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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 06:47:31 +020011#include "modules/audio_coding/test/PCMFile.h"
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <ctype.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000014#include <stdio.h>
15#include <string.h>
16
Danil Chapovalov8aba6b42018-04-17 10:10:57 +020017#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "test/gtest.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000020namespace webrtc {
21
niklase@google.com470e71d2011-07-07 08:21:25 +000022#define MAX_FILE_NAME_LENGTH_BYTE 500
23
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000024PCMFile::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) {
Yves Gerey665174f2018-06-19 15:03:05 +020033 timestamp_ =
34 (((uint32_t)rand() & 0x0000FFFF) << 16) | ((uint32_t)rand() & 0x0000FFFF);
niklase@google.com470e71d2011-07-07 08:21:25 +000035}
36
pbos@webrtc.org0946a562013-04-09 00:28:06 +000037PCMFile::PCMFile(uint32_t timestamp)
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000038 : 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;
niklase@google.com470e71d2011-07-07 08:21:25 +000047}
48
kwiberg65fc8b92016-08-29 10:05:24 -070049PCMFile::~PCMFile() {
50 if (pcm_file_) {
51 fclose(pcm_file_);
52 }
53}
54
Yves Gerey665174f2018-06-19 15:03:05 +020055int16_t PCMFile::ChooseFile(std::string* file_name,
56 int16_t max_len,
pbos@webrtc.org0946a562013-04-09 00:28:06 +000057 uint16_t* frequency_hz) {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000058 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';
pbos@webrtc.org0946a562013-04-09 00:28:06 +000062 int16_t n = 0;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000063
64 // Removing trailing spaces.
Niels Möllere66b83f2022-05-30 12:57:41 +020065 while ((isspace(static_cast<unsigned char>(tmp_name[n])) ||
66 iscntrl(static_cast<unsigned char>(tmp_name[n]))) &&
67 (static_cast<unsigned char>(tmp_name[n]) != 0) &&
Yves Gerey665174f2018-06-19 15:03:05 +020068 (n < MAX_FILE_NAME_LENGTH_BYTE)) {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000069 n++;
70 }
71 if (n > 0) {
72 memmove(tmp_name, &tmp_name[n], MAX_FILE_NAME_LENGTH_BYTE - n);
73 }
74
75 // Removing trailing spaces.
pbos@webrtc.org0946a562013-04-09 00:28:06 +000076 n = (int16_t)(strlen(tmp_name) - 1);
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000077 if (n >= 0) {
Niels Möllere66b83f2022-05-30 12:57:41 +020078 while ((isspace(static_cast<unsigned char>(tmp_name[n])) ||
79 iscntrl(static_cast<unsigned char>(tmp_name[n]))) &&
80 (n >= 0)) {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000081 n--;
niklase@google.com470e71d2011-07-07 08:21:25 +000082 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000083 }
84 if (n >= 0) {
85 tmp_name[n + 1] = '\0';
86 }
niklase@google.com470e71d2011-07-07 08:21:25 +000087
Yves Gerey665174f2018-06-19 15:03:05 +020088 int16_t len = (int16_t)strlen(tmp_name);
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000089 if (len > max_len) {
90 return -1;
91 }
92 if (len > 0) {
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000093 std::string tmp_string(tmp_name, len + 1);
94 *file_name = tmp_string;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000095 }
96 printf("Enter the sampling frequency (in Hz) of the above file [%u]: ",
97 *frequency_hz);
98 EXPECT_TRUE(fgets(tmp_name, 10, stdin) != NULL);
Yves Gerey665174f2018-06-19 15:03:05 +020099 uint16_t tmp_frequency = (uint16_t)atoi(tmp_name);
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000100 if (tmp_frequency > 0) {
101 *frequency_hz = tmp_frequency;
102 }
103 return 0;
104}
105
Yves Gerey665174f2018-06-19 15:03:05 +0200106void PCMFile::Open(const std::string& file_name,
107 uint16_t frequency,
108 const char* mode,
109 bool auto_rewind) {
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000110 if ((pcm_file_ = fopen(file_name.c_str(), mode)) == NULL) {
111 printf("Cannot open file %s.\n", file_name.c_str());
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000112 ADD_FAILURE() << "Unable to read file";
113 }
114 frequency_ = frequency;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000115 samples_10ms_ = (uint16_t)(frequency_ / 100);
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000116 auto_rewind_ = auto_rewind;
117 end_of_file_ = false;
118 rewinded_ = false;
119}
120
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000121int32_t PCMFile::SamplingFrequency() const {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000122 return frequency_;
123}
124
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000125uint16_t PCMFile::PayloadLength10Ms() const {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000126 return samples_10ms_;
127}
128
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000129int32_t PCMFile::Read10MsData(AudioFrame& audio_frame) {
130 uint16_t channels = 1;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000131 if (read_stereo_) {
132 channels = 2;
133 }
134
Yves Gerey665174f2018-06-19 15:03:05 +0200135 int32_t payload_size =
136 (int32_t)fread(audio_frame.mutable_data(), sizeof(uint16_t),
137 samples_10ms_ * channels, pcm_file_);
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000138 if (payload_size < samples_10ms_ * channels) {
yujo36b1a5f2017-06-12 12:45:32 -0700139 int16_t* frame_data = audio_frame.mutable_data();
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000140 for (int k = payload_size; k < samples_10ms_ * channels; k++) {
yujo36b1a5f2017-06-12 12:45:32 -0700141 frame_data[k] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000142 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000143 if (auto_rewind_) {
144 rewind(pcm_file_);
145 rewinded_ = true;
146 } else {
147 end_of_file_ = true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000148 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000149 }
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000150 audio_frame.samples_per_channel_ = samples_10ms_;
151 audio_frame.sample_rate_hz_ = frequency_;
152 audio_frame.num_channels_ = channels;
153 audio_frame.timestamp_ = timestamp_;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000154 timestamp_ += samples_10ms_;
Henrik Lundin4d682082015-12-10 16:24:39 +0100155 ++blocks_read_;
156 if (num_10ms_blocks_to_read_ && blocks_read_ >= *num_10ms_blocks_to_read_)
157 end_of_file_ = true;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000158 return samples_10ms_;
159}
niklase@google.com470e71d2011-07-07 08:21:25 +0000160
yujo36b1a5f2017-06-12 12:45:32 -0700161void PCMFile::Write10MsData(const AudioFrame& audio_frame) {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000162 if (audio_frame.num_channels_ == 1) {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000163 if (!save_stereo_) {
yujo36b1a5f2017-06-12 12:45:32 -0700164 if (fwrite(audio_frame.data(), sizeof(uint16_t),
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000165 audio_frame.samples_per_channel_, pcm_file_) !=
166 static_cast<size_t>(audio_frame.samples_per_channel_)) {
167 return;
168 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000169 } else {
yujo36b1a5f2017-06-12 12:45:32 -0700170 const int16_t* frame_data = audio_frame.data();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000171 int16_t* stereo_audio = new int16_t[2 * audio_frame.samples_per_channel_];
Peter Kastingdce40cf2015-08-24 14:52:23 -0700172 for (size_t k = 0; k < audio_frame.samples_per_channel_; k++) {
yujo36b1a5f2017-06-12 12:45:32 -0700173 stereo_audio[k << 1] = frame_data[k];
174 stereo_audio[(k << 1) + 1] = frame_data[k];
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000175 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000176 if (fwrite(stereo_audio, sizeof(int16_t),
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000177 2 * audio_frame.samples_per_channel_, pcm_file_) !=
178 static_cast<size_t>(2 * audio_frame.samples_per_channel_)) {
179 return;
180 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000181 delete[] stereo_audio;
niklase@google.com470e71d2011-07-07 08:21:25 +0000182 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000183 } else {
yujo36b1a5f2017-06-12 12:45:32 -0700184 if (fwrite(audio_frame.data(), sizeof(int16_t),
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000185 audio_frame.num_channels_ * audio_frame.samples_per_channel_,
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000186 pcm_file_) !=
187 static_cast<size_t>(audio_frame.num_channels_ *
188 audio_frame.samples_per_channel_)) {
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000189 return;
190 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000191 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000192}
193
yujo36b1a5f2017-06-12 12:45:32 -0700194void PCMFile::Write10MsData(const int16_t* playout_buffer,
195 size_t length_smpls) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000196 if (fwrite(playout_buffer, sizeof(uint16_t), length_smpls, pcm_file_) !=
197 length_smpls) {
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000198 return;
199 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000200}
201
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000202void PCMFile::Close() {
203 fclose(pcm_file_);
204 pcm_file_ = NULL;
Henrik Lundin4d682082015-12-10 16:24:39 +0100205 blocks_read_ = 0;
206}
207
208void PCMFile::FastForward(int num_10ms_blocks) {
209 const int channels = read_stereo_ ? 2 : 1;
210 long num_bytes_to_move =
211 num_10ms_blocks * sizeof(int16_t) * samples_10ms_ * channels;
212 int error = fseek(pcm_file_, num_bytes_to_move, SEEK_CUR);
213 RTC_DCHECK_EQ(error, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000216void PCMFile::Rewind() {
217 rewind(pcm_file_);
218 end_of_file_ = false;
Henrik Lundin4d682082015-12-10 16:24:39 +0100219 blocks_read_ = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000220}
221
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000222bool PCMFile::Rewinded() {
223 return rewinded_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000224}
225
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000226void PCMFile::SaveStereo(bool is_stereo) {
227 save_stereo_ = is_stereo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000228}
229
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000230void PCMFile::ReadStereo(bool is_stereo) {
231 read_stereo_ = is_stereo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000232}
233
Henrik Lundin4d682082015-12-10 16:24:39 +0100234void PCMFile::SetNum10MsBlocksToRead(int value) {
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100235 num_10ms_blocks_to_read_ = value;
Henrik Lundin4d682082015-12-10 16:24:39 +0100236}
237
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000238} // namespace webrtc