WaveSwissKnife 0.2.0.20120302

Sign up to get free protection for your applications and to get access to all the features.
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
+ }