beeps 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/beeps/analyser.cpp +1 -1
  3. data/.doc/ext/beeps/{adsr.cpp → envelope.cpp} +20 -20
  4. data/.doc/ext/beeps/file_in.cpp +1 -1
  5. data/.doc/ext/beeps/gain.cpp +1 -1
  6. data/.doc/ext/beeps/mic_in.cpp +1 -1
  7. data/.doc/ext/beeps/native.cpp +4 -2
  8. data/.doc/ext/beeps/oscillator.cpp +1 -1
  9. data/.doc/ext/beeps/pitch_shift.cpp +1 -1
  10. data/.doc/ext/beeps/processor.cpp +1 -1
  11. data/.doc/ext/beeps/sequencer.cpp +87 -0
  12. data/.doc/ext/beeps/sound.cpp +1 -1
  13. data/.doc/ext/beeps/sound_player.cpp +1 -1
  14. data/.doc/ext/beeps/time_stretch.cpp +1 -1
  15. data/.github/workflows/release-gem.yml +1 -1
  16. data/.github/workflows/test.yml +3 -0
  17. data/ChangeLog.md +13 -0
  18. data/Gemfile.lock +1 -1
  19. data/LICENSE +21 -0
  20. data/Rakefile +3 -2
  21. data/VERSION +1 -1
  22. data/beeps.gemspec +2 -2
  23. data/ext/beeps/analyser.cpp +1 -1
  24. data/ext/beeps/defs.h +2 -0
  25. data/ext/beeps/{adsr.cpp → envelope.cpp} +20 -20
  26. data/ext/beeps/extconf.rb +11 -3
  27. data/ext/beeps/file_in.cpp +1 -1
  28. data/ext/beeps/gain.cpp +1 -1
  29. data/ext/beeps/mic_in.cpp +1 -1
  30. data/ext/beeps/native.cpp +4 -2
  31. data/ext/beeps/oscillator.cpp +1 -1
  32. data/ext/beeps/pitch_shift.cpp +1 -1
  33. data/ext/beeps/processor.cpp +1 -1
  34. data/ext/beeps/sequencer.cpp +92 -0
  35. data/ext/beeps/sound.cpp +1 -1
  36. data/ext/beeps/sound_player.cpp +1 -1
  37. data/ext/beeps/time_stretch.cpp +1 -1
  38. data/include/beeps/defs.h +7 -0
  39. data/include/beeps/filter.h +4 -4
  40. data/include/beeps/generator.h +31 -0
  41. data/include/beeps/ruby/beeps.h +1 -1
  42. data/include/beeps/ruby/exception.h +2 -2
  43. data/include/beeps/ruby/filter.h +16 -10
  44. data/include/beeps/ruby/generator.h +18 -5
  45. data/include/beeps/ruby/processor.h +2 -2
  46. data/include/beeps/ruby/sound.h +4 -4
  47. data/lib/beeps/extension.rb +4 -0
  48. data/lib/beeps/processor.rb +2 -2
  49. data/src/beeps.cpp +3 -1
  50. data/src/beeps.h +22 -0
  51. data/src/{adsr.cpp → envelope.cpp} +21 -20
  52. data/src/openal.cpp +3 -1
  53. data/src/oscillator.cpp +75 -44
  54. data/src/osx/beeps.mm +19 -0
  55. data/src/processor.cpp +59 -49
  56. data/src/processor.h +30 -14
  57. data/src/sequencer.cpp +160 -0
  58. data/src/signals.cpp +45 -29
  59. data/src/signals.h +4 -4
  60. data/src/sound.cpp +32 -29
  61. data/src/win32/beeps.cpp +36 -0
  62. data/src/win32/exception.cpp +40 -0
  63. data/src/win32/exception.h +40 -0
  64. data/src/win32/signals.cpp +186 -0
  65. metadata +21 -10
data/src/signals.cpp CHANGED
@@ -27,7 +27,9 @@ namespace Beeps
27
27
  Signals
28
28
  Signals_create (uint capacity, uint nchannels, double sample_rate)
29
29
  {
30
- if (capacity <= 0 || nchannels <= 0)
30
+ if (capacity <= 0)
31
+ argument_error(__FILE__, __LINE__);
32
+ if (nchannels <= 0)
31
33
  argument_error(__FILE__, __LINE__);
32
34
 
33
35
  if (sample_rate <= 0) sample_rate = Beeps::sample_rate();
@@ -43,7 +45,11 @@ namespace Beeps
43
45
  const float* const* channels,
44
46
  uint nsamples, uint nchannels, double sample_rate)
