~ubuntu-branches/ubuntu/wily/ecasound2.2/wily

« back to all changes in this revision

Viewing changes to libecasound/audioio-tone.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Junichi Uekawa
  • Date: 2008-09-26 09:58:52 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20080926095852-k3v9ewhmxpaltusw
Tags: 2.5.2-3
yodl 2.13.1 removed --unique-output option. Remove --unique-output
accordingly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ------------------------------------------------------------------------
 
2
// audioio-tone.cpp: Tone generator
 
3
//
 
4
// Adaptation to Ecasound:
 
5
// Copyright (C) 2007,2008 Kai Vehmanen (adaptation to Ecasound)
 
6
//
 
7
// Sources for sine generation (cmt-src-1.15/src/sine.cpp):
 
8
//
 
9
// Computer Music Toolkit - a library of LADSPA plugins. Copyright (C)
 
10
// 2000-2002 Richard W.E. Furse. The author may be contacted at
 
11
// richard@muse.demon.co.uk.
 
12
//
 
13
// Attributes:
 
14
//     eca-style-version: 3 (see Ecasound Programmer's Guide)
 
15
//
 
16
// This program is free software; you can redistribute it and/or modify
 
17
// it under the terms of the GNU General Public License as published by
 
18
// the Free Software Foundation; either version 2 of the License, or
 
19
// (at your option) any later version.
 
20
// 
 
21
// This program is distributed in the hope that it will be useful,
 
22
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
23
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
24
// GNU General Public License for more details.
 
25
// 
 
26
// You should have received a copy of the GNU General Public License
 
27
// along with this program; if not, write to the Free Software
 
28
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 
29
// ------------------------------------------------------------------------
 
30
 
 
31
#include <algorithm>
 
32
#include <string>
 
33
#include <iostream>
 
34
#include <fstream>
 
35
#include <cstdlib>
 
36
 
 
37
#include <math.h> /* C++'s standard <cmath> does not define M_PI */
 
38
 
 
39
#include <kvu_message_item.h>
 
40
#include <kvu_numtostr.h>
 
41
#include <kvu_dbc.h>
 
42
 
 
43
#include "eca-object-factory.h"
 
44
#include "samplebuffer.h"
 
45
#include "audioio-tone.h"
 
46
 
 
47
#include "eca-error.h"
 
48
#include "eca-logger.h"
 
49
 
 
50
/**
 
51
 * FIXME notes  (last update 2008-03-06)
 
52
 *
 
53
 *  - define the syntax: is this 'tone', 'sinetone', 
 
54
 *    'tone=sine', ..., or?
 
55
 *  - add support for multichannel testing (different
 
56
 *    frequnecies for different channels?)
 
57
 */
 
58
 
 
59
using std::cout;
 
60
using std::endl;
 
61
using std::atof;
 
62
using std::string;
 
63
 
 
64
/* Sine table size is given by (1 << SINE_TABLE_BITS). */
 
65
#define SINE_TABLE_BITS 14
 
66
#define SINE_TABLE_SHIFT (8 * sizeof(unsigned long) - SINE_TABLE_BITS)
 
67
 
 
68
SAMPLE_SPECS::sample_t *g_pfSineTable = NULL;
 
69
SAMPLE_SPECS::sample_t g_fPhaseStepBase = 0;
 
70
 
 
71
static void initialise_sine_wavetable(void)
 
72
{
 
73
  if (g_pfSineTable == NULL) {
 
74
    unsigned long lTableSize = (1 << SINE_TABLE_BITS);
 
75
    double dShift = (double(M_PI) * 2) / lTableSize;
 
76
    g_pfSineTable = new SAMPLE_SPECS::sample_t[lTableSize];
 
77
    if (g_pfSineTable != NULL)
 
78
      for (unsigned long lIndex = 0; lIndex < lTableSize; lIndex++)
 
79
        g_pfSineTable[lIndex] = SAMPLE_SPECS::sample_t(sin(dShift * lIndex));
 
80
  }
 
81
  if (g_fPhaseStepBase == 0) {
 
82
    g_fPhaseStepBase = (SAMPLE_SPECS::sample_t)pow(2, sizeof(unsigned long) * 8);
 
83
  }
 
84
}
 
