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,61 @@
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 Actions
9
+
10
+ class ConstantCompare
11
+
12
+ include WSK::Common
13
+
14
+ # Get the number of samples that will be written.
15
+ # This is called before execute, as it is needed to write the output file.
16
+ # It is possible to give a majoration: it will be padded with silence.
17
+ #
18
+ # Parameters::
19
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
20
+ # Return::
21
+ # * _Integer_: The number of samples to be written
22
+ def get_nbr_samples(iInputData)
23
+ return 0
24
+ end
25
+
26
+ # Execute
27
+ #
28
+ # Parameters::
29
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
30
+ # * *oOutputData* (_Object_): The output data to fill
31
+ # Return::
32
+ # * _Exception_: An error, or nil if success
33
+ def execute(iInputData, oOutputData)
34
+ if (iInputData.NbrSamples != @NbrSamples)
35
+ log_err "Input data has #{iInputData.NbrSamples} samples. It should be #{@NbrSamples}"
36
+ end
37
+ lRawSample = iInputData.Header.getEncodedString([@Value]*iInputData.Header.NbrChannels)
38
+ lCompareBuffer = nil
39
+ lNbrSamplesProcessed = 0
40
+ iInputData.each_raw_buffer do |iRawBuffer, iNbrSamples, iNbrChannels|
41
+ if ((lCompareBuffer == nil) or
42
+ (lCompareBuffer.size != iRawBuffer.size))
43
+ # Create the comparison buffer
44
+ lCompareBuffer = lRawSample*iNbrSamples
45
+ end
46
+ if (lCompareBuffer != iRawBuffer)
47
+ log_err "Differences found between samples #{lNbrSamplesProcessed} and #{lNbrSamplesProcessed+iNbrSamples-1}"
48
+ end
49
+ lNbrSamplesProcessed += iNbrSamples
50
+ $stdout.write("#{(lNbrSamplesProcessed*100)/iInputData.NbrSamples} %\015")
51
+ $stdout.flush
52
+ end
53
+
54
+ return nil
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,20 @@
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
+ {
7
+ :OutputInterface => 'DirectStream',
8
+ :Options => {
9
+ :BeginSample => [
10
+ '--begin <BeginSample>', String,
11
+ '<BeginSample>: Index of sample to begin with [default = 0]. Can be specified in float seconds (ie. 12.3s).',
12
+ 'Specify the first sample to write'
13
+ ],
14
+ :EndSample => [
15
+ '--end <EndSample>', String,
16
+ '<EndSample>: Index of sample to end with [default = 256]. Can be specified in float seconds (ie. 12.3s).',
17
+ 'Specify the last sample to write'
18
+ ]
19
+ }
20
+ }
@@ -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
+ module Actions
9
+
10
+ class Cut
11
+
12
+ include WSK::Common
13
+
14
+ # Get the number of samples that will be written.
15
+ # This is called before execute, as it is needed to write the output file.
16
+ # It is possible to give a majoration: it will be padded with silence.
17
+ #
18
+ # Parameters::
19
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
20
+ # Return::
21
+ # * _Integer_: The number of samples to be written
22
+ def get_nbr_samples(iInputData)
23
+ @IdxBeginSample = readDuration(@BeginSample, iInputData.Header.SampleRate)
24
+ @IdxEndSample = readDuration(@EndSample, iInputData.Header.SampleRate)
25
+
26
+ return @IdxEndSample-@IdxBeginSample+1
27
+ end
28
+
29
+ # Execute
30
+ #
31
+ # Parameters::
32
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
33
+ # * *oOutputData* (_Object_): The output data to fill
34
+ # Return::
35
+ # * _Exception_: An error, or nil if success
36
+ def execute(iInputData, oOutputData)
37
+ lChannelsSampleSize = (iInputData.Header.NbrChannels*iInputData.Header.NbrBitsPerSample)/8
38
+ lIdxFirstSample = @IdxBeginSample
39
+ iInputData.each_raw_buffer(@IdxBeginSample) do |iInputRawBuffer, iNbrSamples, iNbrChannels|
40
+ # If the end sample is in this buffer, write only up to it
41
+ if (@IdxEndSample < lIdxFirstSample + iNbrSamples - 1)
42
+ oOutputData.pushRawBuffer(iInputRawBuffer[0..(@IdxEndSample-lIdxFirstSample+1)*lChannelsSampleSize-1])
43
+ else
44
+ oOutputData.pushRawBuffer(iInputRawBuffer)
45
+ end
46
+ if (@IdxEndSample < lIdxFirstSample + iNbrSamples)
47
+ # Nothing left to write
48
+ break
49
+ end
50
+ lIdxFirstSample += iNbrSamples
51
+ end
52
+
53
+ return nil
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,25 @@
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
+ {
7
+ :OutputInterface => 'DirectStream',
8
+ :Options => {
9
+ :SilenceThreshold => [
10
+ '--silencethreshold <SilenceThreshold>', String,
11
+ '<SilenceThreshold>: Threshold to use to identify silent parts [default = 0]. It is possible to specify several values, for each channel, sperated with | (ie. 34|35). It is also possible to specify a range instead of a threshold with , (ie. -128,126 or -128,126|-127,132)',
12
+ 'Specify the silence threshold'
13
+ ],
14
+ :NoiseFFTFileName => [
15
+ '--noisefft <FFTFile>', String,
16
+ '<FFTFile>: File containing the FFT profile of the reference noise. Can be set to \'none\' if no file.',
17
+ 'This is used to compare potential noise profile with the real noise profile.'
18
+ ],
19
+ :SilenceMin => [
20
+ '--silencemin <SilenceDuration>', String,
21
+ '<SilenceDuration>: Silence duration in samples or in float seconds (ie. 234 or 25.3s).',
22
+ 'Specify the minimum duration a silent part must have to be interpreted as a silence.'
23
+ ],
24
+ }
25
+ }
@@ -0,0 +1,72 @@
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 Actions
9
+
10
+ class CutFirstSignal
11
+
12
+ include WSK::Common
13
+ include WSK::FFT
14
+
15
+ # Get the number of samples that will be written.
16
+ # This is called before execute, as it is needed to write the output file.
17
+ # It is possible to give a majoration: it will be padded with silence.
18
+ #
19
+ # Parameters::
20
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
21
+ # Return::
22
+ # * _Integer_: The number of samples to be written
23
+ def get_nbr_samples(iInputData)
24
+ @IdxStartSample = 0
25
+ lSilenceThresholds = readThresholds(@SilenceThreshold, iInputData.Header.NbrChannels)
26
+ # Find the first signal
27
+ lIdxSignalSample, lIdxNextAboveThresholds = getNextNonSilentSample(iInputData, 0, lSilenceThresholds, nil, nil, false)
28
+ if (lIdxSignalSample == nil)
29
+ log_warn 'No signal found. Keeping the whole file.'
30
+ else
31
+ lNoiseFFTMaxDistance, lNoiseFFTProfile = readFFTProfile(@NoiseFFTFileName)
32
+ lSilenceDuration = readDuration(@SilenceMin, iInputData.Header.SampleRate)
33
+ lIdxSilenceSample, lSilenceLength, lIdxNextAboveThresholds = getNextSilentSample(iInputData, lIdxSignalSample, lSilenceThresholds, lSilenceDuration, lNoiseFFTProfile, lNoiseFFTMaxDistance, false)
34
+ if (lIdxSilenceSample == nil)
35
+ log_warn "No silence found after the signal beginning at #{lIdxSignalSample}. Keeping the whole file."
36
+ elsif (lSilenceLength == nil)
37
+ # Find the silence length by parsing following data
38
+ lIdxNonSilentSample, lIdxNextAboveThresholds = getNextNonSilentSample(iInputData, lIdxSilenceSample+1, lSilenceThresholds, lNoiseFFTProfile, lNoiseFFTMaxDistance, false)
39
+ if (lIdxNonSilentSample == nil)
40
+ # The file should be empty
41
+ @IdxStartSample = iInputData.NbrSamples-1
42
+ else
43
+ @IdxStartSample = lIdxNonSilentSample
44
+ end
45
+ else
46
+ @IdxStartSample = lIdxSilenceSample + lSilenceLength
47
+ end
48
+ end
49
+
50
+ return iInputData.NbrSamples-@IdxStartSample
51
+ end
52
+
53
+ # Execute
54
+ #
55
+ # Parameters::
56
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
57
+ # * *oOutputData* (_Object_): The output data to fill
58
+ # Return::
59
+ # * _Exception_: An error, or nil if success
60
+ def execute(iInputData, oOutputData)
61
+ iInputData.each_raw_buffer(@IdxStartSample) do |iInputRawBuffer, iNbrSamples, iNbrChannels|
62
+ oOutputData.pushRawBuffer(iInputRawBuffer)
63
+ end
64
+
65
+ return nil
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,15 @@
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
+ {
7
+ :OutputInterface => 'DirectStream',
8
+ :Options => {
9
+ :Offset => [
10
+ '--offset <DCOffset>', String,
11
+ '<DCOffset>: Offset to use for the shift [default = 0]. It is possible to specify several values, for each channel, sperated with | (ie. 34|35).',
12
+ 'Specify the offset'
13
+ ]
14
+ }
15
+ }
@@ -0,0 +1,67 @@
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 Actions
9
+
10
+ class DCShifter
11
+
12
+ include WSK::Maps
13
+
14
+ # Get the number of samples that will be written.
15
+ # This is called before execute, as it is needed to write the output file.
16
+ # It is possible to give a majoration: it will be padded with silence.
17
+ #
18
+ # Parameters::
19
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
20
+ # Return::
21
+ # * _Integer_: The number of samples to be written
22
+ def get_nbr_samples(iInputData)
23
+ return iInputData.NbrSamples
24
+ end
25
+
26
+ # Execute
27
+ #
28
+ # Parameters::
29
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
30
+ # * *oOutputData* (_Object_): The output data to fill
31
+ # Return::
32
+ # * _Exception_: An error, or nil if success
33
+ def execute(iInputData, oOutputData)
34
+ # The offset, per channel
35
+ # list< Integer >
36
+ lOffsets = nil
37
+ if (@Offset.split('|').size == 1)
38
+ lOffsets = [@Offset.to_i] * iInputData.Header.NbrChannels
39
+ else
40
+ lOffsets = @Offset.split('|').map { |iStrValue| iStrValue.to_i }
41
+ end
42
+
43
+ # List of functions to apply, per channel
44
+ lMaxValue = 2**(iInputData.Header.NbrBitsPerSample-1) - 1
45
+ lMinValue = -2**(iInputData.Header.NbrBitsPerSample-1)
46
+ lFunctions = []
47
+ lOffsets.each do |iOffset|
48
+ lFunctions << {
49
+ :FunctionType => WSK::Functions::FCTTYPE_PIECEWISE_LINEAR,
50
+ :MinValue => lMinValue,
51
+ :MaxValue => lMaxValue,
52
+ :Points => {
53
+ lMinValue => lMinValue + iOffset,
54
+ lMaxValue => lMaxValue + iOffset
55
+ }
56
+ }
57
+ end
58
+ apply_map_functions(iInputData, oOutputData, lFunctions)
59
+
60
+ return nil
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,20 @@
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
+ {
7
+ :OutputInterface => 'DirectStream',
8
+ :Options => {
9
+ :FctFileName => [
10
+ '--function <FunctionFileName>', String,
11
+ '<FunctionFileName>: File containing the function definition',
12
+ 'Specify the function to draw'
13
+ ],
14
+ :UnitDB => [
15
+ '--unitdb <Switch>', Integer,
16
+ '<Switch>: 0 means that units used in the function are ratios. 1 means that units used in the functions are db.',
17
+ 'Specify the unit used in the function'
18
+ ]
19
+ }
20
+ }
@@ -0,0 +1,59 @@
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 Actions
9
+
10
+ class DrawFct
11
+
12
+ include WSK::Common
13
+ include WSK::Functions
14
+
15
+ # Get the number of samples that will be written.
16
+ # This is called before execute, as it is needed to write the output file.
17
+ # It is possible to give a majoration: it will be padded with silence.
18
+ #
19
+ # Parameters::
20
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
21
+ # Return::
22
+ # * _Integer_: The number of samples to be written
23
+ def get_nbr_samples(iInputData)
24
+ @Function = WSK::Functions::Function.new
25
+ @Function.read_from_file(@FctFileName)
26
+ lMinX, lMinY, lMaxX, lMaxY = @Function.get_bounds
27
+ @NbrSamplesOut = lMaxX.to_i-lMinX.to_i+1
28
+
29
+ return @NbrSamplesOut
30
+ end
31
+
32
+ # Execute
33
+ #
34
+ # Parameters::
35
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
36
+ # * *oOutputData* (_Object_): The output data to fill
37
+ # Return::
38
+ # * _Exception_: An error, or nil if success
39
+ def execute(iInputData, oOutputData)
40
+ rError = nil
41
+
42
+ # Then draw it
43
+ lMaxY = @Function.get_bounds[3]
44
+ if (@UnitDB == 1)
45
+ lMaxY = (2**(lMaxY.to_f/6)).to_r
46
+ end
47
+ lMedianValue = ((2**(iInputData.Header.NbrBitsPerSample-1)-1)/lMaxY).to_i
48
+ log_info "Draw function with maximal ratio #{lMaxY.to_f}, using median value #{lMedianValue}"
49
+ # Take the median value as a fraction of the maximal value
50
+ @Function.draw(iInputData, oOutputData, 0, @NbrSamplesOut-1, (@UnitDB == 1), lMedianValue)
51
+
52
+ return rError
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,104 @@
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 Actions
9
+
10
+ class FFT
11
+
12
+ include WSK::Common
13
+ include WSK::FFT
14
+
15
+ # Get the number of samples that will be written.
16
+ # This is called before execute, as it is needed to write the output file.
17
+ # It is possible to give a majoration: it will be padded with silence.
18
+ #
19
+ # Parameters::
20
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
21
+ # Return::
22
+ # * _Integer_: The number of samples to be written
23
+ def get_nbr_samples(iInputData)
24
+ return 0
25
+ end
26
+
27
+ # Execute
28
+ #
29
+ # Parameters::
30
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
31
+ # * *oOutputData* (_Object_): The output data to fill
32
+ # Return::
33
+ # * _Exception_: An error, or nil if success
34
+ def execute(iInputData, oOutputData)
35
+
36
+ # 1. Create the whole FFT profile
37
+ log_info 'Creating FFT profile ...'
38
+ # Object that will create the FFT
39
+ lFFTComputing = FFTComputing.new(false, iInputData.Header)
40
+ # Parse the data
41
+ lIdxSample = 0
42
+ iInputData.each_raw_buffer do |iInputRawBuffer, iNbrSamples, iNbrChannels|
43
+ lFFTComputing.completeFFT(iInputRawBuffer, iNbrSamples)
44
+ lIdxSample += iNbrSamples
45
+ $stdout.write("#{(lIdxSample*100)/iInputData.NbrSamples} %\015")
46
+ $stdout.flush
47
+ end
48
+ # Compute the result
49
+ require 'WSK/FFTUtils/FFTUtils'
50
+ lFFTUtils = FFTUtils::FFTUtils.new
51
+ lFFTProfile = lFFTComputing.getFFTProfile
52
+ lFFTReferenceProfile = lFFTUtils.createCFFTProfile(lFFTProfile)
53
+
54
+ # 2. Compute the distance obtained by comparing this profile with a normal file pass
55
+ log_info 'Computing average distance ...'
56
+ lFFTComputing2 = FFTComputing.new(true, iInputData.Header)
57
+ lIdxSample = 0
58
+ lNbrTimes = 0
59
+ lSumDist = 0
60
+ while (lIdxSample < iInputData.NbrSamples)
61
+ # Compute the number of samples needed to have a valid FFT.
62
+ # Modify this number if it exceeds the range we have
63
+ lNbrSamplesFFTMax = iInputData.Header.SampleRate/FFTSAMPLE_FREQ
64
+ lIdxBeginFFTSample = lIdxSample
65
+ lIdxEndFFTSample = lIdxSample+lNbrSamplesFFTMax-1
66
+ if (lIdxEndFFTSample >= iInputData.NbrSamples)
67
+ lIdxEndFFTSample = iInputData.NbrSamples-1
68
+ end
69
+ lNbrSamplesFFT = lIdxEndFFTSample-lIdxBeginFFTSample+1
70
+ # Load an FFT buffer of this
71
+ lFFTBuffer = ''
72
+ iInputData.each_raw_buffer(lIdxBeginFFTSample, lIdxEndFFTSample, :nbr_samples_prefetch => iInputData.NbrSamples-lIdxBeginFFTSample) do |iInputRawBuffer, iNbrSamples, iNbrChannels|
73
+ lFFTBuffer.concat(iInputRawBuffer)
74
+ end
75
+ # Compute its FFT profile
76
+ lFFTComputing2.resetData
77
+ lFFTComputing2.completeFFT(lFFTBuffer, lNbrSamplesFFT)
78
+ lSumDist += lFFTUtils.distFFTProfiles(lFFTReferenceProfile, lFFTUtils.createCFFTProfile(lFFTComputing2.getFFTProfile), FFTDIST_MAX).abs
79
+ lNbrTimes += 1
80
+ lIdxSample = lIdxEndFFTSample+1
81
+ $stdout.write("#{(lIdxSample*100)/iInputData.NbrSamples} %\015")
82
+ $stdout.flush
83
+ end
84
+ lAverageDist = lSumDist/lNbrTimes
85
+ log_debug "Average distance with silence: #{lAverageDist}"
86
+
87
+ # Display results
88
+ (FREQINDEX_FIRST..FREQINDEX_LAST).each_with_index do |iIdx, iIdxFreq|
89
+ log_debug "[#{(440*(2**(iIdx/12.0))).round} Hz]: #{lFFTProfile[2][iIdxFreq].join(', ')}"
90
+ end
91
+
92
+ # Write the result in a file
93
+ File.open('fft.result', 'wb') do |oFile|
94
+ oFile.write(Marshal.dump([lAverageDist, lFFTProfile]))
95
+ end
96
+
97
+ return nil
98
+ end
99
+
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,67 @@
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 Actions
9
+
10
+ class GenAllValues
11
+
12
+ MAX_BUFFER_SAMPLES = 65536
13
+
14
+ # Get the number of samples that will be written.
15
+ # This is called before execute, as it is needed to write the output file.
16
+ # It is possible to give a majoration: it will be padded with silence.
17
+ #
18
+ # Parameters::
19
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
20
+ # Return::
21
+ # * _Integer_: The number of samples to be written
22
+ def get_nbr_samples(iInputData)
23
+ @MaxValue = 2**(iInputData.Header.NbrBitsPerSample-1)-1
24
+ @MinValue = -2**(iInputData.Header.NbrBitsPerSample-1)
25
+
26
+ return @MaxValue-@MinValue+1
27
+ end
28
+
29
+ # Execute
30
+ #
31
+ # Parameters::
32
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
33
+ # * *oOutputData* (_Object_): The output data to fill
34
+ # Return::
35
+ # * _Exception_: An error, or nil if success
36
+ def execute(iInputData, oOutputData)
37
+ # Create buffer
38
+ lNbrBuffers = ((@MaxValue-@MinValue+1) / MAX_BUFFER_SAMPLES)+1
39
+ lSizeofLastBuffer = ((@MaxValue-@MinValue+1) % MAX_BUFFER_SAMPLES)
40
+ lIdxValue = @MinValue
41
+ log_debug "Will output #{@MaxValue-@MinValue+1} samples in #{lNbrBuffers} buffers."
42
+ lNbrBuffers.times do |iIdxBuffer|
43
+ lBuffer = []
44
+ lSamplesInBuffer = nil
45
+ if (iIdxBuffer == lNbrBuffers-1)
46
+ # The last one
47
+ lSamplesInBuffer = lSizeofLastBuffer
48
+ else
49
+ lSamplesInBuffer = MAX_BUFFER_SAMPLES
50
+ end
51
+ lSamplesInBuffer.times do |iIdxSampleBuffer|
52
+ iInputData.Header.NbrChannels.times do |iIdxChannel|
53
+ lBuffer << lIdxValue
54
+ end
55
+ lIdxValue += 1
56
+ end
57
+ oOutputData.pushBuffer(lBuffer)
58
+ end
59
+
60
+ return nil
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,20 @@
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
+ {
7
+ :OutputInterface => 'DirectStream',
8
+ :Options => {
9
+ :Value => [
10
+ '--value <Value>', Integer,
11
+ '<Value>: Constant value to write',
12
+ 'Specify the value to write in the wave file.'
13
+ ],
14
+ :NbrSamples => [
15
+ '--nbrsamples <NbrSamples>', Integer,
16
+ '<NbrSamples>: Number of samples used to write this value',
17
+ 'Specify the number of samples during the value will be written.'
18
+ ]
19
+ }
20
+ }
@@ -0,0 +1,56 @@
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 Actions
9
+
10
+ class GenConstant
11
+
12
+ MAX_BUFFER_SAMPLES = 65536
13
+
14
+ # Get the number of samples that will be written.
15
+ # This is called before execute, as it is needed to write the output file.
16
+ # It is possible to give a majoration: it will be padded with silence.
17
+ #
18
+ # Parameters::
19
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
20
+ # Return::
21
+ # * _Integer_: The number of samples to be written
22
+ def get_nbr_samples(iInputData)
23
+ return @NbrSamples
24
+ end
25
+
26
+ # Execute
27
+ #
28
+ # Parameters::
29
+ # * *iInputData* (<em>WSK::Model::InputData</em>): The input data
30
+ # * *oOutputData* (_Object_): The output data to fill
31
+ # Return::
32
+ # * _Exception_: An error, or nil if success
33
+ def execute(iInputData, oOutputData)
34
+ lRawSample = iInputData.Header.getEncodedString([@Value]*iInputData.Header.NbrChannels)
35
+ # Write complete buffers
36
+ lNbrCompleteBuffers = @NbrSamples/MAX_BUFFER_SAMPLES
37
+ if (lNbrCompleteBuffers > 0)
38
+ lCompleteRawBuffer = lRawSample*MAX_BUFFER_SAMPLES
39
+ lNbrCompleteBuffers.times do |iIdx|
40
+ oOutputData.pushRawBuffer(lCompleteRawBuffer)
41
+ end
42
+ end
43
+ # Write last buffer
44
+ lLastBufferSize = @NbrSamples % MAX_BUFFER_SAMPLES
45
+ if (lLastBufferSize > 0)
46
+ oOutputData.pushRawBuffer(lRawSample*lLastBufferSize)
47
+ end
48
+
49
+ return nil
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+
56
+ end