1
/******************************************************************************
2
* Copyright © 2012-2014 Institut für Nachrichtentechnik, Universität Rostock *
3
* Copyright © 2006-2012 Quality & Usability Lab, *
4
* Telekom Innovation Laboratories, TU Berlin *
6
* This file is part of the Audio Processing Framework (APF). *
8
* The APF is free software: you can redistribute it and/or modify it under *
9
* the terms of the GNU General Public License as published by the Free *
10
* Software Foundation, either version 3 of the License, or (at your option) *
11
* any later version. *
13
* The APF is distributed in the hope that it will be useful, but WITHOUT ANY *
14
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
15
* FOR A PARTICULAR PURPOSE. *
16
* See the GNU General Public License for more details. *
18
* You should have received a copy of the GNU General Public License along *
19
* with this program. If not, see <http://www.gnu.org/licenses/>. *
21
* http://AudioProcessingFramework.github.com *
22
******************************************************************************/
24
// A small (static) example of the MimoProcessor with the fixed_matrix class.
25
// This is a stand-alone program.
28
#include <cassert> // for assert()
30
#include "apf/mimoprocessor.h"
31
#include "apf/jack_policy.h"
32
#include "apf/posix_thread_policy.h"
33
#include "apf/container.h" // for fixed_matrix
35
class MatrixProcessor : public apf::MimoProcessor<MatrixProcessor
37
, apf::posix_thread_policy>
40
using matrix_t = apf::fixed_matrix<sample_type>;
41
using channel_iterator = matrix_t::channel_iterator;
42
using slice_iterator = matrix_t::slice_iterator;
43
using Channel = matrix_t::Channel;
44
using Slice = matrix_t::Slice;
46
using Input = MimoProcessorBase::DefaultInput;
53
explicit MatrixProcessor(const apf::parameter_map& p);
63
APF_PROCESS(MatrixProcessor, MimoProcessorBase)
65
_process_list(_m1_list);
66
_process_list(_m2_list);
67
_process_list(_m3_list);
71
/// make sure blocksize is divisible by parts.
72
static int _get_parts(int x, int blocksize)
75
while (blocksize % parts != 0) parts /= 2;
79
const int _channels, _blocksize, _parts, _part_length, _part_channels;
80
matrix_t _m1, _m2, _m3;
81
rtlist_t _m1_list, _m2_list, _m3_list;
84
class MatrixProcessor::m1_channel : public ProcessItem<m1_channel>
89
Params() : input(nullptr), part(0), part_size(0) {}
98
Setup(int parts, int part_length, const rtlist_proxy<Input>& input_list)
101
, _part_length(part_length)
102
, _input(input_list.begin())
105
m1_channel* operator()(const Channel& channel)
110
p.part_size = _part_length;
119
return new m1_channel(p);
124
const int _parts, _part_length;
125
rtlist_proxy<Input>::iterator _input;
128
APF_PROCESS(m1_channel, ProcessItem<m1_channel>)
130
assert(_input != nullptr);
131
auto begin = _input->begin() + _part * _part_size;
132
std::copy(begin, begin + _part_size, _channel.begin());
136
m1_channel(const Params& p)
137
: _channel(p.channel)
140
, _part_size(p.part_size)
144
const Input* const _input;
145
const int _part, _part_size;
148
class MatrixProcessor::m2_channel : public ProcessItem<m2_channel>
151
struct Params { Channel channel; Slice input; };
153
static m2_channel* create(const Channel& channel, const Slice& input)
156
temp.channel = channel;
158
return new m2_channel(temp);
161
APF_PROCESS(m2_channel, ProcessItem<m2_channel>)
163
std::copy(_input.begin(), _input.end(), _channel.begin());
167
m2_channel(const Params& p) : _channel(p.channel) , _input(p.input) {}
173
class MatrixProcessor::m3_slice : public ProcessItem<m3_slice>
176
struct Params { Slice slice; Channel input; };
178
static m3_slice* create(const Slice& slice, const Channel& input)
183
return new m3_slice(temp);
186
APF_PROCESS(m3_slice, ProcessItem<m3_slice>)
188
std::copy(_input.begin(), _input.end(), _slice.begin());
192
m3_slice(const Params& p) : _slice(p.slice), _input(p.input) {}
198
class MatrixProcessor::Output : public MimoProcessorBase::DefaultOutput
201
struct Params : MimoProcessorBase::DefaultOutput::Params
203
std::list<Channel> channel_list;
206
explicit Output(const Params& p)
207
: MimoProcessorBase::DefaultOutput(p)
208
, _channel_list(p.channel_list)
211
APF_PROCESS(Output, MimoProcessorBase::DefaultOutput)
213
auto out = this->begin();
215
for (const auto& ch: _channel_list)
217
out = std::copy(ch.begin(), ch.end(), out);
219
assert(out = this->end());
223
std::list<Channel> _channel_list;
226
MatrixProcessor::MatrixProcessor(const apf::parameter_map& p)
227
: MimoProcessorBase(p)
228
, _channels(p.get<int>("channels")) // if no channels -> exception!
229
, _blocksize(this->block_size())
230
, _parts(_get_parts(16, _blocksize))
231
, _part_length(_blocksize / _parts)
232
, _part_channels(_channels * _parts)
233
, _m1(_part_channels, _part_length)
234
, _m2(_part_length, _part_channels)
235
, _m3(_part_channels, _part_length)
240
std::cout << "channels: " << _channels << ", parts: " << _parts
241
<< ", blocksize: " << _blocksize << std::endl;
243
std::cout << "Creating Matrix with "
244
<< _part_channels << " channels and "
245
<< _part_length << " slices." << std::endl;
247
// first, set parameters for all inputs ...
249
for (int i = 1; i <= _channels; ++i)
255
// m1: input channels are split up in more (and smaller) channels
257
m1_channel::Setup m1_setup(_parts, _part_length, this->get_input_list());
258
for (const auto& ch: _m1.channels)
260
_m1_list.add(m1_setup(ch));
263
// m2: reading slices from first matrix and writing to channels of second
264
// matrix (= transpose matrix)
266
std::list<m2_channel*> m2_temp;
267
std::transform(_m2.channels.begin(), _m2.channels.end(), _m1.slices.begin()
268
, back_inserter(m2_temp), m2_channel::create);
269
_m2_list.add(m2_temp.begin(), m2_temp.end());
271
// m3: reading channels, writing slices
273
std::list<m3_slice*> m3_temp;
274
std::transform(_m3.slices.begin(), _m3.slices.end(), _m2.channels.begin()
275
, back_inserter(m3_temp), m3_slice::create);
276
_m3_list.add(m3_temp.begin(), m3_temp.end());
278
// set parameters for all outputs ...
281
auto next_channel = _m3.channels.begin();
282
for (int i = 1; i <= _channels; ++i)
285
op.channel_list.clear();
286
for (int j = 0; j < _parts; ++j)
288
op.channel_list.push_back(*next_channel++);
298
apf::parameter_map p;
299
p.set("channels", 2);
300
//p.set("channels", 120);
302
MatrixProcessor engine(p);
306
// Settings for Vim (http://www.vim.org/), please do not remove:
307
// vim:softtabstop=2:shiftwidth=2:expandtab:textwidth=80:cindent