Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 144 lines (126 sloc) 4.5 kB
4d4d90b @hzeller o More legalese
authored
1 // Folve - A fuse filesystem that convolves audio files on-the-fly.
2 //
2fee1d6 @hzeller o extract sound processor
authored
3 // Copyright (C) 2012 Henner Zeller <h.zeller@acm.org>
b4eec5c @hzeller o libboost caused too many troubles in embedded systems with weak
authored
4 //
2fee1d6 @hzeller o extract sound processor
authored
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 #include "sound-processor.h"
19
20 #include <assert.h>
21 #include <string.h>
950f192 @hzeller o Wire up processor-pool to folve-filesystem.
authored
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
2fee1d6 @hzeller o extract sound processor
authored
25
b4eec5c @hzeller o libboost caused too many troubles in embedded systems with weak
authored
26 #include "util.h"
efe3975 @hzeller o Work around some threading bug in initialization of zita-convolver/…
authored
27
28 // There seems to be a bug somewhere inside the fftwf library or the use
29 // within Convproc::configure()
30 // It creates a double-delete somewhere if accessed with multiple threads.
b4eec5c @hzeller o libboost caused too many troubles in embedded systems with weak
authored
31 static folve::Mutex fftw_mutex;
efe3975 @hzeller o Work around some threading bug in initialization of zita-convolver/…
authored
32
2fee1d6 @hzeller o extract sound processor
authored
33 SoundProcessor *SoundProcessor::Create(const std::string &config_file,
34 int samplerate, int channels) {
35 ZitaConfig zita;
36 memset(&zita, 0, sizeof(zita));
37 zita.fsamp = samplerate;
38 zita.ninp = channels;
39 zita.nout = channels;
40 zita.convproc = new Convproc();
efe3975 @hzeller o Work around some threading bug in initialization of zita-convolver/…
authored
41 { // fftw threading bug workaround, see above.
b4eec5c @hzeller o libboost caused too many troubles in embedded systems with weak
authored
42 folve::MutexLock l(&fftw_mutex);
efe3975 @hzeller o Work around some threading bug in initialization of zita-convolver/…
authored
43 if ((config(&zita, config_file.c_str()) != 0)
44 || zita.convproc->inpdata(channels - 1) == NULL
45 || zita.convproc->outdata(channels - 1) == NULL) {
46 return NULL;
47 }
2fee1d6 @hzeller o extract sound processor
authored
48 }
9af16fe @hzeller o Gapless string should break when configuration changes.
authored
49 return new SoundProcessor(zita, config_file);
2fee1d6 @hzeller o extract sound processor
authored
50 }
51
950f192 @hzeller o Wire up processor-pool to folve-filesystem.
authored
52 static time_t GetModificationTime(const std::string &filename) {
53 struct stat st;
54 stat(filename.c_str(), &st);
55 return st.st_mtime;
56 }
57
9af16fe @hzeller o Gapless string should break when configuration changes.
authored
58 SoundProcessor::SoundProcessor(const ZitaConfig &config, const std::string &cfg)
59 : zita_config_(config), config_file_(cfg),
950f192 @hzeller o Wire up processor-pool to folve-filesystem.
authored
60 config_file_timestamp_(GetModificationTime(cfg)),
2fee1d6 @hzeller o extract sound processor
authored
61 buffer_(new float[config.fragm * config.ninp]),
62 channels_(config.ninp),
63 input_pos_(0), output_pos_(0),
64 max_out_value_observed_(0.0) {
65 Reset();
66 }
67
68 SoundProcessor::~SoundProcessor() {
69 zita_config_.convproc->stop_process();
70 zita_config_.convproc->cleanup();
71 delete zita_config_.convproc;
72 delete [] buffer_;
73 }
74
75 int SoundProcessor::FillBuffer(SNDFILE *in) {
76 const int samples_needed = zita_config_.fragm - input_pos_;
77 assert(samples_needed); // Otherwise, call WriteProcessed() first.
78 output_pos_ = -1;
79 int r = sf_readf_float(in, buffer_ + input_pos_ * channels_, samples_needed);
80 input_pos_ += r;
81 return r;
82 }
83
84 void SoundProcessor::WriteProcessed(SNDFILE *out, int sample_count) {
85 if (output_pos_ < 0) {
86 Process();
87 }
88 assert(sample_count <= zita_config_.fragm - output_pos_);
89 sf_writef_float(out, buffer_ + output_pos_ * channels_, sample_count);
90 output_pos_ += sample_count;
91 if (output_pos_ == zita_config_.fragm) {
92 input_pos_ = 0;
93 }
94 }
95
96 void SoundProcessor::Process() {
97 const int samples_missing = zita_config_.fragm - input_pos_;
98 if (samples_missing) {
99 memset(buffer_ + input_pos_ * channels_, 0x00,
100 samples_missing * channels_ * sizeof(float));
101 }
102
103 // Flatten channels: LRLRLRLRLR -> LLLLL and RRRRR
104 for (int ch = 0; ch < channels_; ++ch) {
105 float *dest = zita_config_.convproc->inpdata(ch);
106 for (int j = 0; j < input_pos_; ++j) {
107 dest[j] = buffer_[j * channels_ + ch];
108 }
109 }
110
111 zita_config_.convproc->process();
112
113 // Join channels again.
114 for (int ch = 0; ch < channels_; ++ch) {
115 float *source = zita_config_.convproc->outdata(ch);
116 for (int j = 0; j < input_pos_; ++j) {
117 buffer_[j * channels_ + ch] = source[j];
118 const float out_abs = source[j];
119 if (out_abs > max_out_value_observed_) {
120 max_out_value_observed_ = out_abs;
121 }
122 }
123 }
124 output_pos_ = 0;
125 }
126
950f192 @hzeller o Wire up processor-pool to folve-filesystem.
authored
127 bool SoundProcessor::ConfigStillUpToDate() const {
128 // TODO(hzeller): this should as well check if any *.wav file mentioned in
129 // config is still the same timestamp.
130 return config_file_timestamp_ == GetModificationTime(config_file_);
131 }
132
fb3fb9a @hzeller o Log clipping even if we pass on the processor.
authored
133 void SoundProcessor::ResetMaxValues() {
134 max_out_value_observed_ = 0.0;
135 }
136
2fee1d6 @hzeller o extract sound processor
authored
137 void SoundProcessor::Reset() {
138 zita_config_.convproc->reset();
139 input_pos_ = 0;
140 output_pos_ = -1;
fb3fb9a @hzeller o Log clipping even if we pass on the processor.
authored
141 ResetMaxValues();
2fee1d6 @hzeller o extract sound processor
authored
142 zita_config_.convproc->start_process(0, 0);
143 }
Something went wrong with that request. Please try again.