1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/core/kernels/spectrogram_test_utils.h"
17
18 #include <math.h>
19 #include <stddef.h>
20
21 #include "tensorflow/core/lib/core/status_test_util.h"
22 #include "tensorflow/core/lib/io/path.h"
23 #include "tensorflow/core/lib/strings/numbers.h"
24 #include "tensorflow/core/lib/strings/str_util.h"
25 #include "tensorflow/core/lib/wav/wav_io.h"
26 #include "tensorflow/core/platform/env.h"
27 #include "tensorflow/core/platform/test.h"
28 #include "tensorflow/core/platform/types.h"
29
30 namespace tensorflow {
31
ReadWaveFileToVector(const string & file_name,std::vector<double> * data)32 bool ReadWaveFileToVector(const string& file_name, std::vector<double>* data) {
33 string wav_data;
34 if (!ReadFileToString(Env::Default(), file_name, &wav_data).ok()) {
35 LOG(ERROR) << "Wave file read failed for " << file_name;
36 return false;
37 }
38 std::vector<float> decoded_data;
39 uint32 decoded_sample_count;
40 uint16 decoded_channel_count;
41 uint32 decoded_sample_rate;
42 if (!wav::DecodeLin16WaveAsFloatVector(
43 wav_data, &decoded_data, &decoded_sample_count,
44 &decoded_channel_count, &decoded_sample_rate)
45 .ok()) {
46 return false;
47 }
48 // Convert from float to double for the output value.
49 data->resize(decoded_data.size());
50 for (int i = 0; i < decoded_data.size(); ++i) {
51 (*data)[i] = decoded_data[i];
52 }
53 return true;
54 }
55
ReadRawFloatFileToComplexVector(const string & file_name,int row_length,std::vector<std::vector<std::complex<double>>> * data)56 bool ReadRawFloatFileToComplexVector(
57 const string& file_name, int row_length,
58 std::vector<std::vector<std::complex<double> > >* data) {
59 data->clear();
60 string data_string;
61 if (!ReadFileToString(Env::Default(), file_name, &data_string).ok()) {
62 LOG(ERROR) << "Failed to open file " << file_name;
63 return false;
64 }
65 float real_out;
66 float imag_out;
67 const int kBytesPerValue = 4;
68 CHECK_EQ(sizeof(real_out), kBytesPerValue);
69 std::vector<std::complex<double> > data_row;
70 int row_counter = 0;
71 int offset = 0;
72 const int end = data_string.size();
73 while (offset < end) {
74 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
75 char arr[4];
76 for (int i = 0; i < kBytesPerValue; ++i) {
77 arr[3 - i] = *(data_string.data() + offset + i);
78 }
79 memcpy(&real_out, arr, kBytesPerValue);
80 offset += kBytesPerValue;
81 for (int i = 0; i < kBytesPerValue; ++i) {
82 arr[3 - i] = *(data_string.data() + offset + i);
83 }
84 memcpy(&imag_out, arr, kBytesPerValue);
85 offset += kBytesPerValue;
86 #else
87 memcpy(&real_out, data_string.data() + offset, kBytesPerValue);
88 offset += kBytesPerValue;
89 memcpy(&imag_out, data_string.data() + offset, kBytesPerValue);
90 offset += kBytesPerValue;
91 #endif
92 if (row_counter >= row_length) {
93 data->push_back(data_row);
94 data_row.clear();
95 row_counter = 0;
96 }
97 data_row.push_back(std::complex<double>(real_out, imag_out));
98 ++row_counter;
99 }
100 if (row_counter >= row_length) {
101 data->push_back(data_row);
102 }
103 return true;
104 }
105
ReadCSVFileToComplexVectorOrDie(const string & file_name,std::vector<std::vector<std::complex<double>>> * data)106 void ReadCSVFileToComplexVectorOrDie(
107 const string& file_name,
108 std::vector<std::vector<std::complex<double> > >* data) {
109 data->clear();
110 string data_string;
111 if (!ReadFileToString(Env::Default(), file_name, &data_string).ok()) {
112 LOG(FATAL) << "Failed to open file " << file_name;
113 return;
114 }
115 std::vector<string> lines = str_util::Split(data_string, '\n');
116 for (const string& line : lines) {
117 if (line.empty()) {
118 continue;
119 }
120 std::vector<std::complex<double> > data_line;
121 std::vector<string> values = str_util::Split(line, ',');
122 for (std::vector<string>::const_iterator i = values.begin();
123 i != values.end(); ++i) {
124 // each element of values may be in the form:
125 // 0.001+0.002i, 0.001, 0.001i, -1.2i, -1.2-3.2i, 1.5, 1.5e-03+21.0i
126 std::vector<string> parts;
127 // Find the first instance of + or - after the second character
128 // in the string, that does not immediately follow an 'e'.
129 size_t operator_index = i->find_first_of("+-", 2);
130 if (operator_index < i->size() &&
131 i->substr(operator_index - 1, 1) == "e") {
132 operator_index = i->find_first_of("+-", operator_index + 1);
133 }
134 parts.push_back(i->substr(0, operator_index));
135 if (operator_index < i->size()) {
136 parts.push_back(i->substr(operator_index, string::npos));
137 }
138
139 double real_part = 0.0;
140 double imaginary_part = 0.0;
141 for (std::vector<string>::const_iterator j = parts.begin();
142 j != parts.end(); ++j) {
143 if (j->find_first_of("ij") != string::npos) {
144 strings::safe_strtod(*j, &imaginary_part);
145 } else {
146 strings::safe_strtod(*j, &real_part);
147 }
148 }
149 data_line.push_back(std::complex<double>(real_part, imaginary_part));
150 }
151 data->push_back(data_line);
152 }
153 }
154
ReadCSVFileToArrayOrDie(const string & filename,std::vector<std::vector<float>> * array)155 void ReadCSVFileToArrayOrDie(const string& filename,
156 std::vector<std::vector<float> >* array) {
157 string contents;
158 TF_CHECK_OK(ReadFileToString(Env::Default(), filename, &contents));
159 std::vector<string> lines = str_util::Split(contents, '\n');
160 contents.clear();
161
162 array->clear();
163 std::vector<float> values;
164 for (int l = 0; l < lines.size(); ++l) {
165 values.clear();
166 std::vector<string> split_line = str_util::Split(lines[l], ",");
167 for (const string& token : split_line) {
168 float tmp;
169 CHECK(strings::safe_strtof(token, &tmp));
170 values.push_back(tmp);
171 }
172 array->push_back(values);
173 }
174 }
175
WriteDoubleVectorToFile(const string & file_name,const std::vector<double> & data)176 bool WriteDoubleVectorToFile(const string& file_name,
177 const std::vector<double>& data) {
178 std::unique_ptr<WritableFile> file;
179 if (!Env::Default()->NewWritableFile(file_name, &file).ok()) {
180 LOG(ERROR) << "Failed to open file " << file_name;
181 return false;
182 }
183 for (int i = 0; i < data.size(); ++i) {
184 if (!file->Append(StringPiece(reinterpret_cast<const char*>(&(data[i])),
185 sizeof(data[i])))
186 .ok()) {
187 LOG(ERROR) << "Failed to append to file " << file_name;
188 return false;
189 }
190 }
191 if (!file->Close().ok()) {
192 LOG(ERROR) << "Failed to close file " << file_name;
193 return false;
194 }
195 return true;
196 }
197
WriteFloatVectorToFile(const string & file_name,const std::vector<float> & data)198 bool WriteFloatVectorToFile(const string& file_name,
199 const std::vector<float>& data) {
200 std::unique_ptr<WritableFile> file;
201 if (!Env::Default()->NewWritableFile(file_name, &file).ok()) {
202 LOG(ERROR) << "Failed to open file " << file_name;
203 return false;
204 }
205 for (int i = 0; i < data.size(); ++i) {
206 if (!file->Append(StringPiece(reinterpret_cast<const char*>(&(data[i])),
207 sizeof(data[i])))
208 .ok()) {
209 LOG(ERROR) << "Failed to append to file " << file_name;
210 return false;
211 }
212 }
213 if (!file->Close().ok()) {
214 LOG(ERROR) << "Failed to close file " << file_name;
215 return false;
216 }
217 return true;
218 }
219
WriteDoubleArrayToFile(const string & file_name,int size,const double * data)220 bool WriteDoubleArrayToFile(const string& file_name, int size,
221 const double* data) {
222 std::unique_ptr<WritableFile> file;
223 if (!Env::Default()->NewWritableFile(file_name, &file).ok()) {
224 LOG(ERROR) << "Failed to open file " << file_name;
225 return false;
226 }
227 for (int i = 0; i < size; ++i) {
228 if (!file->Append(StringPiece(reinterpret_cast<const char*>(&(data[i])),
229 sizeof(data[i])))
230 .ok()) {
231 LOG(ERROR) << "Failed to append to file " << file_name;
232 return false;
233 }
234 }
235 if (!file->Close().ok()) {
236 LOG(ERROR) << "Failed to close file " << file_name;
237 return false;
238 }
239 return true;
240 }
241
WriteFloatArrayToFile(const string & file_name,int size,const float * data)242 bool WriteFloatArrayToFile(const string& file_name, int size,
243 const float* data) {
244 std::unique_ptr<WritableFile> file;
245 if (!Env::Default()->NewWritableFile(file_name, &file).ok()) {
246 LOG(ERROR) << "Failed to open file " << file_name;
247 return false;
248 }
249 for (int i = 0; i < size; ++i) {
250 if (!file->Append(StringPiece(reinterpret_cast<const char*>(&(data[i])),
251 sizeof(data[i])))
252 .ok()) {
253 LOG(ERROR) << "Failed to append to file " << file_name;
254 return false;
255 }
256 }
257 if (!file->Close().ok()) {
258 LOG(ERROR) << "Failed to close file " << file_name;
259 return false;
260 }
261 return true;
262 }
263
WriteComplexVectorToRawFloatFile(const string & file_name,const std::vector<std::vector<std::complex<double>>> & data)264 bool WriteComplexVectorToRawFloatFile(
265 const string& file_name,
266 const std::vector<std::vector<std::complex<double> > >& data) {
267 std::unique_ptr<WritableFile> file;
268 if (!Env::Default()->NewWritableFile(file_name, &file).ok()) {
269 LOG(ERROR) << "Failed to open file " << file_name;
270 return false;
271 }
272 for (int i = 0; i < data.size(); ++i) {
273 for (int j = 0; j < data[i].size(); ++j) {
274 const float real_part(real(data[i][j]));
275 if (!file->Append(StringPiece(reinterpret_cast<const char*>(&real_part),
276 sizeof(real_part)))
277 .ok()) {
278 LOG(ERROR) << "Failed to append to file " << file_name;
279 return false;
280 }
281
282 const float imag_part(imag(data[i][j]));
283 if (!file->Append(StringPiece(reinterpret_cast<const char*>(&imag_part),
284 sizeof(imag_part)))
285 .ok()) {
286 LOG(ERROR) << "Failed to append to file " << file_name;
287 return false;
288 }
289 }
290 }
291 if (!file->Close().ok()) {
292 LOG(ERROR) << "Failed to close file " << file_name;
293 return false;
294 }
295 return true;
296 }
297
SineWave(int sample_rate,float frequency,float duration_seconds,std::vector<double> * data)298 void SineWave(int sample_rate, float frequency, float duration_seconds,
299 std::vector<double>* data) {
300 data->clear();
301 for (int i = 0; i < static_cast<int>(sample_rate * duration_seconds); ++i) {
302 data->push_back(
303 sin(2.0 * M_PI * i * frequency / static_cast<double>(sample_rate)));
304 }
305 }
306
307 } // namespace tensorflow
308