Browse Source

Get Audio more generic, initial pass at AudioCaptchaBuilder, restructure

/sounds directory.
master
James Childers 13 years ago
parent
commit
030f44d2d8
  1. 2
      .gitignore
  2. 213
      Java/src/nl/captcha/audio/AudioCaptcha.java
  3. 55
      Java/src/nl/captcha/audio/AudioSampleReader.java
  4. 89
      Java/src/nl/captcha/audio/AudioSampleWriter.java
  5. 109
      Java/src/nl/captcha/audio/Mixer.java
  6. 55
      Java/src/nl/captcha/audio/producer/RandomNumberVoiceProducer.java
  7. 7
      Java/src/nl/captcha/audio/producer/VoiceProducer.java
  8. 23
      Java/src/nl/captcha/servlet/AudioCaptchaServlet.java
  9. 38
      Java/src/nl/captcha/servlet/CaptchaServletUtil.java
  10. 29
      Java/src/nl/captcha/text/producer/NumberAnswerProducer.java
  11. BIN
      sounds/0-fred.wav
  12. BIN
      sounds/0-ralph.wav
  13. BIN
      sounds/1-fred.wav
  14. BIN
      sounds/1-ralph.wav
  15. BIN
      sounds/2-fred.wav
  16. BIN
      sounds/2-ralph.wav
  17. BIN
      sounds/3-fred.wav
  18. BIN
      sounds/3-ralph.wav
  19. BIN
      sounds/4-fred.wav
  20. BIN
      sounds/4-ralph.wav
  21. BIN
      sounds/5-fred.wav
  22. BIN
      sounds/5-ralph.wav
  23. BIN
      sounds/6-fred.wav
  24. BIN
      sounds/6-ralph.wav
  25. BIN
      sounds/7-fred.wav
  26. BIN
      sounds/7-ralph.wav
  27. BIN
      sounds/8-fred.wav
  28. BIN
      sounds/8-ralph.wav
  29. BIN
      sounds/9-fred.wav
  30. BIN
      sounds/9-ralph.wav
  31. BIN
      sounds/en/numbers/0-alex.wav
  32. BIN
      sounds/en/numbers/0-bruce.wav
  33. BIN
      sounds/en/numbers/0-fred.wav
  34. BIN
      sounds/en/numbers/0-kathy.wav
  35. BIN
      sounds/en/numbers/0-ralph.wav
  36. BIN
      sounds/en/numbers/0-vicki.wav
  37. BIN
      sounds/en/numbers/0-victoria.wav
  38. BIN
      sounds/en/numbers/1-alex.wav
  39. BIN
      sounds/en/numbers/1-bruce.wav
  40. BIN
      sounds/en/numbers/1-fred.wav
  41. BIN
      sounds/en/numbers/1-kathy.wav
  42. BIN
      sounds/en/numbers/1-ralph.wav
  43. BIN
      sounds/en/numbers/1-vicki.wav
  44. BIN
      sounds/en/numbers/1-victoria.wav
  45. BIN
      sounds/en/numbers/2-alex.wav
  46. BIN
      sounds/en/numbers/2-bruce.wav
  47. BIN
      sounds/en/numbers/2-fred.wav
  48. BIN
      sounds/en/numbers/2-kathy.wav
  49. BIN
      sounds/en/numbers/2-ralph.wav
  50. BIN
      sounds/en/numbers/2-vicki.wav
  51. BIN
      sounds/en/numbers/2-victoria.wav
  52. BIN
      sounds/en/numbers/3-alex.wav
  53. BIN
      sounds/en/numbers/3-bruce.wav
  54. BIN
      sounds/en/numbers/3-fred.wav
  55. BIN
      sounds/en/numbers/3-kathy.wav
  56. BIN
      sounds/en/numbers/3-ralph.wav
  57. BIN
      sounds/en/numbers/3-vicki.wav
  58. BIN
      sounds/en/numbers/3-victoria.wav
  59. BIN
      sounds/en/numbers/4-alex.wav
  60. BIN
      sounds/en/numbers/4-bruce.wav
  61. BIN
      sounds/en/numbers/4-fred.wav
  62. BIN
      sounds/en/numbers/4-kathy.wav
  63. BIN
      sounds/en/numbers/4-ralph.wav
  64. BIN
      sounds/en/numbers/4-vicki.wav
  65. BIN
      sounds/en/numbers/4-victoria.wav
  66. BIN
      sounds/en/numbers/5-alex.wav
  67. BIN
      sounds/en/numbers/5-bruce.wav
  68. BIN
      sounds/en/numbers/5-fred.wav
  69. BIN
      sounds/en/numbers/5-kathy.wav
  70. BIN
      sounds/en/numbers/5-ralph.wav
  71. BIN
      sounds/en/numbers/5-vicki.wav
  72. BIN
      sounds/en/numbers/5-victoria.wav
  73. BIN
      sounds/en/numbers/6-alex.wav
  74. BIN
      sounds/en/numbers/6-bruce.wav
  75. BIN
      sounds/en/numbers/6-fred.wav
  76. BIN
      sounds/en/numbers/6-kathy.wav
  77. BIN
      sounds/en/numbers/6-ralph.wav
  78. BIN
      sounds/en/numbers/6-vicki.wav
  79. BIN
      sounds/en/numbers/6-victoria.wav
  80. BIN
      sounds/en/numbers/7-alex.wav
  81. BIN
      sounds/en/numbers/7-bruce.wav
  82. BIN
      sounds/en/numbers/7-fred.wav
  83. BIN
      sounds/en/numbers/7-kathy.wav
  84. BIN
      sounds/en/numbers/7-ralph.wav
  85. BIN
      sounds/en/numbers/7-vicki.wav
  86. BIN
      sounds/en/numbers/7-victoria.wav
  87. BIN
      sounds/en/numbers/8-alex.wav
  88. BIN
      sounds/en/numbers/8-bruce.wav
  89. BIN
      sounds/en/numbers/8-fred.wav
  90. BIN
      sounds/en/numbers/8-kathy.wav
  91. BIN
      sounds/en/numbers/8-ralph.wav
  92. BIN
      sounds/en/numbers/8-vicki.wav
  93. BIN
      sounds/en/numbers/8-victoria.wav
  94. BIN
      sounds/en/numbers/9-alex.wav
  95. BIN
      sounds/en/numbers/9-bruce.wav
  96. BIN
      sounds/en/numbers/9-fred.wav
  97. BIN
      sounds/en/numbers/9-kathy.wav
  98. BIN
      sounds/en/numbers/9-ralph.wav
  99. BIN
      sounds/en/numbers/9-vicki.wav
  100. BIN
      sounds/en/numbers/9-victoria.wav

