WaveSwissKnife 0.0.1.20101110-x86-cygwin

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 (88) hide show
  1. data/AUTHORS +1 -0
  2. data/ChangeLog +5 -0
  3. data/Credits +3 -0
  4. data/LICENSE +31 -0
  5. data/README +18 -0
  6. data/ReleaseInfo +8 -0
  7. data/TODO +2 -0
  8. data/bin/WSK.rb +14 -0
  9. data/ext/WSK/AnalyzeUtils/AnalyzeUtils.c +272 -0
  10. data/ext/WSK/AnalyzeUtils/AnalyzeUtils.o +0 -0
  11. data/ext/WSK/AnalyzeUtils/AnalyzeUtils.so +0 -0
  12. data/ext/WSK/AnalyzeUtils/Makefile +149 -0
  13. data/ext/WSK/AnalyzeUtils/build.rb +18 -0
  14. data/ext/WSK/ArithmUtils/ArithmUtils.c +862 -0
  15. data/ext/WSK/ArithmUtils/ArithmUtils.o +0 -0
  16. data/ext/WSK/ArithmUtils/ArithmUtils.so +0 -0
  17. data/ext/WSK/ArithmUtils/Makefile +149 -0
  18. data/ext/WSK/ArithmUtils/build.rb +20 -0
  19. data/ext/WSK/FFTUtils/FFTUtils.c +662 -0
  20. data/ext/WSK/FFTUtils/FFTUtils.o +0 -0
  21. data/ext/WSK/FFTUtils/FFTUtils.so +0 -0
  22. data/ext/WSK/FFTUtils/Makefile +149 -0
  23. data/ext/WSK/FFTUtils/build.rb +20 -0
  24. data/ext/WSK/FunctionUtils/FunctionUtils.c +182 -0
  25. data/ext/WSK/FunctionUtils/FunctionUtils.o +0 -0
  26. data/ext/WSK/FunctionUtils/FunctionUtils.so +0 -0
  27. data/ext/WSK/FunctionUtils/Makefile +149 -0
  28. data/ext/WSK/FunctionUtils/build.rb +20 -0
  29. data/ext/WSK/SilentUtils/Makefile +149 -0
  30. data/ext/WSK/SilentUtils/SilentUtils.c +431 -0
  31. data/ext/WSK/SilentUtils/SilentUtils.o +0 -0
  32. data/ext/WSK/SilentUtils/SilentUtils.so +0 -0
  33. data/ext/WSK/SilentUtils/build.rb +18 -0
  34. data/ext/WSK/VolumeUtils/Makefile +149 -0
  35. data/ext/WSK/VolumeUtils/VolumeUtils.c +494 -0
  36. data/ext/WSK/VolumeUtils/VolumeUtils.o +0 -0
  37. data/ext/WSK/VolumeUtils/VolumeUtils.so +0 -0
  38. data/ext/WSK/VolumeUtils/build.rb +20 -0
  39. data/lib/WSK/Actions/Analyze.rb +176 -0
  40. data/lib/WSK/Actions/ApplyMap.desc.rb +15 -0
  41. data/lib/WSK/Actions/ApplyMap.rb +57 -0
  42. data/lib/WSK/Actions/ApplyVolumeFct.desc.rb +30 -0
  43. data/lib/WSK/Actions/ApplyVolumeFct.rb +72 -0
  44. data/lib/WSK/Actions/Compare.desc.rb +25 -0
  45. data/lib/WSK/Actions/Compare.rb +238 -0
  46. data/lib/WSK/Actions/ConstantCompare.desc.rb +20 -0
  47. data/lib/WSK/Actions/ConstantCompare.rb +61 -0
  48. data/lib/WSK/Actions/Cut.desc.rb +20 -0
  49. data/lib/WSK/Actions/Cut.rb +60 -0
  50. data/lib/WSK/Actions/CutFirstSignal.desc.rb +25 -0
  51. data/lib/WSK/Actions/CutFirstSignal.rb +72 -0
  52. data/lib/WSK/Actions/DCShifter.desc.rb +15 -0
  53. data/lib/WSK/Actions/DCShifter.rb +67 -0
  54. data/lib/WSK/Actions/DrawFct.desc.rb +20 -0
  55. data/lib/WSK/Actions/DrawFct.rb +59 -0
  56. data/lib/WSK/Actions/FFT.rb +104 -0
  57. data/lib/WSK/Actions/GenAllValues.rb +67 -0
  58. data/lib/WSK/Actions/GenConstant.desc.rb +20 -0
  59. data/lib/WSK/Actions/GenConstant.rb +56 -0
  60. data/lib/WSK/Actions/GenSawtooth.rb +57 -0
  61. data/lib/WSK/Actions/GenSine.desc.rb +20 -0
  62. data/lib/WSK/Actions/GenSine.rb +73 -0
  63. data/lib/WSK/Actions/Identity.rb +43 -0
  64. data/lib/WSK/Actions/Mix.desc.rb +15 -0
  65. data/lib/WSK/Actions/Mix.rb +149 -0
  66. data/lib/WSK/Actions/Multiply.desc.rb +15 -0
  67. data/lib/WSK/Actions/Multiply.rb +73 -0
  68. data/lib/WSK/Actions/NoiseGate.desc.rb +35 -0
  69. data/lib/WSK/Actions/NoiseGate.rb +129 -0
  70. data/lib/WSK/Actions/SilenceInserter.desc.rb +20 -0
  71. data/lib/WSK/Actions/SilenceInserter.rb +87 -0
  72. data/lib/WSK/Actions/SilenceRemover.desc.rb +30 -0
  73. data/lib/WSK/Actions/SilenceRemover.rb +74 -0
  74. data/lib/WSK/Actions/VolumeProfile.desc.rb +35 -0
  75. data/lib/WSK/Actions/VolumeProfile.rb +63 -0
  76. data/lib/WSK/Common.rb +292 -0
  77. data/lib/WSK/FFT.rb +527 -0
  78. data/lib/WSK/Functions.rb +770 -0
  79. data/lib/WSK/Launcher.rb +216 -0
  80. data/lib/WSK/Maps.rb +29 -0
  81. data/lib/WSK/Model/CachedBufferReader.rb +151 -0
  82. data/lib/WSK/Model/Header.rb +133 -0
  83. data/lib/WSK/Model/InputData.rb +193 -0
  84. data/lib/WSK/Model/RawReader.rb +78 -0
  85. data/lib/WSK/Model/WaveReader.rb +91 -0
  86. data/lib/WSK/OutputInterfaces/DirectStream.rb +146 -0
  87. data/lib/WSK/RIFFReader.rb +60 -0
  88. metadata +151 -0
