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,193 @@
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
+ require 'WSK/Model/RawReader.rb'
7
+ require 'WSK/Model/WaveReader.rb'
8
+
9
+ module WSK
10
+
11
+ module Model
12
+
13
+ class InputData
14
+
15
+ # Number of samples in the data
16
+ # Integer
17
+ attr_reader :NbrSamples
18
+
19
+ # Header of the input data
20
+ # WSK::Model::Header
21
+ attr_reader :Header
22
+
23
+ # Constructor
24
+ #
25
+ # Parameters::
26
+ # * *iFile* (_IO_): The file descriptor. Don't use it externally as long as it is used by this class.
27
+ # * *iHeader* (<em>WSK::Model::Header</em>): Corresponding file header
28
+ def initialize(iFile, iHeader)
29
+ @File, @Header = iFile, iHeader
30
+ @NbrSamples = nil
31
+ end
32
+
33
+ # Check that data seems coherent, and initialize the cursor
34
+ #
35
+ # Return::
36
+ # * _Exception_: Error, or nil in case of success
37
+ def init_cursor
38
+ rError = nil
39
+
40
+ # Size of a sample
41
+ # Integer
42
+ lSampleSize = (@Header.NbrChannels*@Header.NbrBitsPerSample)/8
43
+ # Read the size of the data
44
+ rError, lDataSize = RIFFReader.new(@File).setFilePos('data')
45
+ if (rError == nil)
46
+ # Check that the data size is coherent
47
+ if (lDataSize % lSampleSize == 0)
48
+ @NbrSamples = lDataSize / lSampleSize
49
+ @RawReader = RawReader.new(@File, @File.pos, lSampleSize, @NbrSamples)
50
+ @WaveReader = WaveReader.new(@RawReader, @Header)
51
+ log_debug "Number of samples: #{@NbrSamples}"
52
+ else
53
+ rError = RuntimeError.new("Data size (#{lDataSize} should be a multiple of #{lSampleSize} according to header.")
54
+ end
55
+ end
56
+
57
+ return rError
58
+ end
59
+
60
+ # Iterate through the samples
61
+ #
62
+ # Parameters::
63
+ # * *iIdxBeginSample* (_Integer_): Index of the first sample to begin with [optional = 0]
64
+ # * *CodeBlock*: The code called for each iteration:
65
+ # * *iInputSampleData* (<em>list<Integer></em>): The list of values (1 per channel)
66
+ def each(iIdxBeginSample = 0)
67
+ each_buffer(iIdxBeginSample) do |iBuffer, iNbrSamples|
68
+ iBuffer.size.times do |iIdxSample|
69
+ yield(iBuffer[iIdxSample*@Header.NbrChannels..(iIdxSample+1)*@Header.NbrChannels-1])
70
+ end
71
+ end
72
+ end
73
+
74
+ # Iterate through the buffers. This is far more efficient than iterating over samples.
75
+ #
76
+ # Parameters::
77
+ # * *iIdxBeginSample* (_Integer_): Index of the first sample to begin with [optional = 0]
78
+ # * *CodeBlock*: The code called for each iteration:
79
+ # * *iInputBuffer* (<em>list<Integer></em>): The list of channel values
80
+ # * *iNbrSamples* (_Integer_): The number of samples in this buffer
81
+ # * *iNbrChannels* (_Integer_): The number of channels in this buffer
82
+ def each_buffer(iIdxBeginSample = 0)
83
+ @WaveReader.each_buffer(iIdxBeginSample) do |iBuffer, iNbrSamples|
84
+ yield(iBuffer, iNbrSamples, @Header.NbrChannels)
85
+ end
86
+ end
87
+
88
+ # Get the current buffer.
89
+ # !!! This must be called only if the buffer was previously initialized (call getSampleSata to do so).
90
+ #
91
+ # Return::
92
+ # * <em>list<Integer></em>: The list of channel values
93
+ # * _Integer_: The number of samples in this buffer
94
+ # * _Integer_: The number of channels in this buffer
95
+ def get_current_buffer
96
+ rBuffer, lIdxStartSample, lIdxEndSample = @WaveReader.get_current_buffer
97
+
98
+ return rBuffer, lIdxEndSample-lIdxStartSample+1, @Header.NbrChannels
99
+ end
100
+
101
+ # Get the current raw buffer.
102
+ # !!! This must be called only if the buffer was previously initialized (call each_raw_buffer to do so).
103
+ #
104
+ # Return::
105
+ # * _String_: The raw buffer
106
+ # * _Integer_: The number of samples in this buffer
107
+ # * _Integer_: The number of channels in this buffer
108
+ def get_current_raw_buffer
109
+ rBuffer, lIdxStartSample, lIdxEndSample = @RawReader.get_current_buffer
110
+
111
+ return rBuffer, lIdxEndSample-lIdxStartSample+1, @Header.NbrChannels
112
+ end
113
+
114
+ # Iterate through the buffers in the reverse order. This is far more efficient than iterating over samples.
115
+ #
116
+ # Parameters::
117
+ # * *iIdxEndSample* (_Integer_): Index of the first sample to begin with [optional = @NbrSamples-1]
118
+ # * *CodeBlock*: The code called for each iteration:
119
+ # * *iInputBuffer* (<em>list<Integer></em>): The list of channel values
120
+ # * *iNbrSamples* (_Integer_): The number of samples in this buffer
121
+ # * *iNbrChannels* (_Integer_): The number of channels in this buffer
122
+ def each_reverse_buffer(iIdxEndSample = @NbrSamples-1)
123
+ @WaveReader.each_reverse_buffer(0, iIdxEndSample) do |iBuffer, iNbrSamples|
124
+ yield(iBuffer, iNbrSamples, @Header.NbrChannels)
125
+ end
126
+ end
127
+
128
+ # Iterate through the buffers in raw mode (strings read directly without unpacking).
129
+ # This is far more efficient than iterating over samples or unpacked buffers.
130
+ #
131
+ # Parameters::
132
+ # * *iIdxBeginSample* (_Integer_): Index of the first sample to begin with [optional = 0]
133
+ # * *iIdxLastSample* (_Integer_): Index of the last sample to end with [optional = @NbrSamples-1]
134
+ # * *iOptions* (<em>map<Symbol,Object></em>): Additional options. See CachedBufferReader for documentation. [optional = {}]
135
+ # * *CodeBlock*: The code called for each iteration:
136
+ # * *iInputRawBuffer* (_String_): The raw buffer
137
+ # * *iNbrSamples* (_Integer_): The number of samples in this buffer
138
+ # * *iNbrChannels* (_Integer_): The number of channels in this buffer
139
+ def each_raw_buffer(iIdxBeginSample = 0, iIdxLastSample = @NbrSamples-1, iOptions = {})
140
+ @RawReader.each_buffer(iIdxBeginSample, iIdxLastSample, iOptions) do |iBuffer, iNbrSamples|
141
+ yield(iBuffer, iNbrSamples, @Header.NbrChannels)
142
+ end
143
+ end
144
+
145
+ # Iterate through the buffers in the reverse order in raw mode (strings read directly without unpacking).
146
+ # This is far more efficient than iterating over samples or unpacked buffers.
147
+ #
148
+ # Parameters::
149
+ # * *iIdxBeginSample* (_Integer_): Index of the first sample to begin with [optional = 0]
150
+ # * *iIdxLastSample* (_Integer_): Index of the last sample to end with [optional = @NbrSamples-1]
151
+ # * *iOptions* (<em>map<Symbol,Object></em>): Additional options. See CachedBufferReader for documentation. [optional = {}]
152
+ # * *CodeBlock*: The code called for each iteration:
153
+ # * *iInputRawBuffer* (_String_): The raw buffer
154
+ # * *iNbrSamples* (_Integer_): The number of samples in this buffer
155
+ # * *iNbrChannels* (_Integer_): The number of channels in this buffer
156
+ def each_reverse_raw_buffer(iIdxBeginSample = 0, iIdxLastSample = @NbrSamples-1, iOptions = {})
157
+ @RawReader.each_reverse_buffer(iIdxBeginSample, iIdxLastSample, iOptions) do |iBuffer, iNbrSamples|
158
+ yield(iBuffer, iNbrSamples, @Header.NbrChannels)
159
+ end
160
+ end
161
+
162
+ # Get a sample's data
163
+ #
164
+ # Parameters::
165
+ # * *iIdxSample* (_Integer_): Index of the sample to retrieve
166
+ # * *iOptions* (<em>map<Symbol,Object></em>): Additional options [optional = {}]
167
+ # * *:reverse_buffer* (_Boolean_): Do we load the previous buffer containing this sample if needed ? [optional = false]
168
+ # Return::
169
+ # * <em>list<Integer></em>: The list of values (1 per channel), or nil in case of error
170
+ def get_sample_data(iIdxSample, iOptions = {})
171
+ rSampleData = nil
172
+
173
+ lReverseBuffer = (iOptions[:reverse_buffer] != nil) ? iOptions[:reverse_buffer] : false
174
+ if (lReverseBuffer)
175
+ @WaveReader.each_reverse_buffer(0, iIdxSample) do |iBuffer, iNbrSamples|
176
+ rSampleData = iBuffer[-@Header.NbrChannels..-1]
177
+ break
178
+ end
179
+ else
180
+ @WaveReader.each_buffer(iIdxSample) do |iBuffer, iNbrSamples|
181
+ rSampleData = iBuffer[0..@Header.NbrChannels-1]
182
+ break
183
+ end
184
+ end
185
+
186
+ return rSampleData
187
+ end
188
+
189
+ end
190
+
191
+ end
192
+
193
+ end
@@ -0,0 +1,78 @@
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
+ require 'WSK/Model/CachedBufferReader'
7
+
8
+ module WSK
9
+
10
+ module Model
11
+
12
+ # Implement a RAW file reader using cached buffer reader.
13
+ # Buffers returned are of type String.
14
+ class RawReader < CachedBufferReader
15
+
16
+ # Buffer size.
17
+ # It is expressed in bytes.
18
+ # Integer
19
+ BUFFER_SIZE = 8388608
20
+
21
+ # Constructor
22
+ #
23
+ # Parameters::
24
+ # * *iFile* (_IO_): The file descriptor. Don't use it externally as long as it is used by this class.
25
+ # * *iFirstSampleFilePos* (_Integer_): Position in the file of the first sample
26
+ # * *iSampleSize* (_Integer_): Size of a single sample to read
27
+ # * *iNbrSamples* (_Integer_): Total number of samples
28
+ def initialize(iFile, iFirstSampleFilePos, iSampleSize, iNbrSamples)
29
+ @File, @FirstSampleFilePos, @SampleSize, @NbrSamples = iFile, iFirstSampleFilePos, iSampleSize, iNbrSamples
30
+ super()
31
+ end
32
+
33
+ # Get the number of samples read per buffer
34
+ #
35
+ # Return::
36
+ # * _Integer_: Nnumber of samples in 1 buffer
37
+ def get_nbr_samples_per_buffer
38
+ return BUFFER_SIZE/@SampleSize
39
+ end
40
+
41
+ # Get the total number of samples
42
+ #
43
+ # Return::
44
+ # * _Integer_: Total number of samples
45
+ def get_nbr_samples
46
+ return @NbrSamples
47
+ end
48
+
49
+ # Read a buffer
50
+ #
51
+ # Parameters::
52
+ # * *iIdxStartSample* (_Integer_): Index of the first sample to begin with
53
+ # * *iIdxEndSample* (_Integer_): Index of the last sample to end with
54
+ # Return::
55
+ # * _Object_: The corresponding buffer
56
+ def read_buffer(iIdxStartSample, iIdxEndSample)
57
+ @File.seek(@FirstSampleFilePos + iIdxStartSample*@SampleSize)
58
+ log_debug "Raw read samples [#{iIdxStartSample} - #{iIdxEndSample}]"
59
+ return @File.read((iIdxEndSample-iIdxStartSample+1)*@SampleSize)
60
+ end
61
+
62
+ # Extract a sub-buffer for the given index range
63
+ #
64
+ # Parameters::
65
+ # * *iBuffer* (_Object_): The buffer to extract from
66
+ # * *iIdxStartSample* (_Integer_): Index of the first sample to begin with
67
+ # * *iIdxEndSample* (_Integer_): Index of the last sample to end with
68
+ # Return::
69
+ # * _Object_: The sub buffer
70
+ def extract_sub_buffer(iBuffer, iIdxStartSample, iIdxEndSample)
71
+ return iBuffer[iIdxStartSample*@SampleSize..(iIdxEndSample+1)*@SampleSize-1]
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,91 @@
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
+ require 'WSK/Model/CachedBufferReader'
7
+
8
+ module WSK
9
+
10
+ module Model
11
+
12
+ # Implement a Wave file reader using a raw buffer reader.
13
+ # Buffers returned are of type list<Integer>.
14
+ class WaveReader < CachedBufferReader
15
+
16
+ # Number of channel samples per buffer.
17
+ # Integer
18
+ NBR_CHANNEL_SAMPLES_PER_BUFFER = 2097152
19
+
20
+ # Constructor
21
+ #
22
+ # Parameters::
23
+ # * *iRawReader* (_CachedBufferReader_): The reader that provides raw data
24
+ # * *iHeader* (<em>WSK::Model::Header</em>): Corresponding file header
25
+ def initialize(iRawReader, iHeader)
26
+ @RawReader, @Header = iRawReader, iHeader
27
+ super()
28
+ end
29
+
30
+ # Get the number of samples read per buffer
31
+ #
32
+ # Return::
33
+ # * _Integer_: Nnumber of samples in 1 buffer
34
+ def get_nbr_samples_per_buffer
35
+ return NBR_CHANNEL_SAMPLES_PER_BUFFER/@Header.NbrChannels
36
+ end
37
+
38
+ # Get the total number of samples
39
+ #
40
+ # Return::
41
+ # * _Integer_: Total number of samples
42
+ def get_nbr_samples
43
+ return @RawReader.get_nbr_samples
44
+ end
45
+
46
+ # Read a buffer
47
+ #
48
+ # Parameters::
49
+ # * *iIdxStartSample* (_Integer_): Index of the first sample to begin with
50
+ # * *iIdxEndSample* (_Integer_): Index of the last sample to end with
51
+ # Return::
52
+ # * _Object_: The corresponding buffer
53
+ def read_buffer(iIdxStartSample, iIdxEndSample)
54
+ lRawBuffer = nil
55
+ lNbrSamplesToRead = iIdxEndSample - iIdxStartSample + 1
56
+ @RawReader.each_buffer(iIdxStartSample, iIdxEndSample) do |iBuffer, iNbrSamples|
57
+ if (lRawBuffer == nil)
58
+ if (lNbrSamplesToRead == iNbrSamples)
59
+ # We have the buffer directly. No copy.
60
+ lRawBuffer = iBuffer
61
+ else
62
+ # We will need to concatenate other buffers. Clone it.
63
+ lRawBuffer = iBuffer.clone
64
+ end
65
+ else
66
+ # Concatenate
67
+ lRawBuffer.concat(iBuffer)
68
+ end
69
+ end
70
+ log_debug "Decode samples [#{iIdxStartSample} - #{iIdxEndSample}]"
71
+
72
+ return @Header.getDecodedSamples(lRawBuffer, lNbrSamplesToRead)
73
+ end
74
+
75
+ # Extract a sub-buffer for the given index range
76
+ #
77
+ # Parameters::
78
+ # * *iBuffer* (_Object_): The buffer to extract from
79
+ # * *iIdxStartSample* (_Integer_): Index of the first sample to begin with
80
+ # * *iIdxEndSample* (_Integer_): Index of the last sample to end with
81
+ # Return::
82
+ # * _Object_: The sub buffer
83
+ def extract_sub_buffer(iBuffer, iIdxStartSample, iIdxEndSample)
84
+ return iBuffer[iIdxStartSample*@Header.NbrChannels..(iIdxEndSample+1)*@Header.NbrChannels-1]
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+
91
+ end
@@ -0,0 +1,146 @@
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
+ module WSK
7
+
8
+ module OutputInterfaces
9
+
10
+ class DirectStream
11
+
12
+ # Here we define the buffer size.
13
+ # The buffer will be used to store contiguous audio data in RAM.
14
+ # Each OutputData object will never use more than this size.
15
+ # It is expressed in bytes.
16
+ # Integer
17
+ BUFFER_SIZE = 2097152
18
+
19
+ # Initialize the plugin
20
+ #
21
+ # Parameters::
22
+ # * *oFile* (_IO_): The file descriptor. Don't use it externally as long as it is used by this class.
23
+ # * *iHeader* (<em>WSK::Model::Header</em>): Corresponding file header
24
+ # * *iNbrOutputDataSamples* (_Integer_): The number of output data samples
25
+ # Return::
26
+ # * _Exception_: An error, or nil in case of success
27
+ def initInterface(oFile, iHeader, iNbrOutputDataSamples)
28
+ rError = nil
29
+
30
+ @File, @Header, @NbrSamples = oFile, iHeader, iNbrOutputDataSamples
31
+ @NbrSamplesWritten = 0
32
+ # Size of a sample
33
+ # Integer
34
+ @SampleSize = (@Header.NbrChannels*@Header.NbrBitsPerSample)/8
35
+ # Compute the number of samples to store in the buffer
36
+ @NbrSamplesPerBuffer = BUFFER_SIZE/@SampleSize
37
+ # The position of the last written sample in the buffer
38
+ # Integer
39
+ @IdxCurrentBufferSample = 0
40
+ # The buffer itself, list of channels values
41
+ # list< Integer >
42
+ @Buffer = []
43
+
44
+ return rError
45
+ end
46
+
47
+ # Finalize writing
48
+ #
49
+ # Return::
50
+ # * _Integer_: The number of samples written
51
+ def finalize
52
+ if (!@Buffer.empty?)
53
+ flushBuffer
54
+ end
55
+
56
+ return @NbrSamplesWritten
57
+ end
58
+
59
+ # Add a sample data
60
+ #
61
+ # Parameters::
62
+ # * *iSampleData* (<em>list<Integer></em>): The list of channel values for this sample
63
+ def pushSample(iSampleData)
64
+ # Write data in the buffer
65
+ @Buffer += iSampleData
66
+ @IdxCurrentBufferSample += 1
67
+ if (@IdxCurrentBufferSample == @NbrSamplesPerBuffer)
68
+ # We have to flush the buffer
69
+ flushBuffer
70
+ end
71
+ end
72
+
73
+ # Add a buffer
74
+ #
75
+ # Parameters::
76
+ # * *iBuffer* (<em>list<Integer></em>): The list of channel values for this buffer
77
+ def pushBuffer(iBuffer)
78
+ # Write data in the current buffer
79
+ @Buffer += iBuffer
80
+ @IdxCurrentBufferSample += iBuffer.size/@Header.NbrChannels
81
+ if (@IdxCurrentBufferSample >= @NbrSamplesPerBuffer)
82
+ # We have to flush the buffer
83
+ flushBuffer
84
+ end
85
+ end
86
+
87
+ # Add a raw buffer
88
+ #
89
+ # Parameters::
90
+ # * *iRawBuffer* (_String_): The raw buffer
91
+ def pushRawBuffer(iRawBuffer)
92
+ # First, flush eventually remaining buffer to encode
93
+ if (!@Buffer.empty?)
94
+ flushBuffer
95
+ end
96
+ # Then write our raw buffer
97
+ @File.write(iRawBuffer)
98
+ updateProgress(iRawBuffer.size/@SampleSize)
99
+ end
100
+
101
+ # Loop on a range of samples split into buffers
102
+ #
103
+ # Parameters::
104
+ # * *iIdxBeginSample* (_Integer_): The beginning sample
105
+ # * *iIdxEndSample* (_Integer_): The ending sample
106
+ # * _CodeBlock_: The code called for each buffer:
107
+ # * *iIdxBeginBufferSample* (_Integer_): The beginning of this buffer's sample
108
+ # * *iIdxEndBufferSample* (_Integer_): The ending of this buffer's sample
109
+ def each_buffer(iIdxBeginSample, iIdxEndSample)
110
+ lIdxBeginBufferSample = iIdxBeginSample
111
+ while (lIdxBeginBufferSample <= iIdxEndSample)
112
+ lIdxEndBufferSample = lIdxBeginBufferSample + @NbrSamplesPerBuffer - 1
113
+ if (lIdxEndBufferSample > iIdxEndSample)
114
+ lIdxEndBufferSample = iIdxEndSample
115
+ end
116
+ yield(lIdxBeginBufferSample, lIdxEndBufferSample)
117
+ lIdxBeginBufferSample = lIdxEndBufferSample + 1
118
+ end
119
+ end
120
+
121
+ private
122
+
123
+ # Write the buffer to the disk
124
+ def flushBuffer
125
+ # Write it
126
+ @File.write(@Header.getEncodedString(@Buffer))
127
+ updateProgress(@Buffer.size/@Header.NbrChannels)
128
+ @IdxCurrentBufferSample = 0
129
+ @Buffer = []
130
+ end
131
+
132
+ # Add a samples' number to the progression
133
+ #
134
+ # Parameters::
135
+ # * *iNbrSamples* (_Integer_): Number of samples
136
+ def updateProgress(iNbrSamples)
137
+ @NbrSamplesWritten += iNbrSamples
138
+ $stdout.write("[#{(@NbrSamplesWritten*100)/@NbrSamples}%]\015")
139
+ $stdout.flush
140
+ end
141
+
142
+ end
143
+
144
+ end
145
+
146
+ end
@@ -0,0 +1,60 @@
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
+ module WSK
7
+
8
+ # Class reading RIFF files
9
+ class RIFFReader
10
+
11
+ # Constructor
12
+ #
13
+ # Parameters::
14
+ # * *iFile* (_IO_): File to read
15
+ def initialize(iFile)
16
+ @File = iFile
17
+ end
18
+
19
+ # Position the file on the data associated to a given RIFF name
20
+ #
21
+ # Parameters::
22
+ # * *iRIFFName* (_String_): The RIFF name
23
+ # Return::
24
+ # * _Exception_: An error, or nil in case of success
25
+ # * _Integer_: The RIFF chunk size
26
+ def setFilePos(iRIFFName)
27
+ rError = nil
28
+ rSize = nil
29
+
30
+ # Loop through the names until we find ours
31
+ @File.seek(12)
32
+ lRIFFName, rSize = @File.read(8).unpack('a4V')
33
+ lCurrentPos = 20
34
+ while (lRIFFName != nil)
35
+ if (lRIFFName == iRIFFName)
36
+ # We are positioned correctly
37
+ lRIFFName = nil
38
+ log_debug "Found RIFF chunk #{iRIFFName} of size #{rSize}"
39
+ else
40
+ log_debug "Skip RIFF chunk #{lRIFFName} of size #{rSize}"
41
+ # Go to the next chunk
42
+ @File.seek(lCurrentPos + rSize)
43
+ lData = @File.read(8)
44
+ lCurrentPos += rSize + 8
45
+ if (lData == nil)
46
+ # End of the file
47
+ rError = RuntimeError.new("End of file met: no RIFF #{iRIFFName} chunk found.")
48
+ lRIFFName = nil
49
+ else
50
+ lRIFFName, rSize = lData.unpack('a4V')
51
+ end
52
+ end
53
+ end
54
+
55
+ return rError, rSize
56
+ end
57
+
58
+ end
59
+
60
+ end