-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathwav_analyzer.cpp
106 lines (79 loc) · 2.82 KB
/
wav_analyzer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <algorithm>
#include <functional>
#include <iostream>
#include "pitch_detection.h"
#include <gflags/gflags.h>
#include <libnyquist/Decoders.h>
DEFINE_double(timeslice, 0.1, "Time slice");
template <class T>
std::vector<T>
get_chunks(T container, size_t k)
{
std::vector<T> ret;
size_t size = container.size();
size_t i = 0;
if (size > k) {
for (; i < size - k; i += k) {
ret.push_back(T(container.begin() + i, container.begin() + i + k));
}
}
if (i % k) {
ret.push_back(
T(container.begin() + i, container.begin() + i + (i % k)));
}
return ret;
}
int
main(int argc, char **argv)
{
gflags::SetUsageMessage("help\n");
gflags::ParseCommandLineFlags(&argc, &argv, true);
std::cout << "Slicing wav file into chunks of " << FLAGS_timeslice
<< " seconds..." << std::endl;
nqr::NyquistIO loader;
if (argc != 2) {
std::cerr << "Usage: wav_analyzer /path/to/audio/file" << std::endl;
return -1;
}
std::shared_ptr<nqr::AudioData> file_data =
std::make_shared<nqr::AudioData>();
loader.Load(file_data.get(), argv[1]);
std::cout << "Audio file info:" << std::endl;
std::cout << "\tsample rate: " << file_data->sampleRate << std::endl;
std::cout << "\tlen samples: " << file_data->samples.size() << std::endl;
std::cout << "\tframe size: " << file_data->frameSize << std::endl;
std::cout << "\tseconds: " << file_data->lengthSeconds << std::endl;
std::cout << "\tchannels: " << file_data->channelCount << std::endl;
std::transform(file_data->samples.begin(), file_data->samples.end(),
file_data->samples.begin(),
std::bind(std::multiplies<float>(), std::placeholders::_1, 10000));
std::vector<float> audio;
if (file_data->channelCount == 2) {
// convert stereo to mono
std::vector<float> audio_copy(file_data->samples.size() / 2);
nqr::StereoToMono(file_data->samples.data(), audio_copy.data(),
file_data->samples.size());
audio = std::vector<float>(audio_copy.begin(), audio_copy.end());
} else {
audio = std::vector<float>(
file_data->samples.begin(), file_data->samples.end());
}
auto sample_rate = file_data->sampleRate;
auto chunk_size = size_t(sample_rate * FLAGS_timeslice);
auto chunks = get_chunks(audio, chunk_size);
std::cout << "Slicing buffer size " << audio.size() << " into "
<< chunks.size() << " chunks of size " << chunk_size << std::endl;
double t = 0.;
for (auto chunk : chunks) {
std::cout << "At t: " << t << std::endl;
auto pitch_mpm = pitch::mpm(chunk, sample_rate);
auto pitch_yin = pitch::yin(chunk, sample_rate);
auto pitch_pmpm = pitch::pmpm(chunk, sample_rate);
auto pitch_pyin = pitch::pyin(chunk, sample_rate);
std::cout << "\tmpm: " << pitch_mpm << "\n\tyin: " << pitch_yin
<< "\n\tpmpm: " << pitch_pmpm << "\n\tpyin: " << pitch_pyin
<< std::endl;
t += FLAGS_timeslice;
}
return 0;
}