85
 
 
86
AUDIO_IO_TONE::AUDIO_IO_TONE (const std::string& name) 
 
87
  :  m_lPhaseStep(0), 
 
88
     m_fCachedFrequency(0),
 
89
     m_fLimitFrequency(0),
 
90
     m_fPhaseStepScalar(0)
 
91
{
 
92
  set_label(name);
 
93
  initialise_sine_wavetable();
 
94
}
 
95
 
 
96
AUDIO_IO_TONE::~AUDIO_IO_TONE(void)
 
97
{
 
98
}
 
99
 
 
100
AUDIO_IO_TONE* AUDIO_IO_TONE::clone(void) const
 
101
{
 
102
  AUDIO_IO_TONE* target = new AUDIO_IO_TONE();
 
103
 
 
104
  for(int n = 0; n < number_of_params(); n++) {
 
105
    target->set_parameter(n + 1, get_parameter(n + 1));
 
106
  }
 
107
 
 
108
  target->set_position_in_samples(position_in_samples());
 
109
  if (ECA_AUDIO_POSITION::length_set())
 
110
    target->ECA_AUDIO_POSITION::set_length_in_samples(ECA_AUDIO_POSITION::length_in_samples());
 
111
 
 
112
  target->buffersize_rep = buffersize_rep;
 
113
  target->finished_rep = finished_rep;
 
114
  target->m_lPhase = m_lPhase;
 
115
  target->m_lPhaseStep = m_lPhaseStep;
 
116
  DBC_CHECK(target->m_fCachedFrequency == m_fCachedFrequency);
 
117
  target->m_fLimitFrequency = m_fLimitFrequency;
 
118
  target->m_fPhaseStepScalar = m_fPhaseStepScalar;
 
119
 
 
120
  return target;
 
121
}
 
122
 
 
123
void AUDIO_IO_TONE::open(void) throw(AUDIO_IO::SETUP_ERROR &)
 
124
{
 
125
  DBC_CHECK(samples_per_second() != 0);
 
126
 
 
127
  if (io_mode() != AUDIO_IO::io_read)
 
128
    throw(SETUP_ERROR(SETUP_ERROR::io_mode, "AUDIO_IO_TONE: Writing to tone generator not allowed!"));
 
129
 
 
130
  finished_rep = false;
 
131
  m_fLimitFrequency
 
132
    = SAMPLE_SPECS::sample_t(samples_per_second() * 0.5);
 
133
  m_fPhaseStepScalar
 
134
    = SAMPLE_SPECS::sample_t(g_fPhaseStepBase / samples_per_second());
 
135
 
 
136
  /* recalculate m_fLimitFrequency and mfPhaseStepScalar */
 
137
  if (m_fCachedFrequency) 
 
138
    setPhaseStepFromFrequency(m_fCachedFrequency, true);
 
139
 
 
140
  AUDIO_IO::open();
 
141
}
 
142
 
 
143
void AUDIO_IO_TONE::close(void)
 
144
{
 
145
  AUDIO_IO::close();
 
146
}
 
147
 
 
148
bool AUDIO_IO_TONE::finite_length_stream(void) const
 
149
{
 
150
  return ECA_AUDIO_POSITION::length_set();
 
151
}
 
152
 
 
153
void AUDIO_IO_TONE::read_buffer(SAMPLE_BUFFER* sbuf)
 
