~ubuntu-branches/ubuntu/vivid/soundscaperenderer/vivid

« back to all changes in this revision

Viewing changes to apf/examples/jack_matrix.cpp

  • Committer: Package Import Robot
  • Author(s): IOhannes m zmölnig (Debian/GNU)
  • Date: 2014-05-08 16:58:09 UTC
  • Revision ID: package-import@ubuntu.com-20140508165809-7tz9dhu5pvo5wy25
Tags: upstream-0.4.1~dfsg
Import upstream version 0.4.1~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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           *
 
5
 *                                                                            *
 
6
 * This file is part of the Audio Processing Framework (APF).                 *
 
7
 *                                                                            *
 
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.                                                         *
 
12
 *                                                                            *
 
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.                       *
 
17
 *                                                                            *
 
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/>.            *
 
20
 *                                                                            *
 
21
 *                                 http://AudioProcessingFramework.github.com *
 
22
 ******************************************************************************/
 
23
 
 
24
// A small (static) example of the MimoProcessor with the fixed_matrix class.
 
25
// This is a stand-alone program.
 
26
 
 
27
#include <iostream>
 
28
#include <cassert>  // for assert()
 
29
 
 
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
 
34
 
 
35
class MatrixProcessor : public apf::MimoProcessor<MatrixProcessor
 
36
                        , apf::jack_policy
 
37
                        , apf::posix_thread_policy>
 
38
{
 
39
  public:
 
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;
 
45
 
 
46
    using Input = MimoProcessorBase::DefaultInput;
 
47
 
 
48
    class m1_channel;
 
49
    class m2_channel;
 
50
    class m3_slice;
 
51
    class Output;
 
52
 
 
53
    explicit MatrixProcessor(const apf::parameter_map& p);
 
54
 
 
55
    ~MatrixProcessor()
 
56
    {
 
57
      this->deactivate();
 
58
      _m3_list.clear();
 
59
      _m2_list.clear();
 
60
      _m1_list.clear();
 
61
    }
 
62
 
 
63
    APF_PROCESS(MatrixProcessor, MimoProcessorBase)
 
64
    {
 
65
      _process_list(_m1_list);
 
66
      _process_list(_m2_list);
 
67
      _process_list(_m3_list);
 
68
    }
 
69
 
 
70
  private:
 
71
    /// make sure blocksize is divisible by parts.
 
72
    static int _get_parts(int x, int blocksize)
 
73
    {
 
74
      int parts = x;
 
75
      while (blocksize % parts != 0) parts /= 2;
 
76
      return parts;
 
77
    }
 
78
 
 
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;
 
82
};
 
83
 
 
84
class MatrixProcessor::m1_channel : public ProcessItem<m1_channel>
 
85
{
 
86
  public:
 
87
    struct Params
 
88
    {
 
89
      Params() : input(nullptr), part(0), part_size(0) {}
 
90
      Channel channel;
 
91
      const Input* input;
 
92
      int part, part_size;
 
93
    };
 
94
 
 
95
    class Setup
 
96
    {
 
97
      public:
 
98
        Setup(int parts, int part_length, const rtlist_proxy<Input>& input_list)
 
99
          : _part(0)
 
100
          , _parts(parts)
 
101
          , _part_length(part_length)
 
102
          , _input(input_list.begin())
 
103
        {}
 
104
 
 
105
        m1_channel* operator()(const Channel& channel)
 
106
        {
 
107
          Params p;
 
108
          p.channel = channel;
 
109
          p.input = &*_input;
 
110
          p.part_size = _part_length;
 
111
          p.part = _part;
 
112
 
 
113
          ++_part;
 
114
          if (_part >= _parts)
 
115
          {
 
116
            _part = 0;
 
117
            ++_input;
 
118
          }
 
119
          return new m1_channel(p);
 
120
        }
 
121
 
 
122
      private:
 
123
        int _part;
 
124
        const int _parts, _part_length;
 
125
        rtlist_proxy<Input>::iterator _input;
 
126
    };
 
127
 
 
128
    APF_PROCESS(m1_channel, ProcessItem<m1_channel>)
 
129
    {
 
130
      assert(_input != nullptr);
 
131
      auto begin = _input->begin() + _part * _part_size;
 
132
      std::copy(begin, begin + _part_size, _channel.begin());
 
133
    }
 
134
 
 
135
  private:
 
136
    m1_channel(const Params& p)
 
137
      : _channel(p.channel)
 
138
      , _input(p.input)
 
139
      , _part(p.part)
 
140
      , _part_size(p.part_size)
 
141
    {}
 
142
 
 
143
    Channel _channel;
 
144
    const Input* const _input;
 
145
    const int _part, _part_size;
 
146
};
 
147
 
 
148
class MatrixProcessor::m2_channel : public ProcessItem<m2_channel>
 