45
47
  {
46
- if (!channels || nsamples <= 0 || nchannels <= 0)
48
+ if (!channels)
49
+ argument_error(__FILE__, __LINE__);
50
+ if (nsamples <= 0)
51
+ argument_error(__FILE__, __LINE__);
52
+ if (nchannels <= 0)
47
53
  argument_error(__FILE__, __LINE__);
48
54
 
49
55
  if (sample_rate <= 0) sample_rate = Beeps::sample_rate();
@@ -64,19 +70,32 @@ namespace Beeps
64
70
  }
65
71
 
66
72
  void
67
- Signals_resize (Signals* signals, uint capacity)
73
+ Signals_clear (Signals* signals)
68
74
  {
69
- if (!signals || !*signals || capacity <= 0)
75
+ if (!signals)
76
+ argument_error(__FILE__, __LINE__);
77
+
78
+ signals->self->nsamples = 0;
79
+ }
80
+
81
+ void
82
+ Signals_clear (Signals* signals, uint capacity)
83
+ {
84
+ if (!signals)
85
+ argument_error(__FILE__, __LINE__);
86
+ if (!*signals)
87
+ argument_error(__FILE__, __LINE__);
88
+ if (capacity <= 0)
70
89
  argument_error(__FILE__, __LINE__);
71
90
 
72
- signals->self->frames->resize(capacity, signals->nchannels());
73
91
  Signals_clear(signals);
92
+ signals->self->frames->resize(capacity, signals->nchannels());
74
93
  }
75
94
 
76
95
  void
77
96
  Signals_resize (Signals* signals, uint nsamples, Float value)
78
97
  {
79
- Signals_resize(signals, nsamples);
98
+ Signals_clear(signals, nsamples);
80
99
 
81
100
  Frames* frames = Signals_get_frames(signals);
82
101
  assert(frames);
@@ -89,15 +108,6 @@ namespace Beeps
89
108
  Signals_set_nsamples(signals, nsamples);
90
109
  }
91
110
 
92
- void
93
- Signals_clear (Signals* signals)
94
- {
95
- if (!signals)
96
- argument_error(__FILE__, __LINE__);
97
-
98
- signals->self->nsamples = 0;
99
- }
100
-
101
111
  static uint
102
112
  copy_frames (Signals* to, const Signals& from, uint from_offset)