2
.gitignore

@ -1,4 +1,4 @@
.DS_Store?
.DS_Store
*.class
.metadata/
.cvsignore

213
Java/src/nl/captcha/audio/AudioCaptcha.java

@ -0,0 +1,213 @@
package nl.captcha.audio;
import static nl.captcha.audio.AudioSampleReader.SC_AUDIO_FORMAT;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import nl.captcha.audio.producer.RandomNumberVoiceProducer;
import nl.captcha.audio.producer.VoiceProducer;
import nl.captcha.text.producer.NumberAnswerProducer;
import nl.captcha.text.producer.TextProducer;
public final class AudioCaptcha {
private Builder _builder;
private AudioSampleReader _asr1, _asr2;
private AudioCaptcha(Builder builder) {
_builder = builder;
}
public static class Builder {
private static final Random RAND = new SecureRandom();
private String _answer = "";
private InputStream _sound;
private List<VoiceProducer> _voiceProds = new ArrayList<VoiceProducer>();
public Builder addAnswer() {
return addAnswer(new NumberAnswerProducer());
}
public Builder addAnswer(TextProducer ansProd) {
_answer += ansProd.getText();
return this;
}
public Builder addVoice() {
return addVoice(new RandomNumberVoiceProducer());
}
public Builder addVoice(VoiceProducer voiceProd) {
_voiceProds.add(voiceProd);
return this;
}
public AudioCaptcha build() {
// 1. Convert _answer to an array
char[] ansAry = _answer.toCharArray();
// 2. Get a random element from the list of voice producers
VoiceProducer vProd = _voiceProds.get(RAND.nextInt(_voiceProds
.size()));
_sound = vProd.getVocalizationOf("1");
return new AudioCaptcha(this);
}
@Override public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("[Answer: ");
sb.append(_answer);
sb.append("]");
return sb.toString();
}
}
public boolean isCorrect(String answer) {
return answer.contains(_builder._answer);
}
public String getAnswer() {
return _builder._answer;
}
public InputStream getSound() {
return _builder._sound;
}
// Below here is stuff for reference during Builder pattern transition.
// Will eventually be removed.
public AudioCaptcha(InputStream is1, InputStream is2) throws IOException {
_asr1 = new AudioSampleReader(is1);
_asr2 = new AudioSampleReader(is2);
}
public final InputStream mix() {
double[] samples1 = _asr1.getInterleavedSamples();
double[] samples2 = _asr2.getInterleavedSamples();
// Mix!
samples1 = mix(samples1, samples2);
return writeSample(samples1);
}
public final static File mixTest(File file1, File file2) throws Exception {
// 0. Get an InputStream for the file
FileInputStream fis1 = new FileInputStream(file1);
// 1. new AudioSampleReader
AudioSampleReader asr1 = new AudioSampleReader(fis1);
// 2. get the interleaved samples
double[] sample1 = asr1.getInterleavedSamples();
// Do things with sample vals
// WRITE!
// 3. convert to byte[]
// 3a. get size the byte[] needs to be
int size = (int) asr1.getSampleCount()
* (SC_AUDIO_FORMAT.getSampleSizeInBits() / 8);
byte[] buffer = new byte[size];
// 3b. convert double[] to byte[]
int in;
for (int i = 0; i < sample1.length; i++) {
in = (int) (sample1[i] * 32767);
// First byte is in LSB
buffer[2 * i] = (byte) (in & 255);
buffer[2 * i + 1] = (byte) (in >> 8);
}
// 4. Data is now in buffer[]. Convert to ByteArrayInputStream.
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
// Convert to AudioInputStream
AudioInputStream ais = new AudioInputStream(bais, SC_AUDIO_FORMAT,
asr1.getSampleCount());
File tmpFile = File.createTempFile(randFileName(), ".wav");
FileOutputStream fos = new FileOutputStream(tmpFile);
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, fos);
fis1.close();
bais.close();
ais.close();
fos.flush();
fos.close();
return tmpFile;
}
public final InputStream append() throws IOException {
double[] samples1 = _asr1.getInterleavedSamples();
double[] samples2 = _asr2.getInterleavedSamples();
double[] appended = new double[samples1.length + samples2.length];
for (int i = 0; i < samples1.length; i++) {
appended[i] = samples1[i];
}
for (int i = 0; i < samples2.length; i++) {
appended[samples1.length + i] = samples2[i];
}
return writeSample(appended);
}
private static final double[] mix(double[] sample1, double[] sample2) {
for (int i = 0; i < sample1.length; i++) {
if (i >= sample2.length) {
sample1[i] = 0;
break;
}
sample1[i] = (sample1[i] + sample2[i]);
}
return sample1;
}
public final InputStream writeSample(double[] samples1) {
File tmpFile;
try {
tmpFile = File.createTempFile(randFileName(), ".wav");
tmpFile.deleteOnExit();
AudioSampleWriter asw = new AudioSampleWriter(tmpFile);
asw.write(samples1);
asw.close();
return new FileInputStream(tmpFile);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override public String toString() {
return _builder.toString();
}
private static final String randFileName() {
return Long.toHexString(Double.doubleToLongBits(Math.random()));
}
}

55
Java/src/nl/captcha/audio/AudioSampleReader.java

@ -6,15 +6,31 @@ import javax.sound.sampled.*;
public class AudioSampleReader {
public static final AudioFormat SC_AUDIO_FORMAT = new AudioFormat(
16000, // sample rate
16, // sample size in bits
1, // channels
true, // signed?
false); // big endian?;
private final AudioInputStream _audioInputStream;
private final AudioFormat _format;
public AudioSampleReader(InputStream is) throws IOException {
public AudioSampleReader(InputStream is) {
if (is instanceof AudioInputStream) {
_audioInputStream = (AudioInputStream) is;
_format = _audioInputStream.getFormat();
return;
}
try {
_audioInputStream = AudioSystem.getAudioInputStream(is);
_format = _audioInputStream.getFormat();
_audioInputStream = AudioSystem.getAudioInputStream(is);
_format = _audioInputStream.getFormat();
checkFormat(_format);
} catch (UnsupportedAudioFileException e) {
throw new IOException(e);
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@ -28,11 +44,12 @@ public class AudioSampleReader {
* @return
*/
public long getSampleCount() {
long total = (_audioInputStream.getFrameLength() * _format.getFrameSize() * 8)
long total = (_audioInputStream.getFrameLength()
* _format.getFrameSize() * 8)
/ _format.getSampleSizeInBits();
return total / _format.getChannels();
}
public double[] getInterleavedSamples() {
double[] samples = new double[(int) getSampleCount()];
try {
@ -42,7 +59,7 @@ public class AudioSampleReader {
} catch (IOException e) {
e.printStackTrace();
}
return samples;
}
@ -58,22 +75,24 @@ public class AudioSampleReader {
* @param samples
* @throws IOException
* @throws IllegalArgumentException
*/
public void getInterleavedSamples(long begin, long end, double[] samples)
*/
public double[] getInterleavedSamples(long begin, long end, double[] samples)
throws IOException, IllegalArgumentException {
long nbSamples = end - begin;
long nbBytes = nbSamples * (_format.getSampleSizeInBits() / 8)
* _format.getChannels();
if (nbBytes > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Too many samples. Try using a smaller wav.");
throw new IllegalArgumentException(
"Too many samples. Try using a smaller wav.");
}
// allocate a byte buffer
byte[] inBuffer = new byte[(int) nbBytes];
// read bytes from audio file
_audioInputStream.read(inBuffer, 0, inBuffer.length);
// decode bytes into samples. Supported encodings are:
// PCM-SIGNED, PCM-UNSIGNED, A-LAW, U-LAW
// decode bytes into samples.
decodeBytes(inBuffer, samples);
return samples;
}
/**
@ -83,7 +102,7 @@ public class AudioSampleReader {
* @param channel
* @param interleavedSamples
* @param channelSamples
*/
*/
public void getChannelSamples(int channel, double[] interleavedSamples,
double[] channelSamples) {
int nbChannels = _format.getChannels();
@ -112,7 +131,7 @@ public class AudioSampleReader {
}
// Decode bytes of audioBytes into audioSamples
private void decodeBytes(byte[] audioBytes, double[] audioSamples) {
public void decodeBytes(byte[] audioBytes, double[] audioSamples) {
int sampleSizeInBytes = _format.getSampleSizeInBits() / 8;
int[] sampleBytes = new int[sampleSizeInBytes];
int k = 0; // index in audioBytes
@ -144,4 +163,12 @@ public class AudioSampleReader {
audioSamples[i] = val;
}
}
private static final void checkFormat(AudioFormat af) throws IOException {
if (!af.matches(SC_AUDIO_FORMAT)) {
throw new IOException("Unsupported audio format.\nReceived: "
+ af.toString() + "\nExpected: " + SC_AUDIO_FORMAT);
}
}
}

89
Java/src/nl/captcha/audio/AudioSampleWriter.java

@ -3,45 +3,42 @@ package nl.captcha.audio;
import java.io.*;
import javax.sound.sampled.*;
import static nl.captcha.audio.AudioSampleReader.SC_AUDIO_FORMAT;
public class AudioSampleWriter implements Runnable {
private final File _file;
private final AudioFormat _format;
private final AudioFileFormat.Type _targetType;
private final PipedOutputStream _pos;
private final PipedInputStream _pis;
private final AudioInputStream _ais;
private File _file;
private PipedOutputStream _pos;
private PipedInputStream _pis;
private AudioInputStream _ais;
private byte[] _bytes;
// Have to use File here because writing to OutputStream exposes a bug
// in AudioSystem.write...
public AudioSampleWriter(File file, AudioFormat format,
AudioFileFormat.Type targetType) throws IOException {
public AudioSampleWriter(File file)
throws IOException {
_file = file;
_format = format;
_targetType = targetType;
// Write to the output stream
_pos = new PipedOutputStream();
// It will then go to the file via the input streams
_pis = new PipedInputStream(_pos);
_ais = new AudioInputStream(_pis, format, AudioSystem.NOT_SPECIFIED);
_ais = new AudioInputStream(_pis, SC_AUDIO_FORMAT,
AudioSystem.NOT_SPECIFIED);
new Thread(this).start();
}
public void run() {
try {
AudioSystem.write(_ais, _targetType, _file);
} catch(Exception e) {
AudioSystem.write(_ais, AudioFileFormat.Type.WAVE, _file);
} catch (Exception e) {
e.printStackTrace();
}
}
public void write(double[] interleavedSamples) throws IOException {
writeInterleavedSamples(interleavedSamples, interleavedSamples.length);
}
@ -53,54 +50,32 @@ public class AudioSampleWriter implements Runnable {
_pos.close();
}
}
private void writeInterleavedSamples(double[] interleavedSamples,
int sampleCount) throws IOException {
// Allocate a new bytes array if necessary. If bytes is too long,
// don't worry about it, just use as much as is needed.
int numBytes = sampleCount * (_format.getSampleSizeInBits() / 8);
int numBytes = sampleCount
* (SC_AUDIO_FORMAT.getSampleSizeInBits() / 8);
if (_bytes == null || numBytes > _bytes.length) {
_bytes = new byte[numBytes];
}
// Convert doubles to bytes using _format
encodeSamples(interleavedSamples, _bytes, sampleCount);
// write it
_pos.write(_bytes, 0, numBytes);
}
private void encodeSamples(double[] audioData, byte[] audioBytes,
int length) {
// TODO: Make private
public static void encodeSamples(double[] audioData, byte[] audioBytes, int length) {
int in;
if (_format.getSampleSizeInBits() == 16) {
if (_format.isBigEndian()) {
for (int i = 0; i < length; i++) {
in = (int)(audioData[i]*32767);
/* First byte is MSB (high order) */
audioBytes[2*i] = (byte)(in >> 8);
/* Second byte is LSB (low order) */
audioBytes[2*i+1] = (byte)(in & 255);
}
} else {
for (int i = 0; i < length; i++) {
in = (int)(audioData[i]*32767);
/* First byte is LSB (low order) */
audioBytes[2*i] = (byte)(in & 255);
/* Second byte is MSB (high order) */
audioBytes[2*i+1] = (byte)(in >> 8);
}
}
} else if (_format.getSampleSizeInBits() == 8) {
if (_format.getEncoding().toString().startsWith("PCM_SIGN")) {
for (int i = 0; i < length; i++) {
audioBytes[i] = (byte)(audioData[i]*127);
}
} else {
for (int i = 0; i < length; i++) {
audioBytes[i] = (byte)(audioData[i]*127 + 127);
}
}
for (int i = 0; i < length; i++) {
in = (int) (audioData[i] * 32767);
/* First byte is LSB (low order) */
audioBytes[2 * i] = (byte) (in & 255);
/* Second byte is MSB (high order) */
audioBytes[2 * i + 1] = (byte) (in >> 8);
}
}
}

109
Java/src/nl/captcha/audio/Mixer.java

@ -1,109 +0,0 @@
package nl.captcha.audio;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
public final class Mixer {
private final AudioSampleReader _asr1, _asr2;
public Mixer(InputStream is1, InputStream is2) throws IOException {
_asr1 = new AudioSampleReader(is1);
checkFormat(_asr1);
_asr2 = new AudioSampleReader(is2);
checkFormat(_asr2);
}
public final InputStream mix() {
double[] samples1 = _asr1.getInterleavedSamples();
double[] samples2 = _asr2.getInterleavedSamples();
// Mix!
samples1 = mix(samples1, samples2);
File tmpFile;
try {
tmpFile = File.createTempFile(randFileName(), "wav");
tmpFile.deleteOnExit();
AudioSampleWriter asw = new AudioSampleWriter(tmpFile,
_asr1.getFormat(), AudioFileFormat.Type.WAVE);
asw.write(samples1);
asw.close();
return new FileInputStream(tmpFile);
} catch (IOException e) {
e.printStackTrace();
}
// TODO: Delete tmpFile
return null;
}
public final InputStream append() throws IOException {
double[] samples1 = _asr1.getInterleavedSamples();
double[] samples2 = _asr2.getInterleavedSamples();
double[] appended = new double[samples1.length + samples2.length];
for (int i = 0; i < samples1.length; i++) {
appended[i] = samples1[i];
}
for (int i = 0; i < samples2.length; i++) {
appended[samples1.length + i] = samples2[i];
}
File tmpFile = File.createTempFile(randFileName(), "wav");
AudioSampleWriter asw = new AudioSampleWriter(tmpFile,
_asr1.getFormat(), AudioFileFormat.Type.WAVE);
asw.write(appended);
asw.close();
return new FileInputStream(tmpFile);
}
private final double[] mix(double[] sample1, double[] sample2) {
for (int i = 0; i < sample1.length; i++) {
if (i >= sample2.length) {
sample1[i] = 0;
break;
}
sample1[i] = (sample1[i] + sample2[i]);
}
return sample1;
}
private static final void checkFormat(AudioSampleReader asr)
throws IOException {
AudioFormat af = asr.getFormat();
if (!SupportedAudioFormat.isFormatSupported(af)) {
throw new IOException("Unsupported audio format.\nReceived: "
+ af.toString() + "\nExpected: "
+ SupportedAudioFormat.FORMAT);
}
}
private static final String randFileName() {
return Long.toHexString(Double.doubleToLongBits(Math.random()));
}
private static class SupportedAudioFormat {
public static final AudioFormat FORMAT = new AudioFormat(
16000, // sample rate
16, // sample size in bits
1, // channels
true, // signed?
false); // big endian?;
public static final boolean isFormatSupported(AudioFormat other) {
return other.matches(FORMAT);
}
}
}

55
Java/src/nl/captcha/audio/producer/RandomNumberVoiceProducer.java

@ -0,0 +1,55 @@
package nl.captcha.audio.producer;
import static nl.captcha.audio.AudioSampleReader.SC_AUDIO_FORMAT;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.Random;
import javax.sound.sampled.AudioInputStream;
import nl.captcha.audio.AudioSampleReader;
public class RandomNumberVoiceProducer implements VoiceProducer {
private static final Random RAND = new SecureRandom();
private static final String[] VOICES = { "alex", "bruce", "fred", "ralph",
"kathy", "vicki", "victoria" };
@Override
public InputStream getVocalizationOf(String num) {
InputStream is = RandomNumberVoiceProducer.class.getResourceAsStream(
"/sounds/en/numbers/2-fred.wav");
AudioSampleReader asr = new AudioSampleReader(is);
double[] sample = asr.getInterleavedSamples();
// convert to byte
int size = (int) asr.getSampleCount()
* (SC_AUDIO_FORMAT.getSampleSizeInBits() / 8);
byte[] buffer = new byte[size];
// convert double[] to byte[]
int in;
for (int i = 0; i < sample.length; i++) {
in = (int) (sample[i] * 32767);
buffer[2 * i] = (byte) (in & 255);
buffer[2 * i + 1] = (byte) (in >> 8);
}
InputStream bais = new ByteArrayInputStream(buffer);
InputStream ais = new AudioInputStream(bais, SC_AUDIO_FORMAT, asr.getSampleCount());
return ais;
}
private static final String getResourceNameForNum(int num) {
StringBuilder sb = new StringBuilder("/sounds/en/numbers/");
sb.append(num);
sb.append("-");
sb.append(VOICES[RAND.nextInt(VOICES.length)]);
sb.append(".wav");
return sb.toString();
}
}

7
Java/src/nl/captcha/audio/producer/VoiceProducer.java

@ -0,0 +1,7 @@
package nl.captcha.audio.producer;
import java.io.InputStream;
public interface VoiceProducer {
public InputStream getVocalizationOf(String str);
}

23
Java/src/nl/captcha/servlet/AudioCaptchaServlet.java

@ -8,7 +8,7 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import nl.captcha.audio.Mixer;
import nl.captcha.audio.AudioCaptcha;
public class AudioCaptchaServlet extends HttpServlet {
@ -18,14 +18,25 @@ public class AudioCaptchaServlet extends HttpServlet {
HttpServletResponse response) throws ServletException, IOException {
InputStream is2 = AudioCaptchaServlet.class
.getResourceAsStream("/sounds/askAquestion.wav");
.getResourceAsStream("/sounds/en/numbers/1-fred.wav");
InputStream is1 = AudioCaptchaServlet.class
.getResourceAsStream("/sounds/gridislive.wav");
Mixer mixer = new Mixer(is1, is2);
InputStream mixedIs = mixer.append();
.getResourceAsStream("/sounds/en/numbers/2-fred.wav");
AudioCaptcha mixer = new AudioCaptcha(is1, is2);
InputStream appendedIs = mixer.append();
System.out.println("[AudioCaptchaServlet] done appending voices.");
CaptchaServletUtil.writeAudio(response, mixedIs);
InputStream noise = AudioCaptchaServlet.class
.getResourceAsStream("/sounds/noise/restaurant.wav");
System.out.println("[AudioCaptchaServlet] appending noise to voices.");
AudioCaptcha mixer2 = new AudioCaptcha(appendedIs, noise);
InputStream mixedIs = mixer2.mix();
System.out
.println("[AudioCaptchaServlet] done appending noise to voices.");
// CaptchaServletUtil.writeAudio(response, mixedIs);
appendedIs.close();
mixedIs.close();
is2.close();
is1.close();

38
Java/src/nl/captcha/servlet/CaptchaServletUtil.java

@ -2,7 +2,6 @@ package nl.captcha.servlet;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
@ -12,7 +11,8 @@ public final class CaptchaServletUtil {
public static void writeImage(HttpServletResponse response, BufferedImage bi) {
response.setHeader("Cache-Control", "private,no-cache,no-store");
response.setContentType("image/png"); // PNGs allow for transparency. JPGs do not.
response.setContentType("image/png"); // PNGs allow for transparency.
// JPGs do not.
try {
writeImage(response.getOutputStream(), bi);
} catch (IOException e) {
@ -21,26 +21,26 @@ public final class CaptchaServletUtil {
}
public static void writeImage(OutputStream os, BufferedImage bi) {
try {
ImageIO.write(bi, "png", os);
os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
ImageIO.write(bi, "png", os);
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeAudio(HttpServletResponse response, InputStream is) throws IOException {
public static void writeAudio(HttpServletResponse response, byte[] wav) {
response.setHeader("Cache-Control", "private,no-cache,no-store");
response.setContentType("audio/x-wav");
OutputStream os = response.getOutputStream();
int readBytes = 0;
while ((readBytes = is.read()) != -1) {
os.write(readBytes);
}
response.setContentLength(wav.length);
os.close();
is.close();
try {
OutputStream os = response.getOutputStream();
os.write(wav);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

29
Java/src/nl/captcha/text/producer/NumberAnswerProducer.java

@ -0,0 +1,29 @@
package nl.captcha.text.producer;
/**
* TextProducer implementation that will return a series of numbers.
*
* @author <a href="mailto:james.childers@gmail.com">James Childers</a>
*
*/
public class NumberAnswerProducer implements TextProducer {
private static final int DEFAULT_LENGTH = 5;
private static final char[] NUMBERS = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9' };
private final TextProducer _txtProd;
public NumberAnswerProducer() {
this(DEFAULT_LENGTH);
}
public NumberAnswerProducer(int length) {
_txtProd = new DefaultTextProducer(length, NUMBERS);
}
@Override public String getText() {
return new StringBuffer(_txtProd.getText()).toString();
}
}

BIN
sounds/0-fred.wav

BIN
sounds/0-ralph.wav

BIN
sounds/1-fred.wav

BIN
sounds/1-ralph.wav

BIN
sounds/2-fred.wav

BIN
sounds/2-ralph.wav

BIN
sounds/3-fred.wav

BIN
sounds/3-ralph.wav

BIN
sounds/4-fred.wav

BIN
sounds/4-ralph.wav

BIN
sounds/5-fred.wav

BIN
sounds/5-ralph.wav

BIN
sounds/6-fred.wav

BIN
sounds/6-ralph.wav

BIN
sounds/7-fred.wav

BIN
sounds/7-ralph.wav

BIN
sounds/8-fred.wav

BIN
sounds/8-ralph.wav

BIN
sounds/9-fred.wav

BIN
sounds/9-ralph.wav

BIN
sounds/en/numbers/0-alex.wav

BIN
sounds/en/numbers/0-bruce.wav

BIN
sounds/en/numbers/0-fred.wav

BIN
sounds/en/numbers/0-kathy.wav

BIN
sounds/en/numbers/0-ralph.wav

BIN
sounds/en/numbers/0-vicki.wav

BIN
sounds/en/numbers/0-victoria.wav

BIN
sounds/en/numbers/1-alex.wav

BIN
sounds/en/numbers/1-bruce.wav

BIN
sounds/en/numbers/1-fred.wav

BIN
sounds/en/numbers/1-kathy.wav

BIN
sounds/en/numbers/1-ralph.wav

BIN
sounds/en/numbers/1-vicki.wav

BIN
sounds/en/numbers/1-victoria.wav

BIN
sounds/en/numbers/2-alex.wav

BIN
sounds/en/numbers/2-bruce.wav

BIN
sounds/en/numbers/2-fred.wav

BIN
sounds/en/numbers/2-kathy.wav

BIN
sounds/en/numbers/2-ralph.wav

BIN
sounds/en/numbers/2-vicki.wav

BIN
sounds/en/numbers/2-victoria.wav

BIN
sounds/en/numbers/3-alex.wav

BIN
sounds/en/numbers/3-bruce.wav

BIN
sounds/en/numbers/3-fred.wav

BIN
sounds/en/numbers/3-kathy.wav

BIN
sounds/en/numbers/3-ralph.wav

BIN
sounds/en/numbers/3-vicki.wav

BIN
sounds/en/numbers/3-victoria.wav

BIN
sounds/en/numbers/4-alex.wav

BIN
sounds/en/numbers/4-bruce.wav

BIN
sounds/en/numbers/4-fred.wav

BIN
sounds/en/numbers/4-kathy.wav

BIN
sounds/en/numbers/4-ralph.wav

BIN
sounds/en/numbers/4-vicki.wav

BIN
sounds/en/numbers/4-victoria.wav

BIN
sounds/en/numbers/5-alex.wav

BIN
sounds/en/numbers/5-bruce.wav

BIN
sounds/en/numbers/5-fred.wav

BIN
sounds/en/numbers/5-kathy.wav

BIN
sounds/en/numbers/5-ralph.wav

BIN
sounds/en/numbers/5-vicki.wav

BIN
sounds/en/numbers/5-victoria.wav

BIN
sounds/en/numbers/6-alex.wav

BIN
sounds/en/numbers/6-bruce.wav

BIN
sounds/en/numbers/6-fred.wav

BIN
sounds/en/numbers/6-kathy.wav

BIN
sounds/en/numbers/6-ralph.wav

BIN
sounds/en/numbers/6-vicki.wav

BIN
sounds/en/numbers/6-victoria.wav

BIN
sounds/en/numbers/7-alex.wav

BIN
sounds/en/numbers/7-bruce.wav

BIN
sounds/en/numbers/7-fred.wav

BIN
sounds/en/numbers/7-kathy.wav

BIN
sounds/en/numbers/7-ralph.wav

BIN
sounds/en/numbers/7-vicki.wav

BIN
sounds/en/numbers/7-victoria.wav

BIN
sounds/en/numbers/8-alex.wav

BIN
sounds/en/numbers/8-bruce.wav

BIN
sounds/en/numbers/8-fred.wav

BIN
sounds/en/numbers/8-kathy.wav

BIN
sounds/en/numbers/8-ralph.wav

BIN
sounds/en/numbers/8-vicki.wav

BIN
sounds/en/numbers/8-victoria.wav

BIN
sounds/en/numbers/9-alex.wav

BIN
sounds/en/numbers/9-bruce.wav

BIN
sounds/en/numbers/9-fred.wav

BIN
sounds/en/numbers/9-kathy.wav

BIN
sounds/en/numbers/9-ralph.wav

BIN
sounds/en/numbers/9-vicki.wav

BIN
sounds/en/numbers/9-victoria.wav

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save