149
{
 
150
  public:
 
151
    struct Params { Channel channel; Slice input; };
 
152
 
 
153
    static m2_channel* create(const Channel& channel, const Slice& input)
 
154
    {
 
155
      Params temp;
 
156
      temp.channel = channel;
 
157
      temp.input   = input;
 
158
      return new m2_channel(temp);
 
159
    }
 
160
 
 
161
    APF_PROCESS(m2_channel, ProcessItem<m2_channel>)
 
162
    {
 
163
      std::copy(_input.begin(), _input.end(), _channel.begin());
 
164
    }
 
165
 
 
166
  private:
 
167
    m2_channel(const Params& p) : _channel(p.channel) , _input(p.input) {}
 
168
 
 
169
    Channel _channel;
 
170
    Slice _input;
 
171
};
 
172
 
 
173
class MatrixProcessor::m3_slice : public ProcessItem<m3_slice>
 
174
{
 
175
  public:
 
176
    struct Params { Slice slice; Channel input; };
 
177
 
 
178
    static m3_slice* create(const Slice& slice, const Channel& input)
 
179
    {
 
180
      Params temp;
 
181
      temp.slice = slice;
 
182
      temp.input = input;
 
183
      return new m3_slice(temp);
 
184
    }
 
185
 
 
186
    APF_PROCESS(m3_slice, ProcessItem<m3_slice>)
 
187
    {
 
188
      std::copy(_input.begin(), _input.end(), _slice.begin());
 
189
    }
 
190
 
 
191
  private:
 
192
    m3_slice(const Params& p) : _slice(p.slice), _input(p.input) {}
 
193
 
 
194
    Slice _slice;
 
195
    Channel _input;
 
196
};
 
197
 
 
198
class MatrixProcessor::Output : public MimoProcessorBase::DefaultOutput
 
199
{
 
200
  public:
 
201
    struct Params : MimoProcessorBase::DefaultOutput::Params
 
202
    {
 
203
      std::list<Channel> channel_list;
 
204
    };
 
205
 
 
206
    explicit Output(const Params& p)
 
207
      : MimoProcessorBase::DefaultOutput(p)
 
208
      , _channel_list(p.channel_list)
 
209
    {}
 
210
 
 
211
    APF_PROCESS(Output, MimoProcessorBase::DefaultOutput)
 
212
    {
 
213
      auto out = this->begin();
 
214
 
 
215
      for (const auto& ch: _channel_list)
 
216
      {
 
217
        out = std::copy(ch.begin(), ch.end(), out);
 
218
      }
 
219
      assert(out = this->end());
 
220
    }
 
221
 
 
222
  private:
 
223
    std::list<Channel> _channel_list;
 
224
};
 
225
 
 
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)
 
236
  , _m1_list(_fifo)
 
237
  , _m2_list(_fifo)
 
238
  , _m3_list(_fifo)
 
239
{
 
240
  std::cout << "channels: " << _channels << ", parts: " << _parts
 
241
    << ", blocksize: " << _blocksize << std::endl;
 
242
 
 
243
  std::cout << "Creating Matrix with "
 
244
    << _part_channels << " channels and "
 
245
    << _part_length << " slices." << std::endl;
 
246
 
 
247
  // first, set parameters for all inputs ...
 
248
  Input::Params ip;
 
249
  for (int i = 1; i <= _channels; ++i)
 
250
  {
 
251
    ip.set("id", i);
 
252
    this->add(ip);
 
253
  }
 
254
 
 
255
  // m1: input channels are split up in more (and smaller) channels
 
256
 
 
257
  m1_channel::Setup m1_setup(_parts, _part_length, this->get_input_list());
 
258
  for (const auto& ch: _m1.channels)
 
259
  {
 
260
    _m1_list.add(m1_setup(ch));
 
261
  }
 
262
 
 
263
  // m2: reading slices from first matrix and writing to channels of second
 
264
  // matrix (= transpose matrix)
 
265
 
 
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());
 
270
 
 
271
  // m3: reading channels, writing slices
 
272
 
 
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());
 
277
 
 
278
  // set parameters for all outputs ...
 
279
  Output::Params op;
 
280
  op.parent = this;
 
281
  auto next_channel = _m3.channels.begin();
 
282
  for (int i = 1; i <= _channels; ++i)
 
283
  {
 
284
    op.set("id", i);
 
285
    op.channel_list.clear();
 
286
    for (int j = 0; j < _parts; ++j)
 
287
    {
 
288
      op.channel_list.push_back(*next_channel++);
 
289
    }
 
290
    this->add(op);
 
291
  }
 
292
 
 
293
  this->activate();
 
294
}
 
295
 
 
296
int main()
 
297
{
 
298
  apf::parameter_map p;
 
299
  p.set("channels", 2);
 
300
  //p.set("channels", 120);
 
301
  p.set("threads", 2);
 
302
  MatrixProcessor engine(p);
 
303
  sleep(60);
 
304
}
 
305
 
 
306
// Settings for Vim (http://www.vim.org/), please do not remove:
 
307
// vim:softtabstop=2:shiftwidth=2:expandtab:textwidth=80:cindent