WaveSwissKnife 0.2.0.20120302

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. data/AUTHORS +4 -0
  2. data/ChangeLog +31 -0
  3. data/Credits +3 -0
  4. data/LICENSE +31 -0
  5. data/README +15 -0
  6. data/ReleaseInfo +8 -0
  7. data/bin/WSK.rb +14 -0
  8. data/ext/WSK/AnalyzeUtils/AnalyzeUtils.c +272 -0
  9. data/ext/WSK/AnalyzeUtils/extconf.rb +7 -0
  10. data/ext/WSK/ArithmUtils/ArithmUtils.c +862 -0
  11. data/ext/WSK/ArithmUtils/extconf.rb +15 -0
  12. data/ext/WSK/CommonBuild.rb +29 -0
  13. data/ext/WSK/FFTUtils/FFTUtils.c +662 -0
  14. data/ext/WSK/FFTUtils/extconf.rb +15 -0
  15. data/ext/WSK/FunctionUtils/FunctionUtils.c +182 -0
  16. data/ext/WSK/FunctionUtils/extconf.rb +15 -0
  17. data/ext/WSK/SilentUtils/SilentUtils.c +431 -0
  18. data/ext/WSK/SilentUtils/extconf.rb +7 -0
  19. data/ext/WSK/VolumeUtils/VolumeUtils.c +494 -0
  20. data/ext/WSK/VolumeUtils/extconf.rb +15 -0
  21. data/external/CommonUtils/build.rb +28 -0
  22. data/external/CommonUtils/include/CommonUtils.h +177 -0
  23. data/external/CommonUtils/src/CommonUtils.c +639 -0
  24. data/lib/WSK/Actions/Analyze.rb +176 -0
  25. data/lib/WSK/Actions/ApplyMap.desc.rb +15 -0
  26. data/lib/WSK/Actions/ApplyMap.rb +57 -0
  27. data/lib/WSK/Actions/ApplyVolumeFct.desc.rb +30 -0
  28. data/lib/WSK/Actions/ApplyVolumeFct.rb +72 -0
  29. data/lib/WSK/Actions/Compare.desc.rb +25 -0
  30. data/lib/WSK/Actions/Compare.rb +238 -0
  31. data/lib/WSK/Actions/ConstantCompare.desc.rb +20 -0
  32. data/lib/WSK/Actions/ConstantCompare.rb +61 -0
  33. data/lib/WSK/Actions/Cut.desc.rb +20 -0
  34. data/lib/WSK/Actions/Cut.rb +60 -0
  35. data/lib/WSK/Actions/CutFirstSignal.desc.rb +25 -0
  36. data/lib/WSK/Actions/CutFirstSignal.rb +72 -0
  37. data/lib/WSK/Actions/DCShifter.desc.rb +15 -0
  38. data/lib/WSK/Actions/DCShifter.rb +67 -0
  39. data/lib/WSK/Actions/DrawFct.desc.rb +20 -0
  40. data/lib/WSK/Actions/DrawFct.rb +59 -0
  41. data/lib/WSK/Actions/FFT.rb +104 -0
  42. data/lib/WSK/Actions/GenAllValues.rb +67 -0
  43. data/lib/WSK/Actions/GenConstant.desc.rb +20 -0
  44. data/lib/WSK/Actions/GenConstant.rb +56 -0
  45. data/lib/WSK/Actions/GenSawtooth.rb +57 -0
  46. data/lib/WSK/Actions/GenSine.desc.rb +20 -0
  47. data/lib/WSK/Actions/GenSine.rb +73 -0
  48. data/lib/WSK/Actions/Identity.rb +43 -0
  49. data/lib/WSK/Actions/Mix.desc.rb +15 -0
  50. data/lib/WSK/Actions/Mix.rb +149 -0
  51. data/lib/WSK/Actions/Multiply.desc.rb +15 -0
  52. data/lib/WSK/Actions/Multiply.rb +73 -0
  53. data/lib/WSK/Actions/NoiseGate.desc.rb +35 -0
  54. data/lib/WSK/Actions/NoiseGate.rb +129 -0
  55. data/lib/WSK/Actions/SilenceInserter.desc.rb +20 -0
  56. data/lib/WSK/Actions/SilenceInserter.rb +87 -0
  57. data/lib/WSK/Actions/SilenceRemover.desc.rb +30 -0
  58. data/lib/WSK/Actions/SilenceRemover.rb +74 -0
  59. data/lib/WSK/Actions/VolumeProfile.desc.rb +35 -0
  60. data/lib/WSK/Actions/VolumeProfile.rb +63 -0
  61. data/lib/WSK/Common.rb +292 -0
  62. data/lib/WSK/FFT.rb +527 -0
  63. data/lib/WSK/Functions.rb +770 -0
  64. data/lib/WSK/Launcher.rb +216 -0
  65. data/lib/WSK/Maps.rb +29 -0
  66. data/lib/WSK/Model/CachedBufferReader.rb +151 -0
  67. data/lib/WSK/Model/Header.rb +133 -0
  68. data/lib/WSK/Model/InputData.rb +193 -0
  69. data/lib/WSK/Model/RawReader.rb +78 -0
  70. data/lib/WSK/Model/WaveReader.rb +91 -0
  71. data/lib/WSK/OutputInterfaces/DirectStream.rb +146 -0
  72. data/lib/WSK/RIFFReader.rb +60 -0
  73. metadata +155 -0
