1 /*
2  *  Copyright (c) 2013 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 <cfloat>
12 #include <cstdio>
13 #include <cstdlib>
14 #include <memory>
15 #include <vector>
16 
17 #include "modules/audio_processing/transient/file_utils.h"
18 #include "modules/audio_processing/transient/transient_detector.h"
19 #include "rtc_base/system/file_wrapper.h"
20 
21 using webrtc::FileWrapper;
22 using webrtc::TransientDetector;
23 
24 // Application to generate a RTP timing file.
25 // Opens the PCM file and divides the signal in frames.
26 // Creates a send times array, one for each step.
27 // Each block that contains a transient, has an infinite send time.
28 // The resultant array is written to a DAT file
29 // Returns -1 on error or |lost_packets| otherwise.
main(int argc,char * argv[])30 int main(int argc, char* argv[]) {
31   if (argc != 5) {
32     printf("\n%s - Application to generate a RTP timing file.\n\n", argv[0]);
33     printf("%s PCMfile DATfile chunkSize sampleRate\n\n", argv[0]);
34     printf("Opens the PCMfile with sampleRate in Hertz.\n");
35     printf("Creates a send times array, one for each chunkSize ");
36     printf("milliseconds step.\n");
37     printf("Each block that contains a transient, has an infinite send time. ");
38     printf("The resultant array is written to a DATfile.\n\n");
39     return 0;
40   }
41 
42   FileWrapper pcm_file = FileWrapper::OpenReadOnly(argv[1]);
43   if (!pcm_file.is_open()) {
44     printf("\nThe %s could not be opened.\n\n", argv[1]);
45     return -1;
46   }
47 
48   FileWrapper dat_file = FileWrapper::OpenWriteOnly(argv[2]);
49   if (!dat_file.is_open()) {
50     printf("\nThe %s could not be opened.\n\n", argv[2]);
51     return -1;
52   }
53 
54   int chunk_size_ms = atoi(argv[3]);
55   if (chunk_size_ms <= 0) {
56     printf("\nThe chunkSize must be a positive integer\n\n");
57     return -1;
58   }
59 
60   int sample_rate_hz = atoi(argv[4]);
61   if (sample_rate_hz <= 0) {
62     printf("\nThe sampleRate must be a positive integer\n\n");
63     return -1;
64   }
65 
66   TransientDetector detector(sample_rate_hz);
67   int lost_packets = 0;
68   size_t audio_buffer_length = chunk_size_ms * sample_rate_hz / 1000;
69   std::unique_ptr<float[]> audio_buffer(new float[audio_buffer_length]);
70   std::vector<float> send_times;
71 
72   // Read first buffer from the PCM test file.
73   size_t file_samples_read = ReadInt16FromFileToFloatBuffer(
74       &pcm_file, audio_buffer_length, audio_buffer.get());
75   for (int time = 0; file_samples_read > 0; time += chunk_size_ms) {
76     // Pad the rest of the buffer with zeros.
77     for (size_t i = file_samples_read; i < audio_buffer_length; ++i) {
78       audio_buffer[i] = 0.0;
79     }
80     float value =
81         detector.Detect(audio_buffer.get(), audio_buffer_length, NULL, 0);
82     if (value < 0.5f) {
83       value = time;
84     } else {
85       value = FLT_MAX;
86       ++lost_packets;
87     }
88     send_times.push_back(value);
89 
90     // Read next buffer from the PCM test file.
91     file_samples_read = ReadInt16FromFileToFloatBuffer(
92         &pcm_file, audio_buffer_length, audio_buffer.get());
93   }
94 
95   size_t floats_written =
96       WriteFloatBufferToFile(&dat_file, send_times.size(), &send_times[0]);
97 
98   if (floats_written == 0) {
99     printf("\nThe send times could not be written to DAT file\n\n");
100     return -1;
101   }
102 
103   pcm_file.Close();
104   dat_file.Close();
105 
106   return lost_packets;
107 }
108