1 /**
2 * Copyright (c) 2011, The University of Southampton and the individual contributors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * * Neither the name of the University of Southampton nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package org.openimaj.audio.analysis;
31
32 import java.nio.ByteBuffer;
33 import java.nio.ShortBuffer;
34
35 import org.openimaj.audio.AudioStream;
36 import org.openimaj.audio.SampleChunk;
37 import org.openimaj.audio.processor.FixedSizeSampleAudioProcessor;
38
39 /**
40 * Calculate the effective sound pressure by calculating the RMS of samples over
41 * a temporal window. This will sum across all channels in the sample chunk.
42 *
43 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
44 */
45 public class EffectiveSoundPressure extends FixedSizeSampleAudioProcessor
46 {
47 private double rms = 0;
48
49 /**
50 * Default constructor
51 */
52 public EffectiveSoundPressure()
53 {
54 super( 1 );
55 }
56
57 /**
58 * Contstructor for ad-hoc processing. Note that the window and overlap
59 * size is given in samples (not in milliseconds as the other constructor).
60 *
61 * @param windowSizeSamples Size of the processing window in samples
62 * @param overlapSamples The overlap of the windows in samples
63 */
64 public EffectiveSoundPressure( final int windowSizeSamples, final int overlapSamples )
65 {
66 super( windowSizeSamples );
67 this.setWindowStep( overlapSamples );
68 }
69
70 /**
71 * Construct with given stream and window parameters. Note that the window
72 * parameters are given in milliseconds and converted into a number of
73 * samples by the method.
74 *
75 * @param stream The audio stream
76 * @param windowSizeMillis The window size in milliseconds
77 * @param overlapMillis The overlap between windows in milliseconds
78 */
79 public EffectiveSoundPressure( final AudioStream stream, final int windowSizeMillis,
80 final int overlapMillis )
81 {
82 super( stream, (int) (stream.getFormat().getSampleRateKHz()
83 * windowSizeMillis * stream.getFormat().getNumChannels()) );
84 this.setWindowStep( (int) (stream.getFormat().getSampleRateKHz() *
85 overlapMillis * stream.getFormat().getNumChannels()) );
86 }
87
88 /**
89 * {@inheritDoc}
90 * @see org.openimaj.audio.processor.FixedSizeSampleAudioProcessor#process(org.openimaj.audio.SampleChunk)
91 */
92 @Override
93 public SampleChunk process( final SampleChunk sample ) throws Exception
94 {
95 long accum = 0;
96 final int size;
97
98 switch (sample.getFormat().getNBits())
99 {
100 case 16:
101 {
102 final ShortBuffer b = sample.getSamplesAsByteBuffer().asShortBuffer();
103 size = b.limit();
104 for( int x = 0; x < size; x++ )
105 accum += b.get( x ) * b.get( x );
106 break;
107 }
108 case 8:
109 {
110 final ByteBuffer b = sample.getSamplesAsByteBuffer();
111 size = b.limit();
112 for( int x = 0; x < size; x++ )
113 accum += b.get( x ) * b.get( x );
114 break;
115 }
116 default:
117 throw new Exception( "Unsupported Format" );
118 }
119
120 this.rms = Math.sqrt( (double) accum / (double) size );
121
122 return sample;
123 }
124
125 /**
126 * @return The effective sound pressure
127 */
128 public double getEffectiveSoundPressure()
129 {
130 return this.rms;
131 }
132 }