@@ -0,0 +1,639 @@
1
+ /**
2
+ * Copyright (c) 2009 - 2012 Muriel Salvan (muriel@x-aeon.com)
3
+ * Licensed under the terms specified in LICENSE file. No warranty is provided.
4
+ **/
5
+
6
+ #include "CommonUtils.h"
7
+ #include "ruby.h"
8
+ #include <stdio.h>
9
+
10
+ /**
11
+ * Invoke each_raw_buffer on an input data.
12
+ * This is meant to be used with rb_iterate.
13
+ *
14
+ * Parameters::
15
+ * * *iValArgs* (<em>list<Object></em>): List of arguments:
16
+ * ** *iValInputData* (<em>WSK::Model::InputData</em>): The input data
17
+ * ** *iValIdxBeginSample* (_Integer_): Index of the first sample to search from
18
+ */
19
+ VALUE commonutils_callEachRawBuffer(
20
+ VALUE iValArgs) {
21
+ // Read arguments
22
+ VALUE iValInputData = rb_ary_entry(iValArgs, 0);
23
+ VALUE iValIdxBeginSample = rb_ary_entry(iValArgs, 1);
24
+
25
+ return rb_funcall(iValInputData, rb_intern("each_raw_buffer"), 1, iValIdxBeginSample);
26
+ }
27
+
28
+ /**
29
+ * Invoke each_reverse_raw_buffer on an input data.
30
+ * This is meant to be used with rb_iterate.
31
+ *
32
+ * Parameters::
33
+ * * *iValArgs* (<em>list<Object></em>): List of arguments:
34
+ * ** *iValInputData* (<em>WSK::Model::InputData</em>): The input data
35
+ * ** *iValIdxBeginSample* (_Integer_): Index of the first sample to search from
36
+ */
37
+ VALUE commonutils_callEachReverseRawBuffer(
38
+ VALUE iValArgs) {
39
+ // Read arguments
40
+ VALUE iValInputData = rb_ary_entry(iValArgs, 0);
41
+ VALUE iValIdxBeginSample = rb_ary_entry(iValArgs, 1);
42
+
43
+ return rb_funcall(iValInputData, rb_intern("each_reverse_raw_buffer"), 2, INT2FIX(0), iValIdxBeginSample);
44
+ }
45
+
46
+ /**
47
+ * Iterate through a raw buffer.
48
+ *
49
+ * Parameters::
50
+ * * *iPtrRawBuffer* (<em>const char*</em>): The raw buffer
51
+ * * *iNbrBitsPerSample* (<em>const int</em>): The number of bits per sample
52
+ * * *iNbrChannels* (<em>const int</em>): The number of channels
53
+ * * *iNbrSamples* (<em>const tSampleIndex</em>): The number of samples
54
+ * * *iIdxOffsetSample* (<em>const tSampleIndex</em>): The base offset of samples to be counted and given to the processing method
55
+ * * *iPtrProcessMethod* (<em>const tPtrFctProcess</em>): Pointer to the method to call for processing
56
+ * * *iPtrArgs* (<em>void*</em>): Pointer to a user specific struct that will be given to the processing function
57
+ */
58
+ void commonutils_iterateThroughRawBuffer(
59
+ const char* iPtrRawBuffer,
60
+ const int iNbrBitsPerSample,
61
+ const int iNbrChannels,
62
+ const tSampleIndex iNbrSamples,
63
+ const tSampleIndex iIdxOffsetSample,
64
+ const tPtrFctProcess iPtrProcessMethod,
65
+ void* iPtrArgs) {
66
+ // Parse the data. This is done differently depending on the data structure
67
+ // Define variables outside the loops to not allocate and initialize heap size for nothing
68
+ tSampleIndex lIdxBufferSample;
69
+ int lIdxChannel;
70
+ tSampleIndex lIdxSample = iIdxOffsetSample;
71
+ // 0: Continue iterations
72
+ // 1: Break all
73
+ // 2: Skip to the next sample
74
+ int lProcessResult;
75
+ if (iNbrBitsPerSample == 8) {
76
+ unsigned char* lPtrData = (unsigned char*)iPtrRawBuffer;
77
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
78
+ lProcessResult = 0;
79
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
80
+ if (lProcessResult == 0) {
81
+ lProcessResult = iPtrProcessMethod(((tSampleValue)(*lPtrData)) - 128, lIdxSample, lIdxChannel, iPtrArgs);
82
+ }
83
+ if (lProcessResult == 1) {
84
+ break;
85
+ }
86
+ ++lPtrData;
87
+ }
88
+ if (lProcessResult == 1) {
89
+ break;
90
+ }
91
+ ++lIdxSample;
92
+ }
93
+ } else if (iNbrBitsPerSample == 16) {
94
+ signed short int* lPtrData = (signed short int*)iPtrRawBuffer;
95
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
96
+ lProcessResult = 0;
97
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
98
+ if (lProcessResult == 0) {
99
+ lProcessResult = iPtrProcessMethod((tSampleValue)(*lPtrData), lIdxSample, lIdxChannel, iPtrArgs);
100
+ }
101
+ if (lProcessResult == 1) {
102
+ break;
103
+ }
104
+ ++lPtrData;
105
+ }
106
+ if (lProcessResult == 1) {
107
+ break;
108
+ }
109
+ ++lIdxSample;
110
+ }
111
+ } else if (iNbrBitsPerSample == 24) {
112
+ t24bits* lPtrData = (t24bits*)iPtrRawBuffer;
113
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
114
+ lProcessResult = 0;
115
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
116
+ if (lProcessResult == 0) {
117
+ lProcessResult = iPtrProcessMethod((tSampleValue)(lPtrData->value), lIdxSample, lIdxChannel, iPtrArgs);
118
+ }
119
+ if (lProcessResult == 1) {
120
+ break;
121
+ }
122
+ // Increase lPtrData this way to ensure alignment.
123
+ lPtrData = (t24bits*)(((int)lPtrData)+3);
124
+ }
125
+ if (lProcessResult == 1) {
126
+ break;
127
+ }
128
+ ++lIdxSample;
129
+ }
130
+ } else {
131
+ rb_raise(rb_eRuntimeError, "Unknown bits per samples: %d\n", iNbrBitsPerSample);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Iterate through a raw buffer, and writes another raw buffer.
137
+ *
138
+ * Parameters::
139
+ * * *iSelf* (_Object_): Object used to call log methods
140
+ * * *iPtrRawBuffer* (<em>const char*</em>): The raw buffer
141
+ * * *oPtrRawBufferOut* (<em>char*</em>): The raw buffer to write
142
+ * * *iNbrBitsPerSample* (<em>const int</em>): The number of bits per sample
143
+ * * *iNbrChannels* (<em>const int</em>): The number of channels
144
+ * * *iNbrSamples* (<em>const tSampleIndex</em>): The number of samples
145
+ * * *iIdxOffsetSample* (<em>const tSampleIndex</em>): The base offset of samples to be counted and given to the processing method
146
+ * * *iNeedCheck* (<em>const int</em>): Do we need checking output value ranges ? 0 = no, 1 = yes
147
+ * * *iPtrProcessMethod* (<em>const tPtrFctProcessOutput</em>): Pointer to the method to call for processing
148
+ * * *iPtrArgs* (<em>void*</em>): Pointer to a user specific struct that will be given to the processing function
149
+ */
150
+ void commonutils_iterateThroughRawBufferOutput(
151
+ VALUE iSelf,
152
+ const char* iPtrRawBuffer,
153
+ char* oPtrRawBufferOut,
154
+ const int iNbrBitsPerSample,
155
+ const int iNbrChannels,
156
+ const tSampleIndex iNbrSamples,
157
+ const tSampleIndex iIdxOffsetSample,
158
+ const int iNeedCheck,
159
+ const tPtrFctProcessOutput iPtrProcessMethod,
160
+ void* iPtrArgs) {
161
+ // Parse the data. This is done differently depending on the data structure
162
+ // Define variables outside the loops to not allocate and initialize heap size for nothing
163
+ tSampleIndex lIdxBufferSample;
164
+ int lIdxChannel;
165
+ tSampleIndex lIdxSample = iIdxOffsetSample;
166
+ // 0: Continue iterations
167
+ // 1: Break all
168
+ // 2: Skip to the next sample
169
+ int lProcessResult;
170
+ tSampleValue lOutputValue;
171
+ // Compute max and min values if needed only
172
+ if (iNeedCheck != 0) {
173
+ char lLogMessage[256];
174
+ ID lIDLogWarn = rb_intern("log_warn");
175
+ int lMaxValue = (1 << (iNbrBitsPerSample-1)) - 1;
176
+ int lMinValue = -(1 << (iNbrBitsPerSample-1));
177
+ if (iNbrBitsPerSample == 8) {
178
+ unsigned char* lPtrData = (unsigned char*)iPtrRawBuffer;
179
+ unsigned char* lPtrDataOut = (unsigned char*)oPtrRawBufferOut;
180
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
181
+ lProcessResult = 0;
182
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
183
+ if (lProcessResult == 0) {
184
+ lProcessResult = iPtrProcessMethod(((tSampleValue)(*lPtrData)) - 128, &lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
185
+ }
186
+ if (lProcessResult == 1) {
187
+ break;
188
+ }
189
+ // Write lOutputValue
190
+ if (lOutputValue > lMaxValue) {
191
+ sprintf(lLogMessage, "@%lld,%d - Exceeding maximal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMaxValue);
192
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
193
+ lOutputValue = lMaxValue;
194
+ } else if (lOutputValue < lMinValue) {
195
+ sprintf(lLogMessage, "@%lld,%d - Exceeding minimal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMinValue);
196
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
197
+ lOutputValue = lMinValue;
198
+ }
199
+ (*lPtrDataOut) = (unsigned char)(lOutputValue + 128);
200
+ ++lPtrDataOut;
201
+ ++lPtrData;
202
+ }
203
+ if (lProcessResult == 1) {
204
+ break;
205
+ }
206
+ ++lIdxSample;
207
+ }
208
+ } else if (iNbrBitsPerSample == 16) {
209
+ signed short int* lPtrData = (signed short int*)iPtrRawBuffer;
210
+ signed short int* lPtrDataOut = (signed short int*)oPtrRawBufferOut;
211
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
212
+ lProcessResult = 0;
213
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
214
+ if (lProcessResult == 0) {
215
+ lProcessResult = iPtrProcessMethod((tSampleValue)(*lPtrData), &lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
216
+ }
217
+ if (lProcessResult == 1) {
218
+ break;
219
+ }
220
+ // Write lOutputValue
221
+ if (lOutputValue > lMaxValue) {
222
+ sprintf(lLogMessage, "@%lld,%d - Exceeding maximal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMaxValue);
223
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
224
+ lOutputValue = lMaxValue;
225
+ } else if (lOutputValue < lMinValue) {
226
+ sprintf(lLogMessage, "@%lld,%d - Exceeding minimal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMinValue);
227
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
228
+ lOutputValue = lMinValue;
229
+ }
230
+ (*lPtrDataOut) = (signed short int)lOutputValue;
231
+ ++lPtrDataOut;
232
+ ++lPtrData;
233
+ }
234
+ if (lProcessResult == 1) {
235
+ break;
236
+ }
237
+ ++lIdxSample;
238
+ }
239
+ } else if (iNbrBitsPerSample == 24) {
240
+ t24bits* lPtrData = (t24bits*)iPtrRawBuffer;
241
+ t24bits* lPtrDataOut = (t24bits*)oPtrRawBufferOut;
242
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
243
+ lProcessResult = 0;
244
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
245
+ if (lProcessResult == 0) {
246
+ lProcessResult = iPtrProcessMethod((tSampleValue)(lPtrData->value), &lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
247
+ }
248
+ if (lProcessResult == 1) {
249
+ break;
250
+ }
251
+ // Write lOutputValue
252
+ if (lOutputValue > lMaxValue) {
253
+ sprintf(lLogMessage, "@%lld,%d - Exceeding maximal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMaxValue);
254
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
255
+ lOutputValue = lMaxValue;
256
+ } else if (lOutputValue < lMinValue) {
257
+ sprintf(lLogMessage, "@%lld,%d - Exceeding minimal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMinValue);
258
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
259
+ lOutputValue = lMinValue;
260
+ }
261
+ lPtrDataOut->value = lOutputValue;
262
+ lPtrDataOut = (t24bits*)(((int)lPtrDataOut)+3);
263
+ // Increase lPtrData this way to ensure alignment.
264
+ lPtrData = (t24bits*)(((int)lPtrData)+3);
265
+ }
266
+ if (lProcessResult == 1) {
267
+ break;
268
+ }
269
+ ++lIdxSample;
270
+ }
271
+ } else {
272
+ rb_raise(rb_eRuntimeError, "Unknown bits per samples: %d\n", iNbrBitsPerSample);
273
+ }
274
+ } else {
275
+ // No check needed here. Just write what we get.
276
+ if (iNbrBitsPerSample == 8) {
277
+ unsigned char* lPtrData = (unsigned char*)iPtrRawBuffer;
278
+ unsigned char* lPtrDataOut = (unsigned char*)oPtrRawBufferOut;
279
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
280
+ lProcessResult = 0;
281
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
282
+ if (lProcessResult == 0) {
283
+ lProcessResult = iPtrProcessMethod(((tSampleValue)(*lPtrData)) - 128, &lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
284
+ }
285
+ if (lProcessResult == 1) {
286
+ break;
287
+ }
288
+ // Write lOutputValue
289
+ (*lPtrDataOut) = (unsigned char)(lOutputValue + 128);
290
+ ++lPtrDataOut;
291
+ ++lPtrData;
292
+ }
293
+ if (lProcessResult == 1) {
294
+ break;
295
+ }
296
+ ++lIdxSample;
297
+ }
298
+ } else if (iNbrBitsPerSample == 16) {
299
+ signed short int* lPtrData = (signed short int*)iPtrRawBuffer;
300
+ signed short int* lPtrDataOut = (signed short int*)oPtrRawBufferOut;
301
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
302
+ lProcessResult = 0;
303
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
304
+ if (lProcessResult == 0) {
305
+ lProcessResult = iPtrProcessMethod((tSampleValue)(*lPtrData), &lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
306
+ }
307
+ if (lProcessResult == 1) {
308
+ break;
309
+ }
310
+ // Write lOutputValue
311
+ (*lPtrDataOut) = (signed short int)lOutputValue;
312
+ ++lPtrDataOut;
313
+ ++lPtrData;
314
+ }
315
+ if (lProcessResult == 1) {
316
+ break;
317
+ }
318
+ ++lIdxSample;
319
+ }
320
+ } else if (iNbrBitsPerSample == 24) {
321
+ t24bits* lPtrData = (t24bits*)iPtrRawBuffer;
322
+ t24bits* lPtrDataOut = (t24bits*)oPtrRawBufferOut;
323
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
324
+ lProcessResult = 0;
325
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
326
+ if (lProcessResult == 0) {
327
+ lProcessResult = iPtrProcessMethod((tSampleValue)(lPtrData->value), &lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
328
+ }
329
+ if (lProcessResult == 1) {
330
+ break;
331
+ }
332
+ // Write lOutputValue
333
+ lPtrDataOut->value = lOutputValue;
334
+ lPtrDataOut = (t24bits*)(((int)lPtrDataOut)+3);
335
+ // Increase lPtrData this way to ensure alignment.
336
+ lPtrData = (t24bits*)(((int)lPtrData)+3);
337
+ }
338
+ if (lProcessResult == 1) {
339
+ break;
340
+ }
341
+ ++lIdxSample;
342
+ }
343
+ } else {
344
+ rb_raise(rb_eRuntimeError, "Unknown bits per samples: %d\n", iNbrBitsPerSample);
345
+ }
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Iterate through an output raw buffer only, without input raw buffer.
351
+ *
352
+ * Parameters::
353
+ * * *iSelf* (_Object_): Object used to call log methods
354
+ * * *oPtrRawBufferOut* (<em>char*</em>): The raw buffer to write
355
+ * * *iNbrBitsPerSample* (<em>const int</em>): The number of bits per sample
356
+ * * *iNbrChannels* (<em>const int</em>): The number of channels
357
+ * * *iNbrSamples* (<em>const tSampleIndex</em>): The number of samples
358
+ * * *iIdxOffsetSample* (<em>const tSampleIndex</em>): The base offset of samples to be counted and given to the processing method
359
+ * * *iNeedCheck* (<em>const int</em>): Do we need checking output value ranges ? 0 = no, 1 = yes
360
+ * * *iPtrProcessMethod* (<em>const tPtrFctProcessOutputOnly</em>): Pointer to the method to call for processing
361
+ * * *iPtrArgs* (<em>void*</em>): Pointer to a user specific struct that will be given to the processing function
362
+ */
363
+ void commonutils_iterateThroughRawBufferOutputOnly(
364
+ VALUE iSelf,
365
+ char* oPtrRawBufferOut,
366
+ const int iNbrBitsPerSample,
367
+ const int iNbrChannels,
368
+ const tSampleIndex iNbrSamples,
369
+ const tSampleIndex iIdxOffsetSample,
370
+ const int iNeedCheck,
371
+ const tPtrFctProcessOutputOnly iPtrProcessMethod,
372
+ void* iPtrArgs) {
373
+ // Parse the data. This is done differently depending on the data structure
374
+ // Define variables outside the loops to not allocate and initialize heap size for nothing
375
+ tSampleIndex lIdxBufferSample;
376
+ int lIdxChannel;
377
+ tSampleIndex lIdxSample = iIdxOffsetSample;
378
+ // 0: Continue iterations
379
+ // 1: Break all
380
+ // 2: Skip to the next sample
381
+ int lProcessResult;
382
+ tSampleValue lOutputValue;
383
+ // Compute max and min values if needed only
384
+ if (iNeedCheck != 0) {
385
+ char lLogMessage[256];
386
+ ID lIDLogWarn = rb_intern("log_warn");
387
+ int lMaxValue = (1 << (iNbrBitsPerSample-1)) - 1;
388
+ int lMinValue = -(1 << (iNbrBitsPerSample-1));
389
+ if (iNbrBitsPerSample == 8) {
390
+ unsigned char* lPtrDataOut = (unsigned char*)oPtrRawBufferOut;
391
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
392
+ lProcessResult = 0;
393
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
394
+ if (lProcessResult == 0) {
395
+ lProcessResult = iPtrProcessMethod(&lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
396
+ }
397
+ if (lProcessResult == 1) {
398
+ break;
399
+ }
400
+ // Write lOutputValue
401
+ if (lOutputValue > lMaxValue) {
402
+ sprintf(lLogMessage, "@%lld,%d - Exceeding maximal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMaxValue);
403
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
404
+ lOutputValue = lMaxValue;
405
+ } else if (lOutputValue < lMinValue) {
406
+ sprintf(lLogMessage, "@%lld,%d - Exceeding minimal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMinValue);
407
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
408
+ lOutputValue = lMinValue;
409
+ }
410
+ (*lPtrDataOut) = (unsigned char)(lOutputValue + 128);
411
+ ++lPtrDataOut;
412
+ }
413
+ if (lProcessResult == 1) {
414
+ break;
415
+ }
416
+ ++lIdxSample;
417
+ }
418
+ } else if (iNbrBitsPerSample == 16) {
419
+ signed short int* lPtrDataOut = (signed short int*)oPtrRawBufferOut;
420
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
421
+ lProcessResult = 0;
422
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
423
+ if (lProcessResult == 0) {
424
+ lProcessResult = iPtrProcessMethod(&lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
425
+ }
426
+ if (lProcessResult == 1) {
427
+ break;
428
+ }
429
+ // Write lOutputValue
430
+ if (lOutputValue > lMaxValue) {
431
+ sprintf(lLogMessage, "@%lld,%d - Exceeding maximal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMaxValue);
432
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
433
+ lOutputValue = lMaxValue;
434
+ } else if (lOutputValue < lMinValue) {
435
+ sprintf(lLogMessage, "@%lld,%d - Exceeding minimal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMinValue);
436
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
437
+ lOutputValue = lMinValue;
438
+ }
439
+ (*lPtrDataOut) = (signed short int)lOutputValue;
440
+ ++lPtrDataOut;
441
+ }
442
+ if (lProcessResult == 1) {
443
+ break;
444
+ }
445
+ ++lIdxSample;
446
+ }
447
+ } else if (iNbrBitsPerSample == 24) {
448
+ t24bits* lPtrDataOut = (t24bits*)oPtrRawBufferOut;
449
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
450
+ lProcessResult = 0;
451
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
452
+ if (lProcessResult == 0) {
453
+ lProcessResult = iPtrProcessMethod(&lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
454
+ }
455
+ if (lProcessResult == 1) {
456
+ break;
457
+ }
458
+ // Write lOutputValue
459
+ if (lOutputValue > lMaxValue) {
460
+ sprintf(lLogMessage, "@%lld,%d - Exceeding maximal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMaxValue);
461
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
462
+ lOutputValue = lMaxValue;
463
+ } else if (lOutputValue < lMinValue) {
464
+ sprintf(lLogMessage, "@%lld,%d - Exceeding minimal value: %d, set to %d", lIdxSample, lIdxChannel, lOutputValue, lMinValue);
465
+ rb_funcall(iSelf, lIDLogWarn, 1, rb_str_new2(lLogMessage));
466
+ lOutputValue = lMinValue;
467
+ }
468
+ lPtrDataOut->value = lOutputValue;
469
+ // Increase lPtrDataOut this way to ensure alignment.
470
+ lPtrDataOut = (t24bits*)(((int)lPtrDataOut)+3);
471
+ }
472
+ if (lProcessResult == 1) {
473
+ break;
474
+ }
475
+ ++lIdxSample;
476
+ }
477
+ } else {
478
+ rb_raise(rb_eRuntimeError, "Unknown bits per samples: %d\n", iNbrBitsPerSample);
479
+ }
480
+ } else {
481
+ // No check needed here. Just write what we get.
482
+ if (iNbrBitsPerSample == 8) {
483
+ unsigned char* lPtrDataOut = (unsigned char*)oPtrRawBufferOut;
484
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
485
+ lProcessResult = 0;
486
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
487
+ if (lProcessResult == 0) {
488
+ lProcessResult = iPtrProcessMethod(&lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
489
+ }
490
+ if (lProcessResult == 1) {
491
+ break;
492
+ }
493
+ // Write lOutputValue
494
+ (*lPtrDataOut) = (unsigned char)(lOutputValue + 128);
495
+ ++lPtrDataOut;
496
+ }
497
+ if (lProcessResult == 1) {
498
+ break;
499
+ }
500
+ ++lIdxSample;
501
+ }
502
+ } else if (iNbrBitsPerSample == 16) {
503
+ signed short int* lPtrDataOut = (signed short int*)oPtrRawBufferOut;
504
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
505
+ lProcessResult = 0;
506
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
507
+ if (lProcessResult == 0) {
508
+ lProcessResult = iPtrProcessMethod(&lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
509
+ }
510
+ if (lProcessResult == 1) {
511
+ break;
512
+ }
513
+ // Write lOutputValue
514
+ (*lPtrDataOut) = (signed short int)lOutputValue;
515
+ ++lPtrDataOut;
516
+ }
517
+ if (lProcessResult == 1) {
518
+ break;
519
+ }
520
+ ++lIdxSample;
521
+ }
522
+ } else if (iNbrBitsPerSample == 24) {
523
+ t24bits* lPtrDataOut = (t24bits*)oPtrRawBufferOut;
524
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
525
+ lProcessResult = 0;
526
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
527
+ if (lProcessResult == 0) {
528
+ lProcessResult = iPtrProcessMethod(&lOutputValue, lIdxSample, lIdxChannel, iPtrArgs);
529
+ }
530
+ if (lProcessResult == 1) {
531
+ break;
532
+ }
533
+ // Write lOutputValue
534
+ lPtrDataOut->value = lOutputValue;
535
+ // Increase lPtrDataOut this way to ensure alignment.
536
+ lPtrDataOut = (t24bits*)(((int)lPtrDataOut)+3);
537
+ }
538
+ if (lProcessResult == 1) {
539
+ break;
540
+ }
541
+ ++lIdxSample;
542
+ }
543
+ } else {
544
+ rb_raise(rb_eRuntimeError, "Unknown bits per samples: %d\n", iNbrBitsPerSample);
545
+ }
546
+ }
547
+ }
548
+
549
+ /**
550
+ * Iterate through a raw buffer in reverse mode.
551
+ *
552
+ * Parameters::
553
+ * * *iPtrRawBuffer* (<em>const char*</em>): The raw buffer
554
+ * * *iNbrBitsPerSample* (<em>const int</em>): The number of bits per sample
555
+ * * *iNbrChannels* (<em>const int</em>): The number of channels
556
+ * * *iNbrSamples* (<em>const tSampleIndex</em>): The number of samples
557
+ * * *iIdxOffsetSample* (<em>const tSampleIndex</em>): The base offset of samples to be counted and given to the processing method
558
+ * * *iPtrProcessMethod* (<em>const tPtrFctProcess</em>): Pointer to the method to call for processing
559
+ * * *iPtrArgs* (<em>void*</em>): Pointer to a user specific struct that will be given to the processing function
560
+ */
561
+ void commonutils_iterateReverseThroughRawBuffer(
562
+ const char* iPtrRawBuffer,
563
+ const int iNbrBitsPerSample,
564
+ const int iNbrChannels,
565
+ const tSampleIndex iNbrSamples,
566
+ const tSampleIndex iIdxOffsetSample,
567
+ const tPtrFctProcess iPtrProcessMethod,
568
+ void* iPtrArgs) {
569
+ // Parse the data. This is done differently depending on the data structure
570
+ // Define variables outside the loops to not allocate and initialize heap size for nothing
571
+ tSampleIndex lIdxBufferSample;
572
+ int lIdxChannel;
573
+ tSampleIndex lIdxSample = iIdxOffsetSample;
574
+ // 0: Continue iterations
575
+ // 1: Break all
576
+ // 2: Skip to the next sample
577
+ int lProcessResult;
578
+ if (iNbrBitsPerSample == 8) {
579
+ unsigned char* lPtrData = (unsigned char*)iPtrRawBuffer;
580
+ lPtrData += iNbrSamples*iNbrChannels - 1;
581
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
582
+ lProcessResult = 0;
583
+ for (lIdxChannel = iNbrChannels-1; lIdxChannel >= 0; --lIdxChannel) {
584
+ if (lProcessResult == 0) {
585
+ lProcessResult = iPtrProcessMethod(((tSampleValue)(*lPtrData)) - 128, lIdxSample, lIdxChannel, iPtrArgs);
586
+ }
587
+ if (lProcessResult == 1) {
588
+ break;
589
+ }
590
+ --lPtrData;
591
+ }
592
+ if (lProcessResult == 1) {
593
+ break;
594
+ }
595
+ --lIdxSample;
596
+ }
597
+ } else if (iNbrBitsPerSample == 16) {
598
+ signed short int* lPtrData = (signed short int*)iPtrRawBuffer;
599
+ lPtrData += iNbrSamples*iNbrChannels - 1;
600
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
601
+ lProcessResult = 0;
602
+ for (lIdxChannel = iNbrChannels-1; lIdxChannel >= 0; --lIdxChannel) {
603
+ if (lProcessResult == 0) {
604
+ lProcessResult = iPtrProcessMethod((tSampleValue)(*lPtrData), lIdxSample, lIdxChannel, iPtrArgs);
605
+ }
606
+ if (lProcessResult == 1) {
607
+ break;
608
+ }
609
+ --lPtrData;
610
+ }
611
+ if (lProcessResult == 1) {
612
+ break;
613
+ }
614
+ --lIdxSample;
615
+ }
616
+ } else if (iNbrBitsPerSample == 24) {
617
+ t24bits* lPtrData = (t24bits*)iPtrRawBuffer;
618
+ lPtrData = (t24bits*)(((int)lPtrData)+3*(((int)iNbrSamples)*iNbrChannels - 1));
619
+ for (lIdxBufferSample = 0; lIdxBufferSample < iNbrSamples; ++lIdxBufferSample) {
620
+ lProcessResult = 0;
621
+ for (lIdxChannel = iNbrChannels-1; lIdxChannel >= 0; --lIdxChannel) {
622
+ if (lProcessResult == 0) {
623
+ lProcessResult = iPtrProcessMethod((tSampleValue)(lPtrData->value), lIdxSample, lIdxChannel, iPtrArgs);
624
+ }
625
+ if (lProcessResult == 1) {
626
+ break;
627
+ }
628
+ // Increase lPtrData this way to ensure alignment.
629
+ lPtrData = (t24bits*)(((int)lPtrData)-3);
630
+ }
631
+ if (lProcessResult == 1) {
632
+ break;
633
+ }
634
+ --lIdxSample;
635
+ }
636
+ } else {
637
+ rb_raise(rb_eRuntimeError, "Unknown bits per samples: %d\n", iNbrBitsPerSample);
638
+ }
639
+ }