-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.cu
146 lines (111 loc) · 3.79 KB
/
main.cu
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <algorithm>
#include <functional>
#include <iomanip>
#include <iostream>
#include "BTrack.h"
#include <libnyquist/Decoders.h>
#include <libzen/hps.h>
#include <libzen/io.h>
static std::vector<std::pair<std::size_t, std::size_t>>
get_chunk_limits(std::vector<float>& container, size_t k)
{
std::vector<std::pair<std::size_t, std::size_t>> ret;
size_t size = container.size();
size_t i = 0;
if (size > k) {
for (; i < size - k; i += k) {
ret.push_back(std::pair<std::size_t, std::size_t>{i, i + k});
}
}
if (i % k) {
ret.push_back(std::pair<std::size_t, std::size_t>(i, i + (i % k)));
}
return ret;
}
int main(int argc, char** argv)
{
std::cout << std::fixed;
std::cout << std::setprecision(4);
std::size_t chunk_size = 256;
std::cout << "Slicing wav file into chunks of " << chunk_size
<< " samples..." << 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::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());
}
std::vector<float> percussive_out = audio;
auto sample_rate = file_data->sampleRate;
auto chunk_limits = get_chunk_limits(audio, chunk_size);
// this implementation of BTrack is fixed for a hop of 512
auto btrack1 = BTrack(sample_rate);
auto btrack2 = BTrack(sample_rate);
std::cout << "Slicing buffer size " << audio.size() << " into "
<< chunk_limits.size() << " chunks of size " << chunk_size
<< std::endl;
double t = 0.;
float timeslice = (( float )chunk_size) / (( float )sample_rate);
auto hpss = zen::hps::HPRRealtime<zen::Backend::GPU>(
file_data->sampleRate, chunk_size, 2.5, zen::hps::OUTPUT_PERCUSSIVE);
// need an io object to do some warming up
auto io = zen::io::IOGPU(chunk_size);
hpss.warmup(io);
std::size_t n = 0;
std::vector<float> beats1;
std::vector<float> beats2;
for (std::vector<std::pair<std::size_t, std::size_t>>::const_iterator chunk_it
= chunk_limits.begin();
chunk_it != chunk_limits.end(); ++chunk_it) {
// copy input samples into io object
std::copy(audio.data() + chunk_it->first,
audio.data() + chunk_it->second, io.host_in);
// process input samples
hpss.process_next_hop(io.device_in);
hpss.copy_percussive(io.device_out);
// copy output samples from io object
std::copy(
io.host_out, io.host_out + chunk_size, percussive_out.begin() + n);
btrack1.processHop(percussive_out.data() + chunk_it->first);
btrack2.processHop(audio.data() + chunk_it->first);
if (btrack1.beatDueInFrame) {
beats1.push_back(t);
}
if (btrack2.beatDueInFrame) {
beats2.push_back(t);
}
t += timeslice;
n += chunk_size;
}
std::cout << "+HPR beat timestamps: ";
for (auto elem : beats1) {
std::cout << elem << " ";
}
std::cout << "\n";
std::cout << "-HPR beat timestamps: ";
for (auto elem : beats2) {
std::cout << elem << " ";
}
std::cout << "\n";
return 0;
}