-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathFilterProject.cpp
More file actions
134 lines (110 loc) · 3.85 KB
/
FilterProject.cpp
File metadata and controls
134 lines (110 loc) · 3.85 KB
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
/* Perform filtering on audio samples
* - reads input from stdin and writes filtered samples to stdout
* - two channels (front left, front right)
* - samples in interleaved format (L R L R ...)
* - samples are 16-bit signed integers (what the Rpi needs)
*
* Usage:
* ./ffmpeg_decode cool_song.mp3 | ./filter | ./ffmpeg_play
*/
#include "FilterProject.h"
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string>
#include <memory>
using std::string;
using std::array;
using std::uint8_t;
using std::int16_t;
// Constructor implementation
FilterProject::FilterProject(float feedbackGain_) :
//initilize filters
allpass1(4410, 0.6),
allpass2(1470, -0.6),
allpass3(490, 0.6),
allpass4(163, -0.6),
// pass in FIR coefficients to the FIR filter class
firFilter({ 0.003369,0.002810,0.001758,0.000340,-0.001255,-0.002793,-0.004014,
-0.004659,-0.004516,-0.003464,-0.001514,0.001148,0.004157,0.006986,0.009003,
0.009571,0.008173,0.004560,-0.001120,-0.008222,-0.015581,-0.021579,-0.024323,
-0.021933,-0.012904,0.003500,0.026890,0.055537,0.086377,0.115331,0.137960,
0.150407,0.150407,0.137960,0.115331,0.086377,0.055537,0.026890,0.003500,
-0.012904,-0.021933,-0.024323,-0.021579,-0.015581,-0.008222,-0.001120,
0.004560,0.008173,0.009571,0.009003,0.006986,0.004157,0.001148,-0.001514,
-0.003464,-0.004516,-0.004659,-0.004014,-0.002793,-0.001255,0.000340,
0.001758,0.002810,0.003369 })
{
delay = std::make_unique<deque>(3*2*2940, 0.0);
feedbackGain = 0.25;
if (feedbackGain_ > 0 && feedbackGain_ < 1) {
feedbackGain = feedbackGain_;
}
}
// function to run on the samples from stdin
uint8_t* FilterProject::get_samples(uint8_t* samples, size_t num_samples) {
//convert the uint8_t samples to floating point
auto samples_cast = reinterpret_cast<int16_t*>(samples);
auto num_samples_cast = num_samples/sizeof(int16_t);
for (auto i = 0; i < num_samples_cast; i++) {
//filters on!
auto left_sample = samples_cast[i];
samples_cast[i] = do_filtering(left_sample);
++i;
auto right_sample = samples_cast[i];
samples_cast[i] = do_filtering(right_sample);
}
return reinterpret_cast<uint8_t*>(samples);
}
FilterProject::outType FilterProject::do_filtering(outType new_x) {
auto &d = *delay.get();
// the coefficient on the d.back() sets how long the reverb
// will sustain: larger = longer
auto x = 0.7*new_x + feedbackGain*d.back();
// run through the all pass filters
// chain the outputs end to end
auto y1 = allpass1.do_filtering(x);
auto y2 = allpass2.do_filtering(y1);
auto y3 = allpass3.do_filtering(y2);
auto y4 = allpass4.do_filtering(y3);
auto y5 = firFilter.do_filtering(y4);
d.pop_back();
d.push_front(y5);
//add a bit of an FIR filter here, smooth the output
auto reverb_signal = y5 + 0.5*d[2*2940] + 0.25*d[2*2*2940] + 0.125*d[3*2*2940];
auto y = 0.6*reverb_signal + new_x;
return y;
}
// ---------------------------------------------main --------------------------------------------------
int main(int argc, char** argv) {
if (argc != 1) {
fprintf(stderr, "usage: ./ffmpeg_decode <input file> | %s | ./ffmpeg_play\n", argv[0]);
exit(1);
}
//some constants
const int BUFF_SIZE = 4096;
array<uint8_t, BUFF_SIZE> buffer;
FilterProject reverb(0.25);
for (;;) {
// read input buffer from stdin
ssize_t ret = read(STDIN_FILENO, buffer.data(), buffer.size());
if (ret < 0) {
fprintf(stderr, "read(stdin)\n");
exit(1);
}
//exit if out of data
if (ret == 0) {
break;
}
// do the filtering
reverb.get_samples(buffer.data(), buffer.size());
// write output buffer to stdout
if (write(STDOUT_FILENO, buffer.data(), buffer.size()) != buffer.size()) {
fprintf(stderr, "error: write(stdout)\n");
exit(1);
}
}
return 0;
}