154
{
 
155
  /* write to sbuf->buffer[ch], similarly as the LADSPA
 
156
   * chainops */
 
157
 
 
158
  sbuf->number_of_channels(channels());
 
159
 
 
160
  /* set the length according to our buffersize */
 
161
  if (ECA_AUDIO_POSITION::length_set() &&
 
162
      (position_in_samples() + buffersize()) 
 
163
      >= ECA_AUDIO_POSITION::length_in_samples()) {
 
164
    /* over requested duration, adjust buffersize */
 
165
    sbuf->length_in_samples(ECA_AUDIO_POSITION::length_in_samples() 
 
166
                            - position_in_samples());
 
167
    finished_rep = true;
 
168
  }
 
169
  else
 
170
    sbuf->length_in_samples(buffersize());
 
171
  
 
172
  i.init(sbuf);
 
173
  i.begin();
 
174
 
 
175
  while(!i.end()) {
 
176
    for(int n = 0; n < channels(); n++) {
 
177
      if (i.end()) 
 
178
        break;
 
179
 
 
180
      *(i.current(n)) 
 
181
        = g_pfSineTable[m_lPhase >> SINE_TABLE_SHIFT];
 
182
 
 
183
    }
 
184
 
 
185
    m_lPhase += m_lPhaseStep;
 
186
 
 
187
    i.next();
 
188
  }
 
189
 
 
190
  change_position_in_samples(sbuf->length_in_samples());
 
191
}
 
192
 
 
193
void AUDIO_IO_TONE::write_buffer(SAMPLE_BUFFER* sbuf)
 
194
{
 
195
  /* NOP */
 
196
  DBC_CHECK(false);
 
197
}
 
198
 
 
199
SAMPLE_SPECS::sample_pos_t AUDIO_IO_TONE::seek_position(SAMPLE_SPECS::sample_pos_t pos)
 
200
{
 
201
  /* note: phase must be correct after arbitrary seeks */
 
202
  m_lPhase = m_lPhaseStep * pos;
 
203
 
 
204
  if (ECA_AUDIO_POSITION::length_set() == true &&
 
205
      pos <
 
206
      ECA_AUDIO_POSITION::length_in_samples())
 
207
    finished_rep = false;
 
208
 
 
209
  return pos;
 
210
}
 
211
 
 
212
void AUDIO_IO_TONE::setPhaseStepFromFrequency(const SAMPLE_SPECS::sample_t fFrequency, bool force)
 
213
{
 
214
  if (fFrequency != m_fCachedFrequency || force == true) {
 
215
    if (fFrequency >= 0 && fFrequency < m_fLimitFrequency) 
 
216
      m_lPhaseStep = (unsigned long)(m_fPhaseStepScalar * fFrequency);
 
217
    else 
 
218
      m_lPhaseStep = 0;
 
219
    m_fCachedFrequency = fFrequency;
 
220
  }
 
221
}
 
222
 
 
223
void AUDIO_IO_TONE::set_parameter(int param, 
 
224
                                  string value)
 
225
{
 
226
  ECA_LOG_MSG(ECA_LOGGER::user_objects, 
 
227
              AUDIO_IO::parameter_set_to_string(param, value));
 
228
 
 
229
  switch (param)
 
230
    {
 
231
    case 1: 
 
232
      {
 
233
        AUDIO_IO::set_parameter (param, value);
 
234
        break;
 
235
      }
 
236
    case 2:
 
237
      {
 
238
        /* type; only "sine" supported */
 
239
        break;
 
240
      }
 
241
    case 3: 
 
242
      {
 
243
        setPhaseStepFromFrequency (atof(value.c_str()), false);
 
244
        break;
 
245
      }
 
246
    case 4:
 
247
      {
 
248
        double duration = atof(value.c_str());
 
249
        if (duration > 0.0f)
 
250
          ECA_AUDIO_POSITION::set_length_in_seconds(duration);
 
251
        break;
 
252
      }
 
253
    }
 
254
}
 
255
 
 
256
string AUDIO_IO_TONE::get_parameter(int param) const
 
257
{
 
258
  switch (param) 
 
259
    {
 
260
    case 1: return AUDIO_IO::get_parameter(param);
 
261
    case 2: return "sine";
 
262
    case 3: return kvu_numtostr(m_fCachedFrequency);
 
263
    case 4: 
 
264
      {
 
265
        if (ECA_AUDIO_POSITION::length_set() == true)
 
266
          return kvu_numtostr(ECA_AUDIO_POSITION::length_in_seconds_exact());
 
267
        else
 
268
          return kvu_numtostr(-1.0f);
 
269
      }
 
270
    default: break;
 
271
    }
 
272
 
 
273
  return std::string();
 
274
}