103
113
  {
@@ -191,7 +201,11 @@ namespace Beeps
191
201
  uint
192
202
  Signals_copy (Signals* to, const Signals& from, uint from_offset)
193
203
  {
194
- if (!to || !*to || !from)
204
+ if (!to)
205
+ argument_error(__FILE__, __LINE__);
206
+ if (!*to)
207
+ argument_error(__FILE__, __LINE__);
208
+ if (!from)
195
209
  argument_error(__FILE__, __LINE__);
196
210
 
197
211
  Signals_clear(to);
@@ -203,23 +217,24 @@ namespace Beeps
203
217
  }
204
218
 
205
219
  void
206
- Signals_apply (Signals* signals, const Signals& multiplier)
220
+ Signals_multiply (Signals* signals, const Signals& multiplier)
207
221
  {
208
- if (!signals || multiplier.nchannels() != 1)
222
+ if (!signals)
223
+ argument_error(__FILE__, __LINE__);
224
+ if (multiplier.nchannels() != 1)
209
225
  argument_error(__FILE__, __LINE__);
210
-
211
226
  if (signals->capacity() != multiplier.capacity())
212
227
  argument_error(__FILE__, __LINE__);
213
228
 
214
229
  Frames* sigf = Signals_get_frames(signals);
215
230
  Frames* mulf = Signals_get_frames(const_cast<Signals*>(&multiplier));
231
+ uint nframes = sigf->nframes();
232
+ uint stride = sigf->nchannels();
216
233
 
217
234
  for (uint ch = 0; ch < sigf->nchannels(); ++ch)
218
235
  {
219
- Float* sigp = &(*sigf)(0, ch);
220
- Float* mulp = &(*mulf)(0, 0);
221
- uint nframes = sigf->nframes();
222
- uint stride = sigf->nchannels();
236
+ Float* sigp = &(*sigf)(0, ch);
237
+ Float* mulp = &(*mulf)(0, 0);
223
238
  for (uint i = 0; i < nframes; ++i, sigp += stride, ++mulp)
224
239
  *sigp *= *mulp;
225
240
  }
@@ -231,13 +246,14 @@ namespace Beeps
231
246
  {
232
247
  uint nsamples = nsamples_ < 0 ? samples.nsamples() : (uint) nsamples_;
233
248
 
234
- if (
235
- !signals || !*signals ||
236
- signals->nchannels() != samples.nchannels() ||
237
- signals->capacity() < nsamples)
238
- {
249
+ if (!signals)
250
+ argument_error(__FILE__, __LINE__);
251
+ if (!*signals)
252
+ argument_error(__FILE__, __LINE__);
253
+ if (signals->nchannels() != samples.nchannels())
254
+ argument_error(__FILE__, __LINE__);
255
+ if (signals->capacity() < nsamples)
239
256
  argument_error(__FILE__, __LINE__);
240
- }
241
257
 
242
258
  Frames* f = Signals_get_frames(signals);
243
259
  assert(f);
data/src/signals.h CHANGED
@@ -31,15 +31,15 @@ namespace Beeps
31
31
  const float* const* channels,
32
32
  uint nsamples, uint nchannels, double sample_rate = 0);
33
33
 
34
- void Signals_resize (Signals* signals, uint capacity);
34
+ void Signals_clear (Signals* signals);
35
35
 
36
- void Signals_resize (Signals* signals, uint nsamples, Float value);
36
+ void Signals_clear (Signals* signals, uint capacity);
37
37
 
38
- void Signals_clear (Signals* signals);
38
+ void Signals_resize (Signals* signals, uint nsamples, Float value);
39
39
 
40
40
  uint Signals_copy (Signals* to, const Signals& from, uint from_offset);
41
41
 
42
- void Signals_apply (Signals* signals, const Signals& multiplier);
42
+ void Signals_multiply (Signals* signals, const Signals& multiplier);
43
43
 
44
44
  template <typename T>
45
45
  void Signals_write_samples (
data/src/sound.cpp CHANGED
@@ -9,6 +9,7 @@
9
9
  #include "beeps/beeps.h"
10
10
  #include "beeps/exception.h"
11
11
  #include "beeps/generator.h"
12
+ #include "beeps/debug.h"
12
13
  #include "openal.h"
13
14
  #include "processor.h"
14
15
  #include "signals.h"
@@ -29,19 +30,19 @@ namespace Beeps
29
30
  {
30
31
 
31
32
  SoundBuffer (bool create = false)
33
+ : self(new Data(create))
32
34
  {
33
- if (create) self->create();
34
35
  }
35
36
 
36
37
  SoundBuffer (const Signals& signals)
38
+ : self(new Data(true))
37
39
  {
38
- self->create();
39
40
  write(signals);
40
41
  }
41
42
 
42
43
  SoundBuffer (ALint id)
44
+ : self(new Data(id))
43
45
  {
44
- self->id = id;
45
46
  }
46
47
 
47
48
  void clear ()
@@ -59,7 +60,8 @@ namespace Beeps
59
60
  double sample_rate = signals.sample_rate();
60
61
  uint nchannels = signals.nchannels();
61
62
  uint nsamples = signals.nsamples();
62
- assert(sample_rate > 0 && nchannels > 0 && nsamples > 0);
63
+ assert(sample_rate > 0 && nchannels > 0);
64
+ if (nsamples <= 0) return 0;
63
65
 
64
66
  const Frames* frames = Signals_get_frames(&signals);
65
67
  assert(frames);
@@ -93,7 +95,7 @@ namespace Beeps
93
95
  return !operator bool();
94
96
  }
95
97
 
96
- struct Data
98
+ struct Data : public Xot::NonCopyable
97
99
  {
98
100
 
99
101
  void* context = NULL;
@@ -102,14 +104,9 @@ namespace Beeps
102
104
 
103
105
  bool owner = false;
104
106
 
105
- ~Data ()
107
+ Data (bool create)
106
108
  {
107
- clear();
108
- }
109
-
110
- void create ()
111
- {
112
- clear();
109
+ if (!create) return;
113
110
 
114
111
  ALuint id_ = 0;
115
112
  alGenBuffers(1, &id_);
@@ -120,6 +117,16 @@ namespace Beeps
120
117
  owner = true;
121
118
  }
122
119
 
120
+ Data (ALint id)
121
+ : context(OpenAL_get_context()), id(id)
122
+ {
123
+ }
124
+
125
+ ~Data ()
126
+ {
127
+ clear();
128
+ }
129
+
123
130
  void clear ()
124
131
  {
125
132
  if (owner && is_valid())
@@ -378,7 +385,7 @@ namespace Beeps
378
385
 
379
386
  Processor::Ref processor;
380
387
 
381
- std::unique_ptr<ProcessorContext> processor_context;
388
+ std::unique_ptr<StreamContext> stream_context;
382
389
 
383
390
  void clear ()
384
391
  {
@@ -403,8 +410,8 @@ namespace Beeps
403
410
  assert(processor && *processor && nchannels > 0 && sample_rate > 0);
404
411
 
405
412
  this->processor = processor;
406
- processor_context.reset(
407
- new ProcessorContext(sample_rate / 10, nchannels, sample_rate));
413
+ stream_context.reset(
414
+ new StreamContext(sample_rate / 10, nchannels, sample_rate));
408
415
 
409
416
  for (int i = 0; i < 2; ++i)
410
417
  {
@@ -418,13 +425,11 @@ namespace Beeps
418
425
 
419
426
  bool process_stream (SoundBuffer* buffer)
420
427
  {
421
- assert(buffer && processor && processor_context);
422
-
423
- Signals signals = processor_context->process_signals(processor);
424
- if (!signals) return false;
428
+ assert(buffer && processor && stream_context);
425
429
 
426
- if (processor_context->is_finished())
427
- processor_context.reset();
430
+ Signals signals = stream_context->process_next(processor);
431
+ if (stream_context->is_finished())
432
+ stream_context.reset();
428
433
 
429
434
  return buffer->write(signals) > 0;
430
435
  }
@@ -447,7 +452,7 @@ namespace Beeps
447
452
 
448
453
  bool is_streaming () const
449
454
  {
450
- return processor && processor_context && *processor_context;
455
+ return processor && stream_context;
451
456
  }
452
457
 
453
458
  };// SoundPlayer::Data
@@ -687,12 +692,8 @@ namespace Beeps
687
692
  processor && *processor &&
688
693
  seconds > 0 && nchannels > 0 && sample_rate > 0);
689
694
 
690
- ProcessorContext context(seconds * sample_rate, nchannels, sample_rate);
691
- Signals signals = context.process_signals(processor);
692
- if (!signals)
693
- beeps_error(__FILE__, __LINE__, "failed to process signals");
694
-
695
- this->signals = signals;
695
+ StreamContext context(seconds * sample_rate, nchannels, sample_rate);
696
+ this->signals = context.process_next(processor);
696
697
  }
697
698
 
698
699
  void attach_to (SoundPlayer* player) override
@@ -798,7 +799,9 @@ namespace Beeps
798
799
  {
799
800
  Processor::Ref ref = processor;
800
801
 
801
- if (!processor || !*processor)
802
+ if (!processor)
803
+ argument_error(__FILE__, __LINE__);
804
+ if (!*processor)
802
805
  argument_error(__FILE__, __LINE__);
803
806
 
804
807
  if (sample_rate <= 0) sample_rate = Beeps::sample_rate();
@@ -0,0 +1,36 @@
1
+ #include "../beeps.h"
2
+
3
+
4
+ #include <mfapi.h>
5
+ #include <xot/windows.h>
6
+ #include "exception.h"
7
+
8
+
9
+ namespace Beeps
10
+ {
11
+
12
+
13
+ void
14
+ Beeps_init ()
15
+ {
16
+ check_media_foundation_error(
17
+ CoInitializeEx(NULL, COINIT_MULTITHREADED),
18
+ __FILE__, __LINE__);
19
+
20
+ check_media_foundation_error(
21
+ MFStartup(MF_VERSION, MFSTARTUP_NOSOCKET),
22
+ __FILE__, __LINE__);
23
+ }
24
+
25
+ void
26
+ Beeps_fin ()
27
+ {
28
+ check_media_foundation_error(
29
+ MFShutdown(),
30
+ __FILE__, __LINE__);
31
+
32
+ CoUninitialize();
33
+ }
34
+
35
+
36
+ }// Beeps
@@ -0,0 +1,40 @@
1
+ #include "exception.h"
2
+
3
+
4
+ #include <xot/string.h>
5
+
6
+
7
+ namespace Beeps
8
+ {
9
+
10
+
11
+ MediaFoundationError::MediaFoundationError (const char* str)
12
+ : Super(str)
13
+ {
14
+ }
15
+
16
+
17
+ namespace ErrorFunctions
18
+ {
19
+
20
+ void
21
+ media_foundation_error (
22
+ const char* file, int line, HRESULT hresult, const char* format, ...)
23
+ {
24
+ XOT_STRINGF(format, s);
25
+ throw MediaFoundationError(
26
+ Xot::error_text(file, line, s + Xot::stringf(" (0x%p)", hresult)));
27
+ }
28
+
29
+ }// ErrorFunctions
30
+
31
+
32
+ void
33
+ check_media_foundation_error (HRESULT hresult, const char* file, int line)
34
+ {
35
+ if (FAILED(hresult))
36
+ media_foundation_error(file, line, hresult);
37
+ }
38
+
39
+
40
+ }// Beeps
@@ -0,0 +1,40 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __BEEPS_SRC_WIN32_EXCEPTION_H__
4
+ #define __BEEPS_SRC_WIN32_EXCEPTION_H__
5
+
6
+
7
+ #include <xot/windows.h>
8
+ #include "beeps/exception.h"
9
+
10
+
11
+ namespace Beeps
12
+ {
13
+
14
+
15
+ class MediaFoundationError : public BeepsError
16
+ {
17
+ typedef BeepsError Super;
18
+ public: MediaFoundationError (const char* str = NULL);
19
+ };
20
+
21
+
22
+ namespace ErrorFunctions
23
+ {
24
+
25
+ [[noreturn]]
26
+ void media_foundation_error (
27
+ const char* file, int line,
28
+ HRESULT hresult, const char* format = NULL, ...);
29
+
30
+ }// ErrorFunctions
31
+
32
+
33
+ void check_media_foundation_error (
34
+ HRESULT hresult, const char* file, int line);
35
+
36
+
37
+ }// Beeps
38
+
39
+
40
+ #endif//EOH
@@ -0,0 +1,186 @@
1
+ #include "../signals.h"
2
+
3
+
4
+ #include <mfapi.h>
5
+ #include <mfidl.h>
6
+ #include <mfreadwrite.h>
7
+ #include <xot/noncopyable.h>
8
+ #include <xot/string.h>
9
+ #include <xot/windows.h>
10
+ #include "exception.h"
11
+
12
+
13
+ namespace Beeps
14
+ {
15
+
16
+
17
+ template <typename T, void (*Delete) (T*)>
18
+ struct Ptr : public Xot::NonCopyable
19
+ {
20
+
21
+ T* ptr;
22
+
23
+ Ptr () : ptr(NULL) {}
24
+
25
+ ~Ptr () {Delete(ptr);}
26
+
27
+ T* operator -> () {return ptr;}
28
+
29
+ operator bool () const {return ptr;}
30
+
31
+ bool operator ! () const {return !operator bool();}
32
+
33
+ };// Ptr
34
+
35
+ template <typename T>
36
+ static void
37
+ release (T* object)
38
+ {
39
+ if (object) object->Release();
40
+ }
41
+
42
+ template <typename T>
43
+ static void
44
+ mem_free (T* object)
45
+ {
46
+ if (object) CoTaskMemFree(object);
47
+ }
48
+
49
+ template <typename T>
50
+ using ReleasePtr = Ptr<T, release<T>>;
51
+
52
+ template <typename T>
53
+ using MemFreePtr = Ptr<T, mem_free<T>>;
54
+
55
+
56
+ static bool is_file_exist (const char* path)
57
+ {
58
+ DWORD attribs = GetFileAttributes(path);
59
+ return
60
+ attribs != INVALID_FILE_ATTRIBUTES &&
61
+ !(attribs & FILE_ATTRIBUTE_DIRECTORY);
62
+ }
63
+
64
+ static std::wstring
65
+ to_wcs (const char* mbs)
66
+ {
67
+ size_t len = strlen(mbs);
68
+ std::wstring wcs(len, L'#');
69
+ mbstowcs(&wcs[0], mbs, len);
70
+ return wcs;
71
+ }
72
+
73
+ static void
74
+ load_bytes (WAVEFORMATEX* format, std::vector<BYTE>* bytes, const char* path)
75
+ {
76
+ std::wstring wpath = to_wcs(path);
77
+
78
+ ReleasePtr<IMFMediaType> pcm_media_type;
79
+ check_media_foundation_error(
80
+ MFCreateMediaType(&pcm_media_type.ptr),
81
+ __FILE__, __LINE__);
82
+ pcm_media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
83
+ pcm_media_type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
84
+
85
+ ReleasePtr<IMFSourceReader> source_reader;
86
+ check_media_foundation_error(
87
+ MFCreateSourceReaderFromURL(wpath.c_str(), NULL, &source_reader.ptr),
88
+ __FILE__, __LINE__);
89
+
90
+ check_media_foundation_error(
91
+ source_reader->SetCurrentMediaType(
92
+ MF_SOURCE_READER_FIRST_AUDIO_STREAM, NULL, pcm_media_type.ptr),
93
+ __FILE__, __LINE__);
94
+
95
+ ReleasePtr<IMFMediaType> media_type;
96
+ check_media_foundation_error(
97
+ source_reader->GetCurrentMediaType(
98
+ MF_SOURCE_READER_FIRST_AUDIO_STREAM, &media_type.ptr),
99
+ __FILE__, __LINE__);
100
+
101
+ MemFreePtr<WAVEFORMATEX> format_;
102
+ check_media_foundation_error(
103
+ MFCreateWaveFormatExFromMFMediaType(media_type.ptr, &format_.ptr, NULL),
104
+ __FILE__, __LINE__);
105
+
106
+ *format = *format_.ptr;
107
+ if (format->wFormatTag != WAVE_FORMAT_PCM)
108
+ beeps_error(__FILE__, __LINE__, "'%s' is not a PCM file.", path);
109
+
110
+ while (true)
111
+ {
112
+ ReleasePtr<IMFSample> sample;
113
+ DWORD flags = 0;
114
+ check_media_foundation_error(
115
+ source_reader->ReadSample(
116
+ MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, NULL, &flags, NULL, &sample.ptr),
117
+ __FILE__, __LINE__);
118
+ if (flags & MF_SOURCE_READERF_ENDOFSTREAM)
119
+ break;
120
+
121
+ ReleasePtr<IMFMediaBuffer> buffer;
122
+ check_media_foundation_error(
123
+ sample->ConvertToContiguousBuffer(&buffer.ptr),
124
+ __FILE__, __LINE__);
125
+
126
+ BYTE* data = NULL;
127
+ DWORD size = 0;
128
+ check_media_foundation_error(
129
+ buffer->Lock(&data, NULL, &size),
130
+ __FILE__, __LINE__);
131
+
132
+ bytes->resize(bytes->size() + size);
133
+ memcpy(&(*bytes)[0] + bytes->size() - size, data, size);
134
+
135
+ check_media_foundation_error(
136
+ buffer->Unlock(),
137
+ __FILE__, __LINE__);
138
+ }
139
+ }
140
+
141
+ Signals
142
+ Signals_load (const char* path)
143
+ {
144
+ if (!is_file_exist(path))
145
+ beeps_error(__FILE__, __LINE__, "'%s' not found.", path);
146
+
147
+ WAVEFORMATEX format = {0};
148
+ std::vector<BYTE> bytes;
149
+ load_bytes(&format, &bytes, path);
150
+ if (bytes.empty())
151
+ beeps_error(__FILE__, __LINE__, "failed to read bytes: '%s'", path);
152
+
153
+ uint Bps = format.wBitsPerSample / 8;
154
+ uint nchannels = format.nChannels;
155
+ uint nsamples = bytes.size() / Bps / nchannels;
156
+ Signals signals = Signals_create(nsamples, nchannels, format.nSamplesPerSec);
157
+ Frames* frames = Signals_get_frames(&signals);
158
+
159
+ for (uint channel = 0; channel < nchannels; ++channel)
160
+ {
161
+ switch (Bps)
162
+ {
163
+ case 1:
164
+ {
165
+ const uchar* p = ((uchar*) &bytes[0]) + channel;
166
+ for (uint sample = 0; sample < nsamples; ++sample, p += nchannels)
167
+ (*frames)(sample, channel) = (*p - 128) / 128.f;
168
+ break;
169
+ }
170
+
171
+ case 2:
172
+ {
173
+ const ushort* p = ((ushort*) &bytes[0]) + channel;
174
+ for (uint sample = 0; sample < nsamples; ++sample, p += nchannels)
175
+ (*frames)(sample, channel) = *p / 32768.f;
176
+ break;
177
+ }
178
+ }
179
+ }
180
+
181
+ Signals_set_nsamples(&signals, nsamples);
182
+ return signals;
183
+ }
184
+
185
+
186
+ }// Beeps