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,193 @@
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
+ 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 initCursor
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
+ logDebug "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
+ eachBuffer(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 eachBuffer(iIdxBeginSample = 0)
83
+ @WaveReader.eachBuffer(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 getCurrentBuffer
96
+ rBuffer, lIdxStartSample, lIdxEndSample = @WaveReader.getCurrentBuffer
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 eachRawBuffer 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 getCurrentRawBuffer
109
+ rBuffer, lIdxStartSample, lIdxEndSample = @RawReader.getCurrentBuffer
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 eachReverseBuffer(iIdxEndSample = @NbrSamples-1)
123
+ @WaveReader.eachReverseBuffer(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 eachRawBuffer(iIdxBeginSample = 0, iIdxLastSample = @NbrSamples-1, iOptions = {})
140
+ @RawReader.eachBuffer(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 eachReverseRawBuffer(iIdxBeginSample = 0, iIdxLastSample = @NbrSamples-1, iOptions = {})
157
+ @RawReader.eachReverseBuffer(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
+ # ** *:ReverseBuffer* (_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 getSampleData(iIdxSample, iOptions = {})
171
+ rSampleData = nil
172
+
173
+ lReverseBuffer = (iOptions[:ReverseBuffer] != nil) ? iOptions[:ReverseBuffer] : false
174
+ if (lReverseBuffer)
175
+ @WaveReader.eachReverseBuffer(0, iIdxSample) do |iBuffer, iNbrSamples|
176
+ rSampleData = iBuffer[-@Header.NbrChannels..-1]
177
+ break
178
+ end
179
+ else
180
+ @WaveReader.eachBuffer(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-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
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 getNbrSamplesPerBuffer
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 getNbrSamples
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 readBuffer(iIdxStartSample, iIdxEndSample)
57
+ @File.seek(@FirstSampleFilePos + iIdxStartSample*@SampleSize)
58
+ logDebug "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 extractSubBuffer(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-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
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 getNbrSamplesPerBuffer
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 getNbrSamples
43
+ return @RawReader.getNbrSamples
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 readBuffer(iIdxStartSample, iIdxEndSample)
54
+ lRawBuffer = nil
55
+ lNbrSamplesToRead = iIdxEndSample - iIdxStartSample + 1
56
+ @RawReader.eachBuffer(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
+ logDebug "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 extractSubBuffer(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-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
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 eachBuffer(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-2010 Muriel Salvan (murielsalvan@users.sourceforge.net)
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
+ logDebug "Found RIFF chunk #{iRIFFName} of size #{rSize}"
39
+ else
40
+ logDebug "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