blob: fbe73f5470f855a6273c3085b872312a3577b47e [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
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +000011#include "PCMFile.h"
12
niklase@google.com470e71d2011-07-07 08:21:25 +000013#include <cctype>
14#include <stdio.h>
15#include <string.h>
16
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +000017#include "gtest/gtest.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000018#include "module_common_types.h"
19
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) {
33 timestamp_ = (((WebRtc_UWord32)rand() & 0x0000FFFF) << 16) |
34 ((WebRtc_UWord32)rand() & 0x0000FFFF);
niklase@google.com470e71d2011-07-07 08:21:25 +000035}
36
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000037PCMFile::PCMFile(WebRtc_UWord32 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;
niklase@google.com470e71d2011-07-07 08:21:25 +000047}
48
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000049WebRtc_Word16 PCMFile::ChooseFile(std::string* file_name,
50 WebRtc_Word16 max_len) {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000051 char tmp_name[MAX_FILE_NAME_LENGTH_BYTE];
niklase@google.com470e71d2011-07-07 08:21:25 +000052
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000053 EXPECT_TRUE(fgets(tmp_name, MAX_FILE_NAME_LENGTH_BYTE, stdin) != NULL);
54 tmp_name[MAX_FILE_NAME_LENGTH_BYTE - 1] = '\0';
55 WebRtc_Word16 n = 0;
56
57 // Removing leading spaces.
58 while ((isspace(tmp_name[n]) || iscntrl(tmp_name[n])) && (tmp_name[n] != 0)
59 && (n < MAX_FILE_NAME_LENGTH_BYTE)) {
60 n++;
61 }
62 if (n > 0) {
63 memmove(tmp_name, &tmp_name[n], MAX_FILE_NAME_LENGTH_BYTE - n);
64 }
65
66 // Removing trailing spaces.
67 n = (WebRtc_Word16)(strlen(tmp_name) - 1);
68 if (n >= 0) {
69 while ((isspace(tmp_name[n]) || iscntrl(tmp_name[n])) && (n >= 0)) {
70 n--;
niklase@google.com470e71d2011-07-07 08:21:25 +000071 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000072 }
73 if (n >= 0) {
74 tmp_name[n + 1] = '\0';
75 }
76
77 WebRtc_Word16 len = (WebRtc_Word16) strlen(tmp_name);
78 if (len > max_len) {
79 return -1;
80 }
81 if (len > 0) {
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000082 std::string tmp_string(tmp_name, len + 1);
83 *file_name = tmp_string;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000084 }
85 return 0;
86}
87
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +000088WebRtc_Word16 PCMFile::ChooseFile(std::string* file_name,
89 WebRtc_Word16 max_len,
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +000090 WebRtc_UWord16* frequency_hz) {
91 char tmp_name[MAX_FILE_NAME_LENGTH_BYTE];
92
93 EXPECT_TRUE(fgets(tmp_name, MAX_FILE_NAME_LENGTH_BYTE, stdin) != NULL);
94 tmp_name[MAX_FILE_NAME_LENGTH_BYTE - 1] = '\0';
95 WebRtc_Word16 n = 0;
96
97 // Removing trailing spaces.
98 while ((isspace(tmp_name[n]) || iscntrl(tmp_name[n])) && (tmp_name[n] != 0)
99 && (n < MAX_FILE_NAME_LENGTH_BYTE)) {
100 n++;
101 }
102 if (n > 0) {
103 memmove(tmp_name, &tmp_name[n], MAX_FILE_NAME_LENGTH_BYTE - n);
104 }
105
106 // Removing trailing spaces.
107 n = (WebRtc_Word16)(strlen(tmp_name) - 1);
108 if (n >= 0) {
109 while ((isspace(tmp_name[n]) || iscntrl(tmp_name[n])) && (n >= 0)) {
110 n--;
niklase@google.com470e71d2011-07-07 08:21:25 +0000111 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000112 }
113 if (n >= 0) {
114 tmp_name[n + 1] = '\0';
115 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000116
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000117 WebRtc_Word16 len = (WebRtc_Word16) strlen(tmp_name);
118 if (len > max_len) {
119 return -1;
120 }
121 if (len > 0) {
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000122 std::string tmp_string(tmp_name, len + 1);
123 *file_name = tmp_string;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000124 }
125 printf("Enter the sampling frequency (in Hz) of the above file [%u]: ",
126 *frequency_hz);
127 EXPECT_TRUE(fgets(tmp_name, 10, stdin) != NULL);
128 WebRtc_UWord16 tmp_frequency = (WebRtc_UWord16) atoi(tmp_name);
129 if (tmp_frequency > 0) {
130 *frequency_hz = tmp_frequency;
131 }
132 return 0;
133}
134
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000135void PCMFile::Open(const std::string& file_name, WebRtc_UWord16 frequency,
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000136 const char* mode, bool auto_rewind) {
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000137 if ((pcm_file_ = fopen(file_name.c_str(), mode)) == NULL) {
138 printf("Cannot open file %s.\n", file_name.c_str());
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000139 ADD_FAILURE() << "Unable to read file";
140 }
141 frequency_ = frequency;
142 samples_10ms_ = (WebRtc_UWord16)(frequency_ / 100);
143 auto_rewind_ = auto_rewind;
144 end_of_file_ = false;
145 rewinded_ = false;
146}
147
148WebRtc_Word32 PCMFile::SamplingFrequency() const {
149 return frequency_;
150}
151
152WebRtc_UWord16 PCMFile::PayloadLength10Ms() const {
153 return samples_10ms_;
154}
155
156WebRtc_Word32 PCMFile::Read10MsData(AudioFrame& audio_frame) {
157 WebRtc_UWord16 channels = 1;
158 if (read_stereo_) {
159 channels = 2;
160 }
161
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000162 WebRtc_Word32 payload_size = (WebRtc_Word32) fread(audio_frame.data_,
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000163 sizeof(WebRtc_UWord16),
164 samples_10ms_ * channels,
165 pcm_file_);
166 if (payload_size < samples_10ms_ * channels) {
167 for (int k = payload_size; k < samples_10ms_ * channels; k++) {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000168 audio_frame.data_[k] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000169 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000170 if (auto_rewind_) {
171 rewind(pcm_file_);
172 rewinded_ = true;
173 } else {
174 end_of_file_ = true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000175 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000176 }
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000177 audio_frame.samples_per_channel_ = samples_10ms_;
178 audio_frame.sample_rate_hz_ = frequency_;
179 audio_frame.num_channels_ = channels;
180 audio_frame.timestamp_ = timestamp_;
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000181 timestamp_ += samples_10ms_;
182 return samples_10ms_;
183}
niklase@google.com470e71d2011-07-07 08:21:25 +0000184
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000185void PCMFile::Write10MsData(AudioFrame& audio_frame) {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000186 if (audio_frame.num_channels_ == 1) {
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000187 if (!save_stereo_) {
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000188 if (fwrite(audio_frame.data_, sizeof(WebRtc_UWord16),
189 audio_frame.samples_per_channel_, pcm_file_) !=
190 static_cast<size_t>(audio_frame.samples_per_channel_)) {
191 return;
192 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000193 } else {
194 WebRtc_Word16* stereo_audio =
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000195 new WebRtc_Word16[2 * audio_frame.samples_per_channel_];
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000196 int k;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000197 for (k = 0; k < audio_frame.samples_per_channel_; k++) {
198 stereo_audio[k << 1] = audio_frame.data_[k];
199 stereo_audio[(k << 1) + 1] = audio_frame.data_[k];
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000200 }
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000201 if (fwrite(stereo_audio, sizeof(WebRtc_Word16),
202 2 * audio_frame.samples_per_channel_, pcm_file_) !=
203 static_cast<size_t>(2 * audio_frame.samples_per_channel_)) {
204 return;
205 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000206 delete[] stereo_audio;
niklase@google.com470e71d2011-07-07 08:21:25 +0000207 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000208 } else {
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000209 if (fwrite(audio_frame.data_, sizeof(WebRtc_Word16),
210 audio_frame.num_channels_ * audio_frame.samples_per_channel_,
211 pcm_file_) != static_cast<size_t>(
212 audio_frame.num_channels_ * audio_frame.samples_per_channel_)) {
213 return;
214 }
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000215 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000216}
217
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000218void PCMFile::Write10MsData(WebRtc_Word16* playout_buffer,
219 WebRtc_UWord16 length_smpls) {
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000220 if (fwrite(playout_buffer, sizeof(WebRtc_UWord16),
221 length_smpls, pcm_file_) != length_smpls) {
222 return;
223 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000224}
225
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000226void PCMFile::Close() {
227 fclose(pcm_file_);
228 pcm_file_ = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000229}
230
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000231void PCMFile::Rewind() {
232 rewind(pcm_file_);
233 end_of_file_ = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000234}
235
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000236bool PCMFile::Rewinded() {
237 return rewinded_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238}
239
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000240void PCMFile::SaveStereo(bool is_stereo) {
241 save_stereo_ = is_stereo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000242}
243
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000244void PCMFile::ReadStereo(bool is_stereo) {
245 read_stereo_ = is_stereo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000246}
247
tina.legrand@webrtc.orga6ecd1e2012-04-26 07:54:30 +0000248} // namespace webrtc