@@ -0,0 +1,494 @@
1
+ /**
2
+ * Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
3
+ * Licensed under the terms specified in LICENSE file. No warranty is provided.
4
+ **/
5
+
6
+ #include "ruby.h"
7
+ #include <math.h>
8
+ #include <stdio.h>
9
+ #include <CommonUtils.h>
10
+ #include <gmp.h>
11
+
12
+ // Struct used to convey data among iterators in the applyVolumeFct method for piecewise linear functions
13
+ typedef struct {
14
+ tFunction_PiecewiseLinear* fctData;
15
+ int unitDB;
16
+ int idxPreviousPoint;
17
+ int idxNextPoint;
18
+ int idxLastPoint;
19
+ // Values used to cache segment computations
20
+ // These must be refreshed each time idxPreviousPoint or idxNextPoint is set/changed.
21
+ tSampleIndex idxPreviousPointX;
22
+ tSampleIndex distWithNextX;
23
+ long double idxPreviousPointY;
24
+ long double distWithNextY;
25
+ tSampleIndex idxNextSegmentX;
26
+ // Values used to cache sample computations
27
+ // These must be refreshed each time we change the current sample. They are the same for all the channels of the current sample.
28
+ long double currentRatio;
29
+ } tApplyVolumeFctStruct_PiecewiseLinear;
30
+
31
+ // Struct used to convey data among iterators in the drawVolumeFct method for piecewise linear functions
32
+ typedef struct {
33
+ tFunction_PiecewiseLinear* fctData;
34
+ int unitDB;
35
+ int idxPreviousPoint;
36
+ int idxNextPoint;
37
+ int idxLastPoint;
38
+ tSampleValue medianValue;
39
+ // Values used to cache segment computations
40
+ // These must be refreshed each time idxPreviousPoint or idxNextPoint is set/changed.
41
+ tSampleIndex idxPreviousPointX;
42
+ tSampleIndex distWithNextX;
43
+ long double idxPreviousPointY;
44
+ long double distWithNextY;
45
+ tSampleIndex idxNextSegmentX;
46
+ // Values used to cache sample computations
47
+ // These must be refreshed each time we change the current sample. They are the same for all the channels of the current sample.
48
+ long double currentRatio;
49
+ } tDrawVolumeFctStruct_PiecewiseLinear;
50
+
51
+ // Struct used to convey data among iterators in the MeasureLevel method
52
+ typedef struct {
53
+ mpz_t* squareSums;
54
+ tSampleValue* maxAbsValue;
55
+ mpz_t tmpInt;
56
+ } tMeasureLevelStruct;
57
+
58
+ /**
59
+ * Process a value read from an input buffer for the applyVolumeFct function in case of piecewise linear function.
60
+ *
61
+ * Parameters:
62
+ * * *iValue* (<em>const tSampleValue</em>): The value being read
63
+ * * *iIdxSample* (<em>const tSampleIndex</em>): Index of this sample
64
+ * * *iIdxChannel* (<em>const int</em>): Channel corresponding to the value being read
65
+ * * *iPtrArgs* (<em>void*</em>): additional arguments. In fact a <em>tApplyVolumeFctStruct_PiecewiseLinear*</em>.
66
+ * Return:
67
+ * * _int_: The return code:
68
+ * ** 0: Continue iteration
69
+ * ** 1: Break all iterations
70
+ * ** 2: Skip directly to the next sample (don't call us for other channels of this sample)
71
+ */
72
+ int volumeutils_processValue_applyVolumeFct_PiecewiseLinear(
73
+ const tSampleValue iValue,
74
+ tSampleValue* oPtrValue,
75
+ const tSampleIndex iIdxSample,
76
+ const int iIdxChannel,
77
+ void* iPtrArgs) {
78
+ tApplyVolumeFctStruct_PiecewiseLinear* lPtrArgs = (tApplyVolumeFctStruct_PiecewiseLinear*)iPtrArgs;
79
+
80
+ // Change caches if needed
81
+ if (iIdxChannel == 0) {
82
+ // Switch to the next segment if we arrived at the end and it is the last one
83
+ if ((iIdxSample == lPtrArgs->idxNextSegmentX) &&
84
+ (lPtrArgs->idxNextPoint != lPtrArgs->idxLastPoint)) {
85
+ /*
86
+ printf("[%lld] Changing segment (%lld reached) to [%d - %d] ([%lld - %lld])\n", iIdxSample, lPtrArgs->idxNextSegmentX, lPtrArgs->idxPreviousPoint+1, lPtrArgs->idxNextPoint+1, lPtrArgs->fctData->pointsX[lPtrArgs->idxPreviousPoint+1], lPtrArgs->fctData->pointsX[lPtrArgs->idxNextPoint+1]);
87
+ */
88
+ ++lPtrArgs->idxNextPoint;
89
+ ++lPtrArgs->idxPreviousPoint;
90
+ // Compute next cache values
91
+ lPtrArgs->idxPreviousPointX = lPtrArgs->fctData->pointsX[lPtrArgs->idxPreviousPoint];
92
+ lPtrArgs->distWithNextX = lPtrArgs->fctData->pointsX[lPtrArgs->idxNextPoint]-lPtrArgs->idxPreviousPointX;
93
+ lPtrArgs->idxPreviousPointY = lPtrArgs->fctData->pointsY[lPtrArgs->idxPreviousPoint];
94
+ lPtrArgs->distWithNextY = lPtrArgs->fctData->pointsY[lPtrArgs->idxNextPoint]-lPtrArgs->idxPreviousPointY;
95
+ lPtrArgs->idxNextSegmentX = lPtrArgs->fctData->pointsX[lPtrArgs->idxNextPoint]+1;
96
+ }
97
+ // Compute the ratio to apply
98
+ if (lPtrArgs->unitDB == 1) {
99
+ lPtrArgs->currentRatio = pow(2, (lPtrArgs->idxPreviousPointY+((iIdxSample-lPtrArgs->idxPreviousPointX)*lPtrArgs->distWithNextY)/lPtrArgs->distWithNextX)/6);
100
+ } else {
101
+ lPtrArgs->currentRatio = lPtrArgs->idxPreviousPointY+((iIdxSample-lPtrArgs->idxPreviousPointX)*lPtrArgs->distWithNextY)/lPtrArgs->distWithNextX;
102
+ }
103
+ /*
104
+ if ((iIdxSample > 26563930) && (iIdxSample < 26563940)) {
105
+ printf("[%lld] idxPreviousPoint=%d idxPreviousPointX=%lld idxPreviousPointY=%Lf idxNextPoint=%d distWithNextX=%lld distWithNextY=%Lf idxNextSegmentX=%lld currentRatio=%Lf\n", iIdxSample, lPtrArgs->idxPreviousPoint, lPtrArgs->idxPreviousPointX, lPtrArgs->idxPreviousPointY, lPtrArgs->idxNextPoint, lPtrArgs->distWithNextX, lPtrArgs->distWithNextY, lPtrArgs->idxNextSegmentX, lPtrArgs->currentRatio);
106
+ }
107
+ */
108
+ }
109
+
110
+ // Write the correct value
111
+ (*oPtrValue) = iValue*lPtrArgs->currentRatio;
112
+
113
+ return 0;
114
+ }
115
+
116
+ /**
117
+ * Apply a function on the volume of an input buffer, and outputs a result buffer.
118
+ *
119
+ * Parameters:
120
+ * * *iSelf* (_FFT_): Self
121
+ * * *iValCFunction* (_Object_): The container of the C function (created with createCFunction)
122
+ * * *iValInputBuffer* (_String_): The input buffer
123
+ * * *iValNbrBitsPerSample* (_Integer_): Number of bits per sample
124
+ * * *iValNbrChannels* (_Integer_): Number of channels
125
+ * * *iValNbrSamples* (_Integer_): Number of samples
126
+ * * *iValIdxBufferFirstSample* (_Integer_): Index of the first buffer's sample in the input data
127
+ * * *iValUnitDB* (_Boolean_): Are the units in DB scale ?
128
+ * Return:
129
+ * * _String_: Output buffer
130
+ **/
131
+ static VALUE volumeutils_applyVolumeFct(
132
+ VALUE iSelf,
133
+ VALUE iValCFunction,
134
+ VALUE iValInputBuffer,
135
+ VALUE iValNbrBitsPerSample,
136
+ VALUE iValNbrChannels,
137
+ VALUE iValNbrSamples,
138
+ VALUE iValIdxBufferFirstSample,
139
+ VALUE iValUnitDB) {
140
+ // Translate Ruby objects
141
+ int iNbrBitsPerSample = FIX2INT(iValNbrBitsPerSample);
142
+ int iNbrChannels = FIX2INT(iValNbrChannels);
143
+ tSampleIndex iNbrSamples = FIX2LONG(iValNbrSamples);
144
+ tSampleIndex iIdxBufferFirstSample = FIX2LONG(iValIdxBufferFirstSample);
145
+ int iUnitDB = (iValUnitDB == Qtrue ? 1 : 0);
146
+ // Get the C function
147
+ tFunction* lPtrFct;
148
+ Data_Get_Struct(iValCFunction, tFunction, lPtrFct);
149
+ // Get the input buffer
150
+ char* lPtrRawBuffer = RSTRING(iValInputBuffer)->ptr;
151
+ int lBufferCharSize = RSTRING(iValInputBuffer)->len;
152
+ // Allocate the output buffer
153
+ char* lPtrOutputBuffer = ALLOC_N(char, lBufferCharSize);
154
+
155
+ // Call the relevant method based on the type
156
+ switch (lPtrFct->fctType) {
157
+ case FCTTYPE_PIECEWISE_LINEAR: ;
158
+ // Create parameters to give the process
159
+ tApplyVolumeFctStruct_PiecewiseLinear lProcessParams;
160
+ lProcessParams.fctData = lPtrFct->fctData;
161
+ lProcessParams.idxLastPoint = lProcessParams.fctData->nbrPoints-1;
162
+ lProcessParams.unitDB = iUnitDB;
163
+ // Find the segment containing iIdxBufferFirstSample
164
+ lProcessParams.idxNextPoint = 0;
165
+ while (lProcessParams.fctData->pointsX[lProcessParams.idxNextPoint] <= iIdxBufferFirstSample) {
166
+ ++lProcessParams.idxNextPoint;
167
+ }
168
+ lProcessParams.idxPreviousPoint = lProcessParams.idxNextPoint - 1;
169
+ // Special case for the last segment
170
+ if (lProcessParams.idxNextPoint == lProcessParams.idxLastPoint + 1) {
171
+ --lProcessParams.idxNextPoint;
172
+ }
173
+ /*
174
+ printf("Apply on volume starts on sample %lld at segment [%d - %d] (%lld - %lld]).\n", iIdxBufferFirstSample, lProcessParams.idxPreviousPoint, lProcessParams.idxNextPoint, lProcessParams.fctData->pointsX[lProcessParams.idxPreviousPoint], lProcessParams.fctData->pointsX[lProcessParams.idxNextPoint]);
175
+ */
176
+ // Compute first cache values
177
+ lProcessParams.idxPreviousPointX = lProcessParams.fctData->pointsX[lProcessParams.idxPreviousPoint];
178
+ lProcessParams.distWithNextX = lProcessParams.fctData->pointsX[lProcessParams.idxNextPoint]-lProcessParams.idxPreviousPointX;
179
+ lProcessParams.idxPreviousPointY = lProcessParams.fctData->pointsY[lProcessParams.idxPreviousPoint];
180
+ lProcessParams.distWithNextY = lProcessParams.fctData->pointsY[lProcessParams.idxNextPoint]-lProcessParams.idxPreviousPointY;
181
+ lProcessParams.idxNextSegmentX = lProcessParams.fctData->pointsX[lProcessParams.idxNextPoint]+1;
182
+ // Iterate through the raw buffer
183
+ commonutils_iterateThroughRawBufferOutput(
184
+ iSelf,
185
+ lPtrRawBuffer,
186
+ lPtrOutputBuffer,
187
+ iNbrBitsPerSample,
188
+ iNbrChannels,
189
+ iNbrSamples,
190
+ iIdxBufferFirstSample,
191
+ 1,
192
+ &volumeutils_processValue_applyVolumeFct_PiecewiseLinear,
193
+ &lProcessParams
194
+ );
195
+ break;
196
+ default: ; // The ; is here to make gcc compile: variables declarations are forbidden after a label.
197
+ char lLogMessage[256];
198
+ sprintf(lLogMessage, "Unknown function type %d", lPtrFct->fctType);
199
+ rb_funcall(iSelf, rb_intern("logErr"), 1, rb_str_new2(lLogMessage));
200
+ break;
201
+ }
202
+
203
+ VALUE rValOutputBuffer = rb_str_new(lPtrOutputBuffer, lBufferCharSize);
204
+
205
+ free(lPtrOutputBuffer);
206
+
207
+ return rValOutputBuffer;
208
+ }
209
+
210
+ /**
211
+ * Process a value read from an input buffer for the drawVolumeFct function in case of piecewise linear function.
212
+ *
213
+ * Parameters:
214
+ * * *iIdxSample* (<em>const tSampleIndex</em>): Index of this sample
215
+ * * *iIdxChannel* (<em>const int</em>): Channel corresponding to the value being read
216
+ * * *iPtrArgs* (<em>void*</em>): additional arguments. In fact a <em>tApplyVolumeFctStruct_PiecewiseLinear*</em>.
217
+ * Return:
218
+ * * _int_: The return code:
219
+ * ** 0: Continue iteration
220
+ * ** 1: Break all iterations
221
+ * ** 2: Skip directly to the next sample (don't call us for other channels of this sample)
222
+ */
223
+ int volumeutils_processValue_drawVolumeFct_PiecewiseLinear(
224
+ tSampleValue* oPtrValue,
225
+ const tSampleIndex iIdxSample,
226
+ const int iIdxChannel,
227
+ void* iPtrArgs) {
228
+ tDrawVolumeFctStruct_PiecewiseLinear* lPtrArgs = (tDrawVolumeFctStruct_PiecewiseLinear*)iPtrArgs;
229
+
230
+ // Change caches if needed
231
+ if (iIdxChannel == 0) {
232
+ // Switch to the next segment if we arrived at the end and it is the last one
233
+ if ((iIdxSample == lPtrArgs->idxNextSegmentX) &&
234
+ (lPtrArgs->idxNextPoint != lPtrArgs->idxLastPoint)) {
235
+ /*
236
+ printf("[%lld] Changing segment (%lld reached) to [%d - %d] ([%lld - %lld])\n", iIdxSample, lPtrArgs->idxNextSegmentX, lPtrArgs->idxPreviousPoint+1, lPtrArgs->idxNextPoint+1, lPtrArgs->fctData->pointsX[lPtrArgs->idxPreviousPoint+1], lPtrArgs->fctData->pointsX[lPtrArgs->idxNextPoint+1]);
237
+ */
238
+ ++lPtrArgs->idxNextPoint;
239
+ ++lPtrArgs->idxPreviousPoint;
240
+ // Compute next cache values
241
+ lPtrArgs->idxPreviousPointX = lPtrArgs->fctData->pointsX[lPtrArgs->idxPreviousPoint];
242
+ lPtrArgs->distWithNextX = lPtrArgs->fctData->pointsX[lPtrArgs->idxNextPoint]-lPtrArgs->idxPreviousPointX;
243
+ lPtrArgs->idxPreviousPointY = lPtrArgs->fctData->pointsY[lPtrArgs->idxPreviousPoint];
244
+ lPtrArgs->distWithNextY = lPtrArgs->fctData->pointsY[lPtrArgs->idxNextPoint]-lPtrArgs->idxPreviousPointY;
245
+ lPtrArgs->idxNextSegmentX = lPtrArgs->fctData->pointsX[lPtrArgs->idxNextPoint]+1;
246
+ }
247
+ // Compute the ratio to apply
248
+ if (lPtrArgs->unitDB == 1) {
249
+ lPtrArgs->currentRatio = pow(2, (lPtrArgs->idxPreviousPointY+((iIdxSample-lPtrArgs->idxPreviousPointX)*lPtrArgs->distWithNextY)/lPtrArgs->distWithNextX)/6);
250
+ } else {
251
+ lPtrArgs->currentRatio = lPtrArgs->idxPreviousPointY+((iIdxSample-lPtrArgs->idxPreviousPointX)*lPtrArgs->distWithNextY)/lPtrArgs->distWithNextX;
252
+ }
253
+ /*
254
+ if ((iIdxSample > 15) && (iIdxSample < 25)) {
255
+ printf("[%lld] idxPreviousPoint=%d idxPreviousPointX=%lld idxPreviousPointY=%Lf idxNextPoint=%d distWithNextX=%lld distWithNextY=%Lf idxNextSegmentX=%lld idxLastPoint=%d currentRatio=%Lf\n", iIdxSample, lPtrArgs->idxPreviousPoint, lPtrArgs->idxPreviousPointX, lPtrArgs->idxPreviousPointY, lPtrArgs->idxNextPoint, lPtrArgs->distWithNextX, lPtrArgs->distWithNextY, lPtrArgs->idxNextSegmentX, lPtrArgs->idxLastPoint, lPtrArgs->currentRatio);
256
+ }
257
+ */
258
+ }
259
+
260
+ // Write the correct value
261
+ (*oPtrValue) = (lPtrArgs->medianValue)*(lPtrArgs->currentRatio);
262
+
263
+ return 0;
264
+ }
265
+
266
+ /**
267
+ * Draw a function on an output buffer.
268
+ *
269
+ * Parameters:
270
+ * * *iSelf* (_FFT_): Self
271
+ * * *iValCFunction* (_Object_): The container of the C function (created with createCFunction)
272
+ * * *iValNbrBitsPerSample* (_Integer_): Number of bits per sample
273
+ * * *iValNbrChannels* (_Integer_): Number of channels
274
+ * * *iValNbrSamples* (_Integer_): Number of samples
275
+ * * *iValIdxBufferFirstSample* (_Integer_): Index of the first buffer's sample in the input data
276
+ * * *iValUnitDB* (_Boolean_): Are the units in DB scale ?
277
+ * * *iValMedianValue* (_Integer_): Sample value to take as the reference to draw the function
278
+ * Return:
279
+ * * _String_: Output buffer
280
+ **/
281
+ static VALUE volumeutils_drawVolumeFct(
282
+ VALUE iSelf,
283
+ VALUE iValCFunction,
284
+ VALUE iValNbrBitsPerSample,
285
+ VALUE iValNbrChannels,
286
+ VALUE iValNbrSamples,
287
+ VALUE iValIdxBufferFirstSample,
288
+ VALUE iValUnitDB,
289
+ VALUE iValMedianValue) {
290
+ // Translate Ruby objects
291
+ int iNbrBitsPerSample = FIX2INT(iValNbrBitsPerSample);
292
+ int iNbrChannels = FIX2INT(iValNbrChannels);
293
+ tSampleIndex iNbrSamples = FIX2LONG(iValNbrSamples);
294
+ tSampleIndex iIdxBufferFirstSample = FIX2LONG(iValIdxBufferFirstSample);
295
+ int iUnitDB = (iValUnitDB == Qtrue ? 1 : 0);
296
+ tSampleValue iMedianValue = FIX2LONG(iValMedianValue);
297
+ // Get the C function
298
+ tFunction* lPtrFct;
299
+ Data_Get_Struct(iValCFunction, tFunction, lPtrFct);
300
+ int lBufferCharSize = (iNbrSamples*iNbrChannels*iNbrBitsPerSample)/8;
301
+ // Allocate the output buffer
302
+ char* lPtrOutputBuffer = ALLOC_N(char, lBufferCharSize);
303
+
304
+ // Call the relevant method based on the type
305
+ switch (lPtrFct->fctType) {
306
+ case FCTTYPE_PIECEWISE_LINEAR: ;
307
+ // Create parameters to give the process
308
+ tDrawVolumeFctStruct_PiecewiseLinear lProcessParams;
309
+ lProcessParams.fctData = lPtrFct->fctData;
310
+ lProcessParams.medianValue = iMedianValue;
311
+ lProcessParams.idxLastPoint = lProcessParams.fctData->nbrPoints-1;
312
+ lProcessParams.unitDB = iUnitDB;
313
+ // Find the segment containing iIdxBufferFirstSample
314
+ lProcessParams.idxNextPoint = 0;
315
+ while (lProcessParams.fctData->pointsX[lProcessParams.idxNextPoint] <= iIdxBufferFirstSample) {
316
+ ++lProcessParams.idxNextPoint;
317
+ }
318
+ // Special case for the last segment
319
+ if (lProcessParams.idxNextPoint == lProcessParams.idxLastPoint + 1) {
320
+ --lProcessParams.idxNextPoint;
321
+ }
322
+ lProcessParams.idxPreviousPoint = lProcessParams.idxNextPoint - 1;
323
+ // Compute first cache values
324
+ lProcessParams.idxPreviousPointX = lProcessParams.fctData->pointsX[lProcessParams.idxPreviousPoint];
325
+ lProcessParams.distWithNextX = lProcessParams.fctData->pointsX[lProcessParams.idxNextPoint]-lProcessParams.idxPreviousPointX;
326
+ lProcessParams.idxPreviousPointY = lProcessParams.fctData->pointsY[lProcessParams.idxPreviousPoint];
327
+ lProcessParams.distWithNextY = lProcessParams.fctData->pointsY[lProcessParams.idxNextPoint]-lProcessParams.idxPreviousPointY;
328
+ lProcessParams.idxNextSegmentX = lProcessParams.fctData->pointsX[lProcessParams.idxNextPoint]+1;
329
+ // Iterate through the raw buffer
330
+ commonutils_iterateThroughRawBufferOutputOnly(
331
+ iSelf,
332
+ lPtrOutputBuffer,
333
+ iNbrBitsPerSample,
334
+ iNbrChannels,
335
+ iNbrSamples,
336
+ iIdxBufferFirstSample,
337
+ 1,
338
+ &volumeutils_processValue_drawVolumeFct_PiecewiseLinear,
339
+ &lProcessParams
340
+ );
341
+ break;
342
+ default: ; // The ; is here to make gcc compile: variables declarations are forbidden after a label.
343
+ char lLogMessage[256];
344
+ sprintf(lLogMessage, "Unknown function type %d", lPtrFct->fctType);
345
+ rb_funcall(iSelf, rb_intern("logErr"), 1, rb_str_new2(lLogMessage));
346
+ break;
347
+ }
348
+
349
+ VALUE rValOutputBuffer = rb_str_new(lPtrOutputBuffer, lBufferCharSize);
350
+
351
+ free(lPtrOutputBuffer);
352
+
353
+ return rValOutputBuffer;
354
+ }
355
+
356
+ /**
357
+ * Process a value read from an input buffer for the MeasureLevel function.
358
+ * Use the trigo cache.
359
+ *
360
+ * Parameters:
361
+ * * *iValue* (<em>const tSampleValue</em>): The value being read
362
+ * * *iIdxSample* (<em>const tSampleIndex</em>): Index of this sample
363
+ * * *iIdxChannel* (<em>const int</em>): Channel corresponding to the value being read
364
+ * * *iPtrArgs* (<em>void*</em>): additional arguments. In fact a <em>tMeasureLevelStruct*</em>.
365
+ * Return:
366
+ * * _int_: The return code:
367
+ * ** 0: Continue iteration
368
+ * ** 1: Break all iterations
369
+ * ** 2: Skip directly to the next sample (don't call us for other channels of this sample)
370
+ */
371
+ int volumeutils_processValue_MeasureLevel(
372
+ const tSampleValue iValue,
373
+ const tSampleIndex iIdxSample,
374
+ const int iIdxChannel,
375
+ void* iPtrArgs) {
376
+ // Interpret parameters
377
+ tMeasureLevelStruct* lPtrParams = (tMeasureLevelStruct*)iPtrArgs;
378
+
379
+ // RMS computation
380
+ mpz_set_si(lPtrParams->tmpInt, iValue);
381
+ mpz_addmul(lPtrParams->squareSums[iIdxChannel], lPtrParams->tmpInt, lPtrParams->tmpInt);
382
+ // Peak computation
383
+ if (abs(iValue) > lPtrParams->maxAbsValue[iIdxChannel]) {
384
+ lPtrParams->maxAbsValue[iIdxChannel] = abs(iValue);
385
+ }
386
+
387
+
388
+ return 0;
389
+ }
390
+
391
+ /**
392
+ * Measure the Level values of a given raw buffer.
393
+ *
394
+ * Parameters:
395
+ * * *iSelf* (_FFT_): Self
396
+ * * *iValInputRawBuffer* (_String_): The input raw buffer
397
+ * * *iValNbrBitsPerSample* (_Integer_): Number of bits per sample
398
+ * * *iValNbrChannels* (_Integer_): Number of channels
399
+ * * *iValNbrSamples* (_Integer_): Number of samples
400
+ * * *iValRMSRatio* (_Float_): Ratio of RMS measure vs Peak level measure
401
+ * Return:
402
+ * * <em>list<Integer></em>: List of integer values
403
+ **/
404
+ static VALUE volumeutils_measureLevel(
405
+ VALUE iSelf,
406
+ VALUE iValInputRawBuffer,
407
+ VALUE iValNbrBitsPerSample,
408
+ VALUE iValNbrChannels,
409
+ VALUE iValNbrSamples,
410
+ VALUE iValRMSRatio) {
411
+ // Translate Ruby objects
412
+ int iNbrBitsPerSample = FIX2INT(iValNbrBitsPerSample);
413
+ int iNbrChannels = FIX2INT(iValNbrChannels);
414
+ tSampleIndex iNbrSamples = FIX2LONG(iValNbrSamples);
415
+ double iRMSRatio = NUM2DBL(iValRMSRatio);
416
+ // Get the input buffer
417
+ char* lPtrRawBuffer = RSTRING(iValInputRawBuffer)->ptr;
418
+
419
+ // Allocate the array that will store the square sums
420
+ mpz_t lSquareSums[iNbrChannels];
421
+ // The array that will store the maximal absolute values
422
+ tSampleValue lMaxAbsValues[iNbrChannels];
423
+ // Initialize everything
424
+ int lIdxChannel;
425
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
426
+ mpz_init(lSquareSums[lIdxChannel]);
427
+ lMaxAbsValues[lIdxChannel] = 0;
428
+ }
429
+
430
+ // Parse the data
431
+ tMeasureLevelStruct lParams;
432
+ lParams.squareSums = lSquareSums;
433
+ lParams.maxAbsValue = lMaxAbsValues;
434
+ mpz_init(lParams.tmpInt);
435
+ commonutils_iterateThroughRawBuffer(
436
+ lPtrRawBuffer,
437
+ iNbrBitsPerSample,
438
+ iNbrChannels,
439
+ iNbrSamples,
440
+ 0,
441
+ &volumeutils_processValue_MeasureLevel,
442
+ &lParams
443
+ );
444
+ mpz_clear(lParams.tmpInt);
445
+
446
+ // Build the resulting array
447
+ VALUE lLevelValues[iNbrChannels];
448
+ // Buffer that stores string representation of mpz_t for Ruby RBigNum
449
+ char lStrValue[128];
450
+ // Temporary variables needed
451
+ mpf_t lRMSCoeff;
452
+ mpf_t lPeakCoeff;
453
+ mpf_t lRMSRatio;
454
+ mpf_t lPeakRatio;
455
+ mpz_t lLevel;
456
+ mpf_init(lRMSCoeff);
457
+ mpf_init(lPeakCoeff);
458
+ mpf_init_set_d(lRMSRatio, iRMSRatio);
459
+ mpf_init_set_d(lPeakRatio, 1.0-iRMSRatio);
460
+ mpz_init(lLevel);
461
+ for (lIdxChannel = 0; lIdxChannel < iNbrChannels; ++lIdxChannel) {
462
+ // Finalize computing the RMS value using a float
463
+ mpf_set_z(lRMSCoeff, lSquareSums[lIdxChannel]);
464
+ mpf_div_ui(lRMSCoeff, lRMSCoeff, iNbrSamples);
465
+ mpf_sqrt(lRMSCoeff, lRMSCoeff);
466
+ // Mix RMS and Peak levels according to the ratio
467
+ mpf_mul(lRMSCoeff, lRMSCoeff, lRMSRatio);
468
+ mpf_set_ui(lPeakCoeff, lMaxAbsValues[lIdxChannel]);
469
+ mpf_mul(lPeakCoeff, lPeakCoeff, lPeakRatio);
470
+ // Use lRMSCoeff to contain the result
471
+ mpf_add(lRMSCoeff, lRMSCoeff, lPeakCoeff);
472
+ mpz_set_f(lLevel, lRMSCoeff);
473
+ lLevelValues[lIdxChannel] = rb_cstr2inum(mpz_get_str(lStrValue, 16, lLevel), 16);
474
+ mpz_clear(lSquareSums[lIdxChannel]);
475
+ }
476
+ mpz_clear(lLevel);
477
+ mpf_clear(lPeakRatio);
478
+ mpf_clear(lRMSRatio);
479
+ mpf_clear(lPeakCoeff);
480
+ mpf_clear(lRMSCoeff);
481
+
482
+ return rb_ary_new4(iNbrChannels, lLevelValues);
483
+ }
484
+
485
+ // Initialize the module
486
+ void Init_VolumeUtils() {
487
+ VALUE lWSKModule = rb_define_module("WSK");
488
+ VALUE lVolumeUtilsModule = rb_define_module_under(lWSKModule, "VolumeUtils");
489
+ VALUE lVolumeUtilsClass = rb_define_class_under(lVolumeUtilsModule, "VolumeUtils", rb_cObject);
490
+
491
+ rb_define_method(lVolumeUtilsClass, "applyVolumeFct", volumeutils_applyVolumeFct, 7);
492
+ rb_define_method(lVolumeUtilsClass, "drawVolumeFct", volumeutils_drawVolumeFct, 7);
493
+ rb_define_method(lVolumeUtilsClass, "measureLevel", volumeutils_measureLevel, 5);
494
+ }
Binary file
Binary file
@@ -0,0 +1,20 @@
1
+ #--
2
+ # Copyright (c) 2009-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
3
+ # Licensed under the terms specified in LICENSE file. No warranty is provided.
4
+ #++
5
+
6
+ lAdditionalLocalLibs = [
7
+ 'CommonUtils'
8
+ ]
9
+
10
+ require 'mkmf'
11
+ $CFLAGS += ' -Wall '
12
+ # TODO (Cygwin): Adding -L/usr/local/lib is due to some Cygwin installs that do not include it with gcc
13
+ $LDFLAGS += ' -L/usr/local/lib -lgmp '
14
+ lAdditionalLocalLibs.each do |iLibName|
15
+ lLibDir = File.expand_path("#{File.dirname(__FILE__)}/../../../external/#{iLibName}")
16
+ $CFLAGS += " -I#{lLibDir}/include "
17
+ $LDFLAGS += " -L#{lLibDir}/lib -l#{iLibName} "
18
+ end
19
+ create_makefile('VolumeUtils')
20
+ system('make')