Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
EchoFilter |
|
| 2.75;2,75 |
1 | /* | |
2 | * Copyright (c) 2002-2014, Mairie de Paris | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * | |
9 | * 1. Redistributions of source code must retain the above copyright notice | |
10 | * and the following disclaimer. | |
11 | * | |
12 | * 2. Redistributions in binary form must reproduce the above copyright notice | |
13 | * and the following disclaimer in the documentation and/or other materials | |
14 | * provided with the distribution. | |
15 | * | |
16 | * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its | |
17 | * contributors may be used to endorse or promote products derived from | |
18 | * this software without specific prior written permission. | |
19 | * | |
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE | |
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | * | |
32 | * License 1.0 | |
33 | */ | |
34 | package fr.paris.lutece.plugins.captcha.modules.jcaptcha.service.sound.filter; | |
35 | ||
36 | import fr.paris.lutece.plugins.captcha.modules.jcaptcha.service.sound.LuteceWordToSound; | |
37 | ||
38 | ||
39 | /** | |
40 | * | |
41 | */ | |
42 | public class EchoFilter extends SoundFilter | |
43 | { | |
44 | private short[] _delayBuffer; | |
45 | private int _delayBufferPos; | |
46 | private float _decay; | |
47 | ||
48 | /** | |
49 | * Creates an EchoFilter with the specified number of delay samples and the | |
50 | * specified decay rate. | |
51 | * <p> | |
52 | * The number of delay samples specifies how long before the echo is | |
53 | * initially heard. For a 1 second echo with mono, 44100Hz sound, use 44100 | |
54 | * delay samples. | |
55 | * <p> | |
56 | * The decay value is how much the echo has decayed from the source. A decay | |
57 | * value of .5 means the echo heard is half as loud as the source. | |
58 | * | |
59 | * @param echoDelay the echoDelay | |
60 | * @param decay the decay | |
61 | */ | |
62 | public EchoFilter( float echoDelay, float decay ) | |
63 | 0 | { |
64 | 0 | int numSampleDelay = ( Math.round( LuteceWordToSound.getSoundsSampleRate( ) * ( echoDelay / 1000 ) ) + |
65 | 1 ); | |
66 | 0 | _delayBuffer = new short[numSampleDelay]; |
67 | 0 | _decay = decay / 100; |
68 | 0 | } |
69 | ||
70 | /** | |
71 | * Gets the remaining size, in bytes, of samples that this filter can echo | |
72 | * after the sound is done playing. Ensures that the sound will have decayed | |
73 | * to below 1% of maximum volume (amplitude). | |
74 | * | |
75 | * @return the Remaining Size | |
76 | */ | |
77 | public int getRemainingSize( ) | |
78 | { | |
79 | 0 | float finalDecay = 0.01f; |
80 | ||
81 | // derived from Math.pow(decay,x) <= finalDecay | |
82 | 0 | int numRemainingBuffers = (int) Math.ceil( Math.log( finalDecay ) / Math.log( _decay ) ); |
83 | 0 | int bufferSize = _delayBuffer.length; |
84 | ||
85 | 0 | return bufferSize * numRemainingBuffers; |
86 | } | |
87 | ||
88 | /** | |
89 | * Clears this EchoFilter's internal delay buffer. | |
90 | */ | |
91 | public void reset( ) | |
92 | { | |
93 | 0 | for ( int i = 0; i < _delayBuffer.length; i++ ) |
94 | { | |
95 | 0 | _delayBuffer[i] = 0; |
96 | } | |
97 | ||
98 | 0 | _delayBufferPos = 0; |
99 | 0 | } |
100 | ||
101 | /** | |
102 | * Filters the sound samples to add an echo. The samples played are added to | |
103 | * the sound in the delay buffer multipied by the decay rate. The result is | |
104 | * then stored in the delay buffer, so multiple echoes are heard. | |
105 | * | |
106 | * @param samples the samples | |
107 | * @param offset the offset | |
108 | * @param length the length | |
109 | * @param sampleSizeInBits the sample size in bits | |
110 | */ | |
111 | public void filter( byte[] samples, int offset, int length, int sampleSizeInBits ) | |
112 | { | |
113 | 0 | if ( sampleSizeInBits == SAMPLE_SIZE_8_BIT ) |
114 | { | |
115 | 0 | for ( int i = offset; i < ( offset + length ); i++ ) |
116 | { | |
117 | // update the sample | |
118 | 0 | short oldSample = get8bitSample( samples, i ); |
119 | 0 | short newSample = (short) ( oldSample + ( _decay * _delayBuffer[_delayBufferPos] ) ); |
120 | 0 | set8bitSample( samples, i, newSample ); |
121 | // update the delay buffer | |
122 | 0 | _delayBuffer[_delayBufferPos] = newSample; |
123 | 0 | _delayBufferPos++; |
124 | ||
125 | 0 | if ( _delayBufferPos == _delayBuffer.length ) |
126 | { | |
127 | 0 | _delayBufferPos = 0; |
128 | } | |
129 | } | |
130 | } | |
131 | 0 | else if ( sampleSizeInBits == SAMPLE_SIZE_16_BIT ) |
132 | { | |
133 | 0 | for ( int i = offset; i < ( offset + length ); i += 2 ) |
134 | { | |
135 | // update the sample | |
136 | 0 | short oldSample = get16bitSample( samples, i ); |
137 | 0 | short newSample = (short) ( oldSample + ( _decay * _delayBuffer[_delayBufferPos] ) ); |
138 | 0 | set16bitSample( samples, i, newSample ); |
139 | // update the delay buffer | |
140 | 0 | _delayBuffer[_delayBufferPos] = newSample; |
141 | 0 | _delayBufferPos++; |
142 | ||
143 | 0 | if ( _delayBufferPos == _delayBuffer.length ) |
144 | { | |
145 | 0 | _delayBufferPos = 0; |
146 | } | |
147 | } | |
148 | } | |
149 | 0 | } |
150 | } |