libvisual  0.5.0
lv_audio.cpp
1 /* Libvisual - The audio visualisation framework.
2  *
3  * Copyright (C) 2012 Libvisual team
4  * 2004-2006 Dennis Smit
5  *
6  * Authors: Chong Kai Xiong <kaixiong@codeleft.sg>
7  * Dennis Smit <ds@nerds-incorporated.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU Lesser General Public License as
11  * published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23 
24 #include "config.h"
25 #include "lv_audio.h"
26 #include "private/lv_audio_convert.hpp"
27 #include "private/lv_audio_stream.hpp"
28 #include "lv_common.h"
29 #include "lv_fourier.h"
30 #include "lv_math.h"
31 #include "lv_time.h"
32 #include "lv_util.hpp"
33 #include <cstdarg>
34 #include <unordered_map>
35 #include <vector>
36 
37 namespace LV {
38 
39  class AudioChannel;
40 
41  typedef std::unique_ptr<AudioChannel> AudioChannelPtr;
42 
43  class Audio::Impl
44  {
45  public:
46 
47  typedef std::unordered_map<std::string, AudioChannelPtr> ChannelList;
48 
49  ChannelList channels;
50 
51  void upload_to_channel (std::string const& name, BufferConstPtr const& samples, Time const& timestamp);
52 
53  AudioChannel* get_channel (std::string const& name) const;
54  };
55 
56  class AudioChannel
57  {
58  public:
59 
60  std::string name;
61  AudioStream stream;
62 
63  explicit AudioChannel (std::string const& name);
64 
65  ~AudioChannel ();
66 
67  // Non-copyable
68  AudioChannel (AudioChannel const&) = delete;
69  AudioChannel& operator= (AudioChannel const&) = delete;
70 
71  void add_samples (BufferConstPtr const& samples, Time const& timestamp);
72  };
73 
74  namespace {
75 
76  void sample_buffer_mix (BufferPtr const& dest, BufferPtr const& src, float multiplier)
77  {
78  visual_return_if_fail (dest->get_size () == src->get_size ());
79 
80  auto dbuf = static_cast<float*> (dest->get_data ());
81  auto const sbuf = static_cast<float const*> (src->get_data ());
82 
83  std::size_t scnt = dest->get_size () / sizeof (float);
84 
85  for (unsigned int i = 0; i < scnt; i++)
86  dbuf[i] += sbuf[i] * multiplier;
87  }
88 
89  } // anonymous
90 
91  void Audio::Impl::upload_to_channel (std::string const& name, BufferConstPtr const& samples, Time const& timestamp)
92  {
93  if (!get_channel (name)) {
94  channels[name] = make_unique<AudioChannel> (name);
95  }
96 
97  channels[name]->add_samples (samples, timestamp);
98  }
99 
100  AudioChannel* Audio::Impl::get_channel (std::string const& name) const
101  {
102  auto entry = channels.find (name);
103  return entry != channels.end () ? entry->second.get () : nullptr;
104  }
105 
106  AudioChannel::AudioChannel (std::string const& name_)
107  : name (name_)
108  {}
109 
110  AudioChannel::~AudioChannel ()
111  {
112  // empty
113  }
114 
115  void AudioChannel::add_samples (BufferConstPtr const& samples, Time const& timestamp)
116  {
117  stream.write (samples, timestamp);
118  }
119 
121  : m_impl (new Impl)
122  {
123  // empty
124  }
125 
127  : m_impl {std::move (rhs.m_impl)}
128  {
129  // empty
130  }
131 
133  {
134  // empty
135  }
136 
137  Audio& Audio::operator= (Audio&& rhs)
138  {
139  m_impl.swap (rhs.m_impl);
140  return *this;
141  }
142 
143  bool Audio::get_sample (BufferPtr const& buffer, std::string const& channel_name)
144  {
145  auto channel = m_impl->get_channel (channel_name);
146 
147  if (!channel) {
148  buffer->fill (0);
149  return false;
150  }
151 
152  channel->stream.read (buffer, buffer->get_size ());
153 
154  return true;
155  }
156 
157  void Audio::get_sample_mixed_simple (BufferPtr const& buffer, unsigned int channels, ...)
158  {
159  va_list args;
160 
161  va_start (args, channels);
162  get_sample_mixed_simple (buffer, channels, args);
163  va_end (args);
164  }
165 
166  void Audio::get_sample_mixed_simple (BufferPtr const& buffer, unsigned int channels, va_list args)
167  {
168  visual_return_if_fail (channels > 0);
169 
170  std::vector<std::string> channel_ids (channels);
171 
172  for (unsigned int i = 0; i < channels; i++)
173  channel_ids[i] = va_arg (args, const char *);
174 
175  float factor = 1.0 / channels;
176 
177  auto channel_samples = Buffer::create (buffer->get_size ());
178  buffer->fill (0);
179 
180  // The mixing loop
181  for (unsigned int i = 0; i < channels; i++) {
182  if (get_sample (channel_samples, channel_ids[i])) {
183  sample_buffer_mix (buffer, channel_samples, factor);
184  }
185  }
186  }
187 
188  void Audio::get_sample_mixed (BufferPtr const& buffer, bool divide, unsigned int channels, ...)
189  {
190  va_list args;
191 
192  va_start (args, channels);
193  get_sample_mixed (buffer, divide, channels, args);
194  va_end (args);
195  }
196 
197  void Audio::get_sample_mixed (BufferPtr const& buffer, bool divide, unsigned int channels, va_list args)
198  {
199  visual_return_if_fail (channels > 0);
200 
201  std::vector<std::string> channel_ids (channels);
202  for (unsigned int i = 0; i < channels; i++) {
203  channel_ids[i] = va_arg (args, const char *);
204  }
205 
206  std::vector<double> channel_factors (channels);
207  for (unsigned int i = 0; i < channels; i++)
208  channel_factors[i] = va_arg (args, double);
209 
210  float factor = divide ? (1.0 / channels) : 1.0;
211 
212  auto channel_samples = Buffer::create (buffer->get_size ());
213  buffer->fill (0);
214 
215  // The mixing loop
216  for (unsigned int i = 0; i < channels; i++) {
217  if (get_sample (channel_samples, channel_ids[i])) {
218  sample_buffer_mix (buffer, channel_samples, channel_factors[i] * factor);
219  }
220  }
221  }
222 
223  void Audio::get_spectrum (BufferPtr const& buffer, std::size_t samplelen, std::string const& channel_name, bool normalised)
224  {
225  auto sample = Buffer::create (samplelen);
226 
227  if (get_sample (sample, channel_name))
228  get_spectrum_for_sample (buffer, sample, normalised);
229  else
230  buffer->fill (0);
231  }
232 
233  void Audio::get_spectrum (BufferPtr const& buffer, std::size_t samplelen, std::string const& channel_name, bool normalised, float multiplier)
234  {
235  get_spectrum (buffer, samplelen, channel_name, normalised);
236 
237  auto data = static_cast<float*> (buffer->get_data ());
238  std::size_t datasize = buffer->get_size () / sizeof (float);
239 
240  visual_math_simd_mul_floats_float (data, data, multiplier, datasize);
241  }
242 
243  void Audio::get_spectrum_for_sample (BufferPtr const& buffer, BufferConstPtr const& sample, bool normalised)
244  {
245  DFT dft (buffer->get_size () / sizeof (float),
246  sample->get_size () / sizeof (float));
247 
248  // Fourier analyze the pcm data
249  dft.perform (static_cast<float*> (buffer->get_data ()),
250  static_cast<float*> (sample->get_data ()));
251 
252  if (normalised)
253  normalise_spectrum (buffer);
254  }
255 
256  void Audio::get_spectrum_for_sample (BufferPtr const& buffer, BufferConstPtr const& sample, bool normalised, float multiplier)
257  {
258  get_spectrum_for_sample (buffer, sample, normalised);
259 
260  auto data = static_cast<float*> (buffer->get_data ());
261  std::size_t datasize = buffer->get_size () / sizeof (float);
262 
263  visual_math_simd_mul_floats_float (data, data, multiplier, datasize);
264  }
265 
266  void Audio::normalise_spectrum (BufferPtr const& buffer)
267  {
268  DFT::log_scale_standard (static_cast<float*> (buffer->get_data ()),
269  static_cast<float*> (buffer->get_data ()),
270  buffer->get_size () / sizeof (float));
271  }
272 
273  void Audio::input (BufferPtr const& buffer,
274  VisAudioSampleRateType rate,
275  VisAudioSampleFormatType format,
276  VisAudioSampleChannelType channeltype)
277  {
278  auto timestamp = Time::now ();
279 
280  auto sample_count = buffer->get_size () / visual_audio_sample_format_get_size (format);
281 
282  auto converted_buffer = Buffer::create (sample_count * sizeof (float));
283 
284  AudioConvert::convert_samples (converted_buffer,
285  VISUAL_AUDIO_SAMPLE_FORMAT_FLOAT,
286  buffer,
287  format);
288 
289  switch (channeltype) {
290  case VISUAL_AUDIO_SAMPLE_CHANNEL_STEREO: {
291  auto samples1 = Buffer::create (sample_count/2 * sizeof (float));
292  auto samples2 = Buffer::create (sample_count/2 * sizeof (float));
293 
294  AudioConvert::deinterleave_stereo_samples (samples1, samples2, converted_buffer, VISUAL_AUDIO_SAMPLE_FORMAT_FLOAT);
295 
296  m_impl->upload_to_channel (VISUAL_AUDIO_CHANNEL_LEFT, samples1, timestamp);
297  m_impl->upload_to_channel (VISUAL_AUDIO_CHANNEL_RIGHT, samples2, timestamp);
298 
299  return;
300  }
301  default: {
302  visual_log (VISUAL_LOG_CRITICAL, "Only stereo input is currently supported");
303  return;
304  }
305  }
306  }
307 
308  void Audio::input (BufferPtr const& buffer,
309  VisAudioSampleRateType rate,
310  VisAudioSampleFormatType format,
311  std::string const& channel_name)
312  {
313  auto timestamp = Time::now ();
314 
315  auto sample_count = buffer->get_size () / visual_audio_sample_format_get_size (format);
316 
317  auto converted_buffer = Buffer::create (sample_count * sizeof (float));
318 
319  AudioConvert::convert_samples (converted_buffer,
320  VISUAL_AUDIO_SAMPLE_FORMAT_FLOAT,
321  buffer,
322  format);
323 
324  m_impl->upload_to_channel (channel_name, converted_buffer, timestamp);
325  }
326 
327 } // LV namespace
328 
329 visual_size_t visual_audio_sample_rate_get_length (VisAudioSampleRateType rate)
330 {
331  visual_return_val_if_fail (rate < VISUAL_AUDIO_SAMPLE_RATE_LAST, 0);
332 
333  static visual_size_t ratelengthtable[] = {
334  0, // VISUAL_AUDIO_SAMPLE_RATE_NONE
335  8000, // VISUAL_AUDIO_SAMPLE_RATE_8000
336  11250, // VISUAL_AUDIO_SAMPLE_RATE_11250
337  22500, // VISUAL_AUDIO_SAMPLE_RATE_22500
338  32000, // VISUAL_AUDIO_SAMPLE_RATE_32000
339  44100, // VISUAL_AUDIO_SAMPLE_RATE_44100
340  48000, // VISUAL_AUDIO_SAMPLE_RATE_48000
341  96000 // VISUAL_AUDIO_SAMPLE_RATE_96000
342  };
343 
344  return ratelengthtable[rate];
345 }
346 
347 visual_size_t visual_audio_sample_format_get_size (VisAudioSampleFormatType format)
348 {
349  visual_return_val_if_fail (format < VISUAL_AUDIO_SAMPLE_FORMAT_LAST, 0);
350 
351  static int formatsizetable[] = {
352  0, // VISUAL_AUDIO_SAMPLE_FORMAT_NONE
353  1, // VISUAL_AUDIO_SAMPLE_FORMAT_U8
354  1, // VISUAL_AUDIO_SAMPLE_FORMAT_S8
355  2, // VISUAL_AUDIO_SAMPLE_FORMAT_U16
356  2, // VISUAL_AUDIO_SAMPLE_FORMAT_S16
357  4, // VISUAL_AUDIO_SAMPLE_FORMAT_U32
358  4, // VISUAL_AUDIO_SAMPLE_FORMAT_S32
359  4 // VISUAL_AUDIO_SAMPLE_FORMAT_FLOAT
360  };
361 
362  return formatsizetable[format];
363 }
364 
365 int visual_audio_sample_format_is_signed (VisAudioSampleFormatType format)
366 {
367  visual_return_val_if_fail (format < VISUAL_AUDIO_SAMPLE_FORMAT_LAST, -1);
368 
369  static bool formatsignedtable[] = {
370  false, // VISUAL_AUDIO_SAMPLE_FORMAT_NONE
371  false, // VISUAL_AUDIO_SAMPLE_FORMAT_U8
372  true, // VISUAL_AUDIO_SAMPLE_FORMAT_S8
373  false, // VISUAL_AUDIO_SAMPLE_FORMAT_U16
374  true, // VISUAL_AUDIO_SAMPLE_FORMAT_S16
375  false, // VISUAL_AUDIO_SAMPLE_FORMAT_U32
376  true, // VISUAL_AUDIO_SAMPLE_FORMAT_S32
377  true // VISUAL_AUDIO_SAMPLE_FORMAT_FLOAT
378  };
379 
380  return formatsignedtable[format];
381 }