jspeex/0000755000175000017500000000000010245633664012323 5ustar twernertwernerjspeex/dist/0000755000175000017500000000000010245633322013255 5ustar twernertwernerjspeex/lib/0000755000175000017500000000000010245633322013060 5ustar twernertwernerjspeex/include/0000755000175000017500000000000010245633324013737 5ustar twernertwernerjspeex/include/metainf/0000755000175000017500000000000010245633322015360 5ustar twernertwernerjspeex/include/metainf/services/0000755000175000017500000000000010245633322017203 5ustar twernertwernerjspeex/include/metainf/services/javax.sound.sampled.spi.AudioFileReader0000644000175000017500000000013310061610410026551 0ustar twernertwerner# Providers of Speex sound file-reading services org.xiph.speex.spi.SpeexAudioFileReader jspeex/include/metainf/services/javax.sound.sampled.spi.AudioFileWriter0000644000175000017500000000013310061610410026623 0ustar twernertwerner# Providers of Speex sound file-writing services org.xiph.speex.spi.SpeexAudioFileWriter jspeex/include/metainf/services/javax.sound.sampled.spi.FormatConversionProvider0000644000175000017500000000014210061610410030576 0ustar twernertwerner# Providers of Speex sound conversion services org.xiph.speex.spi.SpeexFormatConvertionProvider jspeex/src/0000755000175000017500000000000010245633324013103 5ustar twernertwernerjspeex/src/java/0000755000175000017500000000000010245633324014024 5ustar twernertwernerjspeex/src/java/org/0000755000175000017500000000000010245633324014613 5ustar twernertwernerjspeex/src/java/org/xiph/0000755000175000017500000000000010245633324015563 5ustar twernertwernerjspeex/src/java/org/xiph/speex/0000755000175000017500000000000010245633324016707 5ustar twernertwernerjspeex/src/java/org/xiph/speex/ant/0000755000175000017500000000000010245633324017471 5ustar twernertwernerjspeex/src/java/org/xiph/speex/ant/JSpeexDecoderTask.java0000644000175000017500000006236010135761046023653 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: JSpeexDecoderTask.java * * * * Author: Marc GIMPEL * * * * Date: Jun 4, 2004 * * * ******************************************************************************/ /* $Id: JSpeexDecoderTask.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ package org.xiph.speex.ant; import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Random; import java.util.Vector; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.FileSet; import org.xiph.speex.AudioFileWriter; import org.xiph.speex.NbEncoder; import org.xiph.speex.OggCrc; import org.xiph.speex.PcmWaveWriter; import org.xiph.speex.RawWriter; import org.xiph.speex.SbEncoder; import org.xiph.speex.SpeexDecoder; /** * Ant Task to Decode an audio file from Speex to PCM Wave. * Here is an usage example: *
 * 
 * 
 *   
 *     
 *       
 *     
 *   
 * 
 * 
* * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class JSpeexDecoderTask extends Task { /** Version of the Speex Encoder */ public static final String VERSION = "Java Speex Decoder Task v0.9.4 ($Revision: 1.2 $)"; /** Copyright display String */ public static final String COPYRIGHT = "Copyright (C) 2002-2004 Wimba S.A."; /** Print level for messages : Print debug information */ public static final int DEBUG = 0; /** Print level for messages : Print basic information */ public static final int INFO = 1; /** Print level for messages : Print only warnings and errors */ public static final int WARN = 2; /** Print level for messages : Print only errors */ public static final int ERROR = 3; /** File format for input or output audio file: Raw */ public static final int FILE_FORMAT_RAW = 0; /** File format for input or output audio file: Ogg */ public static final int FILE_FORMAT_OGG = 1; /** File format for input or output audio file: Wave */ public static final int FILE_FORMAT_WAVE = 2; /** Random number generator for packet loss simulation. */ protected static Random random = new Random(); /** Speex Decoder */ protected SpeexDecoder speexDecoder; /** Source file to decode */ private File srcFile; /** List of source files to decode */ private final Vector srcFileset = new Vector(); /** Destination file of decoded audio */ private File destFile; /** Directory to place destination files */ private File destDir; /** */ private boolean failOnError = true; /** Print level for messages */ private int printlevel = INFO; /** Tells the task to suppress all but the most important output */ private boolean quiet; /** Tells the task to output as much information as possible */ private boolean verbose; /** Defines File format for input audio file (Raw, Ogg or Wave). */ private int srcFormat; /** Defines File format for output audio file (Raw or Wave). */ private int destFormat; /** Defines whether or not the perceptual enhancement is used. */ private boolean enhanced = true; /** If input is raw, defines the decoder mode (0=NB, 1=WB and 2-UWB). */ private int mode = 0; /** If input is raw, defines the quality setting used by the encoder. */ private int quality = 8; /** If input is raw, defines the number of frmaes per packet. */ private int nframes = 1; /** If input is raw, defines the sample rate of the audio. */ private int sampleRate = -1; /** */ private float vbr_quality = -1; /** */ private boolean vbr = false; /** If input is raw, defines th number of channels (1=mono, 2=stereo). */ private int channels = 1; /** The percentage of packets to lose in the packet loss simulation. */ private int loss = 0; //------------------------------------------------------------------------- // Ant Task //------------------------------------------------------------------------- /** * The method executing the task. * @throws BuildException */ public void execute() throws BuildException { if (srcFile == null && srcFileset.size() == 0) { throw new BuildException("There must be a file attribute or a fileset child element"); } boolean hadError = false; if (srcFile != null) { if (destFile == null) { destFile = buildDestFile(srcFile); } try { setupTask(srcFile, destFile); decode(srcFile, destFile); } catch (IOException e) { log(e.getMessage()); } } for (int i=0; ifileset child element. * @param set */ public void addFileset(final FileSet set) { srcFileset.addElement(set); } /** * Handles the srcfile attribute. * @param file the attribute value converted to a File. */ public void setSrcfile(final File file) { this.srcFile = file; } /** * Handles the destfile attribute. * @param file the attribute value converted to a File. */ public void setDestfile(final File file) { this.destFile = file; } /** * Handles the destdir attribute. * @param dir the attribute value converted to a File. */ public void setDestdir(final File dir) { this.destDir = dir; } /** * Handles the failonerror attribute. * @param failOnError the attribute value converted to a boolean. */ public void setFailonerror(final boolean failOnError) { this.failOnError = failOnError; } /** * Handles the quiet attribute. * @param quiet the attribute value converted to a boolean. */ public void setQuiet(final boolean quiet) { this.quiet = quiet; this.printlevel = WARN; } /** * Handles the verbose attribute. * @param verbose the attribute value converted to a boolean. */ public void setVerbose(final boolean verbose) { this.verbose = verbose; this.printlevel = DEBUG; } /** * Handles the enhanced attribute. * @param enhanced the attribute value converted to a boolean. */ public void setEnhanced(final boolean enhanced) { this.enhanced = enhanced; } //------------------------------------------------------------------------- // Decoder //------------------------------------------------------------------------- /** * Prints the version. */ public void version() { log(VERSION); log("using " + SpeexDecoder.VERSION); log(COPYRIGHT); } /** * Decodes a spx file to wave. * @param srcPath the Speex encoded source file. * @param destPath the destination file. * @exception IOException */ public void decode(final File srcPath, final File destPath) throws IOException { byte[] header = new byte[2048]; byte[] payload = new byte[65536]; byte[] decdat = new byte[44100*2*2]; final int WAV_HEADERSIZE = 8; final short WAVE_FORMAT_SPEEX = (short) 0xa109; final String RIFF = "RIFF"; final String WAVE = "WAVE"; final String FORMAT = "fmt "; final String DATA = "data"; final int OGG_HEADERSIZE = 27; final int OGG_SEGOFFSET = 26; final String OGGID = "OggS"; int segments=0; int curseg=0; int bodybytes=0; int decsize=0; int packetNo=0; // Display info if (printlevel <= INFO) version(); if (printlevel <= DEBUG) log(""); if (printlevel <= DEBUG) log("Input File: " + srcPath); // construct a new decoder speexDecoder = new SpeexDecoder(); // open the input stream DataInputStream dis = new DataInputStream(new FileInputStream(srcPath)); AudioFileWriter writer = null; int origchksum; int chksum; try { // read until we get to EOF while (true) { if (srcFormat == FILE_FORMAT_OGG) { // read the OGG header dis.readFully(header, 0, OGG_HEADERSIZE); origchksum = readInt(header, 22); header[22] = 0; header[23] = 0; header[24] = 0; header[25] = 0; chksum=OggCrc.checksum(0, header, 0, OGG_HEADERSIZE); // make sure its a OGG header if (!OGGID.equals(new String(header, 0, 4))) { log("missing ogg id!"); return; } /* how many segments are there? */ segments = header[OGG_SEGOFFSET] & 0xFF; dis.readFully(header, OGG_HEADERSIZE, segments); chksum=OggCrc.checksum(chksum, header, OGG_HEADERSIZE, segments); /* decode each segment, writing output to wav */ for (curseg=0; curseg < segments; curseg++) { /* get the number of bytes in the segment */ bodybytes = header[OGG_HEADERSIZE+curseg] & 0xFF; if (bodybytes==255) { log("sorry, don't handle 255 sizes!"); return; } dis.readFully(payload, 0, bodybytes); chksum=OggCrc.checksum(chksum, payload, 0, bodybytes); /* decode the segment */ /* if first packet, read the Speex header */ if (packetNo == 0) { if (readSpeexHeader(payload, 0, bodybytes)) { if (printlevel <= DEBUG) { log("File Format: Ogg Speex"); log("Sample Rate: " + sampleRate); log("Channels: " + channels); log("Encoder mode: " + (mode==0 ? "Narrowband" : (mode==1 ? "Wideband" : "UltraWideband"))); log("Frames per packet: " + nframes); } /* once Speex header read, initialize the wave writer with output format */ if (destFormat == FILE_FORMAT_WAVE) { writer = new PcmWaveWriter(speexDecoder.getSampleRate(), speexDecoder.getChannels()); if (printlevel <= DEBUG) { log(""); log("Output File: " + destPath); log("File Format: PCM Wave"); log("Perceptual Enhancement: " + enhanced); } } else { writer = new RawWriter(); if (printlevel <= DEBUG) { log(""); log("Output File: " + destPath); log("File Format: Raw Audio"); log("Perceptual Enhancement: " + enhanced); } } writer.open(destPath); writer.writeHeader(null); packetNo++; } else { packetNo = 0; } } else if (packetNo == 1) { // Ogg Comment packet packetNo++; } else { if (loss>0 && random.nextInt(100) 0) { writer.writePacket(decdat, 0, decsize); } packetNo++; } } if (chksum != origchksum) throw new IOException("Ogg CheckSums do not match"); } else { // Wave or Raw Speex /* if first packet, initialise everything */ if (packetNo == 0) { if (srcFormat == FILE_FORMAT_WAVE) { // read the WAVE header dis.readFully(header, 0, WAV_HEADERSIZE+4); // make sure its a WAVE header if (!RIFF.equals(new String(header, 0, 4)) && !WAVE.equals(new String(header, 8, 4))) { log("Not a WAVE file"); return; } // Read other header chunks dis.readFully(header, 0, WAV_HEADERSIZE); String chunk = new String(header, 0, 4); int size = readInt(header, 4); while (!chunk.equals(DATA)) { dis.readFully(header, 0, size); if (chunk.equals(FORMAT)) { /* typedef struct waveformat_extended_tag { WORD wFormatTag; // format type WORD nChannels; // number of channels (i.e. mono, stereo...) DWORD nSamplesPerSec; // sample rate DWORD nAvgBytesPerSec; // for buffer estimation WORD nBlockAlign; // block size of data WORD wBitsPerSample; // Number of bits per sample of mono data WORD cbSize; // The count in bytes of the extra size } WAVEFORMATEX; */ if (readShort(header, 0) != WAVE_FORMAT_SPEEX) { log("Not a Wave Speex file"); return; } channels = readShort(header, 2); sampleRate = readInt(header, 4); bodybytes = readShort(header, 12); /* The extra data in the wave format are 18 : ACM major version number 19 : ACM minor version number 20-100 : Speex header 100-... : Comment ? */ if (readShort(header, 16) < 82) { log("Possibly corrupt Speex Wave file."); return; } readSpeexHeader(header, 20, 80); // Display audio info if (printlevel <= DEBUG) { log("File Format: Wave Speex"); log("Sample Rate: " + sampleRate); log("Channels: " + channels); log("Encoder mode: " + (mode==0 ? "Narrowband" : (mode==1 ? "Wideband" : "UltraWideband"))); log("Frames per packet: " + nframes); } } dis.readFully(header, 0, WAV_HEADERSIZE); chunk = new String(header, 0, 4); size = readInt(header, 4); } if (printlevel <= DEBUG) log("Data size: " + size); } else { if (printlevel <= DEBUG) { log("File Format: Raw Speex"); log("Sample Rate: " + sampleRate); log("Channels: " + channels); log("Encoder mode: " + (mode==0 ? "Narrowband" : (mode==1 ? "Wideband" : "UltraWideband"))); log("Frames per packet: " + nframes); } /* initialize the Speex decoder */ speexDecoder.init(mode, sampleRate, channels, enhanced); if (!vbr) { switch (mode) { case 0: bodybytes = NbEncoder.NB_FRAME_SIZE[NbEncoder.NB_QUALITY_MAP[quality]]; break; case 1: bodybytes = SbEncoder.NB_FRAME_SIZE[SbEncoder.NB_QUALITY_MAP[quality]]; bodybytes += SbEncoder.SB_FRAME_SIZE[SbEncoder.WB_QUALITY_MAP[quality]]; break; case 2: bodybytes = SbEncoder.NB_FRAME_SIZE[SbEncoder.NB_QUALITY_MAP[quality]]; bodybytes += SbEncoder.SB_FRAME_SIZE[SbEncoder.WB_QUALITY_MAP[quality]]; bodybytes += SbEncoder.SB_FRAME_SIZE[SbEncoder.UWB_QUALITY_MAP[quality]]; break; default: } bodybytes = (bodybytes + 7) >> 3; } else { // We have read the stream to find out more bodybytes = 0; } } /* initialize the wave writer with output format */ if (destFormat == FILE_FORMAT_WAVE) { writer = new PcmWaveWriter(sampleRate, channels); if (printlevel <= DEBUG) { log(""); log("Output File: " + destPath); log("File Format: PCM Wave"); log("Perceptual Enhancement: " + enhanced); } } else { writer = new RawWriter(); if (printlevel <= DEBUG) { log(""); log("Output File: " + destPath); log("File Format: Raw Audio"); log("Perceptual Enhancement: " + enhanced); } } writer.open(destPath); writer.writeHeader(null); packetNo++; } else { dis.readFully(payload, 0, bodybytes); if (loss>0 && random.nextInt(100) 0) { writer.writePacket(decdat, 0, decsize); } packetNo++; } } } } catch (EOFException eof) {} /* close the output file */ writer.close(); } /** * Reads the header packet. *
   *  0 -  7: speex_string: "Speex   "
   *  8 - 27: speex_version: "speex-1.0"
   * 28 - 31: speex_version_id: 1
   * 32 - 35: header_size: 80
   * 36 - 39: rate
   * 40 - 43: mode: 0=narrowband, 1=wb, 2=uwb
   * 44 - 47: mode_bitstream_version: 4
   * 48 - 51: nb_channels
   * 52 - 55: bitrate: -1
   * 56 - 59: frame_size: 160
   * 60 - 63: vbr
   * 64 - 67: frames_per_packet
   * 68 - 71: extra_headers: 0
   * 72 - 75: reserved1
   * 76 - 79: reserved2
   * 
* @param packet * @param offset * @param bytes * @return true if the Speex header was successfully parsed, false otherwise. */ private boolean readSpeexHeader(final byte[] packet, final int offset, final int bytes) { if (bytes!=80) { log("Oooops"); return false; } if (!"Speex ".equals(new String(packet, offset, 8))) { return false; } mode = packet[40+offset] & 0xFF; sampleRate = readInt(packet, offset+36); channels = readInt(packet, offset+48); nframes = readInt(packet, offset+64); return speexDecoder.init(mode, sampleRate, channels, enhanced); } /** * Converts Little Endian (Windows) bytes to an int (Java uses Big Endian). * @param data the data to read. * @param offset the offset from which to start reading. * @return the integer value of the reassembled bytes. */ protected static int readInt(final byte[] data, final int offset) { return (data[offset] & 0xff) | ((data[offset+1] & 0xff) << 8) | ((data[offset+2] & 0xff) << 16) | (data[offset+3] << 24); // no 0xff on the last one to keep the sign } /** * Converts Little Endian (Windows) bytes to an short (Java uses Big Endian). * @param data the data to read. * @param offset the offset from which to start reading. * @return the integer value of the reassembled bytes. */ protected static int readShort(final byte[] data, final int offset) { return (data[offset] & 0xff) | (data[offset+1] << 8); // no 0xff on the last one to keep the sign } } jspeex/src/java/org/xiph/speex/ant/JSpeexEncoderTask.java0000644000175000017500000005136210135761046023665 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: JSpeexEncoderTask.java * * * * Author: Marc GIMPEL * * * * Date: Jun 4, 2004 * * * ******************************************************************************/ /* $Id: JSpeexEncoderTask.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ package org.xiph.speex.ant; import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Vector; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.FileSet; import org.xiph.speex.AudioFileWriter; import org.xiph.speex.OggSpeexWriter; import org.xiph.speex.PcmWaveWriter; import org.xiph.speex.RawWriter; import org.xiph.speex.SpeexDecoder; import org.xiph.speex.SpeexEncoder; /** * Ant Task to Encode an audio file from PCM Wave to Speex. * Here is an usage example: *
 * 
 * 
 *   
 *     
 *       
 *     
 *   
 * 
 * 
* * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class JSpeexEncoderTask extends Task { /** Version of the Speex Encoder */ public static final String VERSION = "Java Speex Encoder Task v0.9.4 ($Revision: 1.2 $)"; /** Copyright display String */ public static final String COPYRIGHT = "Copyright (C) 2002-2004 Wimba S.A."; /** Print level for messages : Print debug information */ public static final int DEBUG = 0; /** Print level for messages : Print basic information */ public static final int INFO = 1; /** Print level for messages : Print only warnings and errors */ public static final int WARN = 2; /** Print level for messages : Print only errors */ public static final int ERROR = 3; /** File format for input or output audio file: Raw */ public static final int FILE_FORMAT_RAW = 0; /** File format for input or output audio file: Ogg */ public static final int FILE_FORMAT_OGG = 1; /** File format for input or output audio file: Wave */ public static final int FILE_FORMAT_WAVE = 2; /** Source file to decode */ private File srcFile; /** List of source files to decode */ private final Vector srcFileset = new Vector(); /** Destination file of decoded audio */ private File destFile; /** Directory to place destination files */ private File destDir; /** */ private boolean failOnError = true; /** Print level for messages */ private int printlevel = INFO; /** Tells the task to suppress all but the most important output */ private boolean quiet; /** Tells the task to output as much information as possible */ private boolean verbose; /** Defines File format for input audio file (Raw, Ogg or Wave). */ protected int srcFormat = FILE_FORMAT_OGG; /** Defines File format for output audio file (Raw or Wave). */ protected int destFormat = FILE_FORMAT_WAVE; /** Whether the mode is manualy set or automatically determined. */ protected boolean modeset = false; /** Defines the encoder mode (0=NB, 1=WB and 2-UWB). */ protected int mode = -1; /** Defines the encoder quality setting (integer from 0 to 10). */ protected int quality = 8; /** Defines the encoders algorithmic complexity. */ protected int complexity = 3; /** Defines the number of frames per speex packet. */ protected int nframes = 1; /** Defines the desired bitrate for the encoded audio. */ protected int bitrate = -1; /** Defines the sampling rate of the audio input. */ protected int sampleRate = -1; /** Defines the number of channels of the audio input (1=mono, 2=stereo). */ protected int channels = 1; /** Defines the encoder VBR quality setting (float from 0 to 10). */ protected float vbr_quality = -1; /** Defines whether or not to use VBR (Variable Bit Rate). */ protected boolean vbr = false; /** Defines whether or not to use VAD (Voice Activity Detection). */ protected boolean vad = false; /** Defines whether or not to use DTX (Discontinuous Transmission). */ protected boolean dtx = false; //------------------------------------------------------------------------- // Ant Task //------------------------------------------------------------------------- /** * The method executing the task. * @throws BuildException */ public void execute() throws BuildException { if (srcFile == null && srcFileset.size() == 0) { throw new BuildException("There must be a file attribute or a fileset child element"); } boolean hadError = false; if (srcFile != null) { if (destFile == null) { destFile = buildDestFile(srcFile); } try { setupTask(srcFile, destFile); encode(srcFile, destFile); } catch (IOException e) { log(e.getMessage()); } } for (int i=0; ifileset child element. * @param set */ public void addFileset(final FileSet set) { srcFileset.addElement(set); } /** * Handles the srcfile attribute. * @param file the attribute value converted to a File. */ public void setSrcfile(final File file) { this.srcFile = file; } /** * Handles the destfile attribute. * @param file the attribute value converted to a File. */ public void setDestfile(final File file) { this.destFile = file; } /** * Handles the destdir attribute. * @param dir the attribute value converted to a File. */ public void setDestdir(final File dir) { this.destDir = dir; } /** * Handles the failonerror attribute. * @param failOnError the attribute value converted to a boolean. */ public void setFailonerror(final boolean failOnError) { this.failOnError = failOnError; } /** * Handles the quiet attribute. * @param quiet the attribute value converted to a boolean. */ public void setQuiet(final boolean quiet) { this.quiet = quiet; this.printlevel = WARN; } /** * Handles the verbose attribute. * @param verbose the attribute value converted to a boolean. */ public void setVerbose(final boolean verbose) { this.verbose = verbose; this.printlevel = DEBUG; } /** * Handles the quality attribute. * @param quality the attribute value converted to a float. */ public void setQuality(float quality) { if (quality < 0) quality = 0; if (quality > 10) quality = 10; this.quality = (int) quality; this.vbr_quality = quality; } /** * Handles the complexity attribute. * @param complexity the attribute value converted to an integer. */ public void setComplexity(final int complexity) { this.complexity = complexity; } /** * Handles the nframes attribute. * @param nframes the attribute value converted to an integer. */ public void setNframes(final int nframes) { this.nframes = nframes; } /** * Handles the vbr attribute. * @param vbr the attribute value converted to a boolean. */ public void setVbr(final boolean vbr) { this.vbr = vbr; } /** * Handles the vad attribute. * @param vad the attribute value converted to a boolean. */ public void setVad(final boolean vad) { this.vad = vad; } /** * Handles the dtx attribute. * @param dtx the attribute value converted to a boolean. */ public void setDtx(final boolean dtx) { this.dtx = dtx; } /** * Handles the mode attribute. * @param mode the attribute value converted to a String. */ public void setMode(final String mode) { modeset = true; if ("ultrawideband".equalsIgnoreCase(mode) || "uwb".equalsIgnoreCase(mode) || "2".equals(mode)) this.mode = 2; else if ("wideband".equalsIgnoreCase(mode) || "wb".equalsIgnoreCase(mode) || "1".equals(mode)) this.mode = 1; else if ("narrowband".equalsIgnoreCase(mode) || "nb".equalsIgnoreCase(mode) || "0".equals(mode)) this.mode = 0; else { this.mode = -1; } } //------------------------------------------------------------------------- // Encoder //------------------------------------------------------------------------- /** * Prints the version. */ public void version() { log(VERSION); log("using " + SpeexDecoder.VERSION); log(COPYRIGHT); } /** * Encodes a PCM file to Speex. * @param srcPath * @param destPath * @exception IOException */ public void encode(final File srcPath, final File destPath) throws IOException { byte[] temp = new byte[2560]; // stereo UWB requires one to read 2560b final int HEADERSIZE = 8; final String RIFF = "RIFF"; final String WAVE = "WAVE"; final String FORMAT = "fmt "; final String DATA = "data"; final int WAVE_FORMAT_PCM = 0x0001; // Display info if (printlevel <= INFO) version(); if (printlevel <= DEBUG) System.out.println(""); if (printlevel <= DEBUG) System.out.println("Input File: " + srcPath); // Open the input stream DataInputStream dis = new DataInputStream(new FileInputStream(srcPath)); // Prepare input stream if (srcFormat == FILE_FORMAT_WAVE) { // read the WAVE header dis.readFully(temp, 0, HEADERSIZE+4); // make sure its a WAVE header if (!RIFF.equals(new String(temp, 0, 4)) && !WAVE.equals(new String(temp, 8, 4))) { System.err.println("Not a WAVE file"); return; } // Read other header chunks dis.readFully(temp, 0, HEADERSIZE); String chunk = new String(temp, 0, 4); int size = readInt(temp, 4); while (!chunk.equals(DATA)) { dis.readFully(temp, 0, size); if (chunk.equals(FORMAT)) { /* typedef struct waveformat_extended_tag { WORD wFormatTag; // format type WORD nChannels; // number of channels (i.e. mono, stereo...) DWORD nSamplesPerSec; // sample rate DWORD nAvgBytesPerSec; // for buffer estimation WORD nBlockAlign; // block size of data WORD wBitsPerSample; // Number of bits per sample of mono data WORD cbSize; // The count in bytes of the extra size } WAVEFORMATEX; */ if (readShort(temp, 0) != WAVE_FORMAT_PCM) { System.err.println("Not a PCM file"); return; } channels = readShort(temp, 2); sampleRate = readInt(temp, 4); if (readShort(temp, 14) != 16) { System.err.println("Not a 16 bit file " + readShort(temp, 18)); return; } // Display audio info if (printlevel <= DEBUG) { System.out.println("File Format: PCM wave"); System.out.println("Sample Rate: " + sampleRate); System.out.println("Channels: " + channels); } } dis.readFully(temp, 0, HEADERSIZE); chunk = new String(temp, 0, 4); size = readInt(temp, 4); } if (printlevel <= DEBUG) System.out.println("Data size: " + size); } else { if (sampleRate < 0) { switch (mode) { case 0: sampleRate = 8000; break; case 1: sampleRate = 16000; break; case 2: sampleRate = 32000; break; default: sampleRate = 8000; break; } } // Display audio info if (printlevel <= DEBUG) { System.out.println("File format: Raw audio"); System.out.println("Sample rate: " + sampleRate); System.out.println("Channels: " + channels); System.out.println("Data size: " + srcPath.length()); } } // Set the mode if it has not yet been determined if (mode < 0) { if (sampleRate < 100) // Sample Rate has probably been given in kHz sampleRate *= 1000; if (sampleRate < 12000) mode = 0; // Narrowband else if (sampleRate < 24000) mode = 1; // Wideband else mode = 2; // Ultra-wideband } // Construct a new encoder SpeexEncoder speexEncoder = new SpeexEncoder(); speexEncoder.init(mode, quality, sampleRate, channels); if (complexity > 0) { speexEncoder.getEncoder().setComplexity(complexity); } if (bitrate > 0) { speexEncoder.getEncoder().setBitRate(bitrate); } if (vbr) { speexEncoder.getEncoder().setVbr(vbr); if (vbr_quality > 0) { speexEncoder.getEncoder().setVbrQuality(vbr_quality); } } if (vad) { speexEncoder.getEncoder().setVad(vad); } if (dtx) { speexEncoder.getEncoder().setDtx(dtx); } // Display info if (printlevel <= DEBUG) { System.out.println(""); System.out.println("Output File: " + destPath); System.out.println("File format: Ogg Speex"); System.out.println("Encoder mode: " + (mode==0 ? "Narrowband" : (mode==1 ? "Wideband" : "UltraWideband"))); System.out.println("Quality: " + (vbr ? vbr_quality : quality)); System.out.println("Complexity: " + complexity); System.out.println("Frames per packet: " + nframes); System.out.println("Varible bitrate: " + vbr); System.out.println("Voice activity detection: " + vad); System.out.println("Discontinouous Transmission: " + dtx); } // Open the file writer AudioFileWriter writer; if (destFormat == FILE_FORMAT_OGG) { writer = new OggSpeexWriter(mode, sampleRate, channels, nframes, vbr); } else if (destFormat == FILE_FORMAT_WAVE) { nframes = PcmWaveWriter.WAVE_FRAME_SIZES[mode-1][channels-1][quality]; writer = new PcmWaveWriter(mode, quality, sampleRate, channels, nframes, vbr); } else { writer = new RawWriter(); } writer.open(destPath); writer.writeHeader("Encoded with: " + VERSION); int pcmPacketSize = 2 * channels * speexEncoder.getFrameSize(); try { // read until we get to EOF while (true) { dis.readFully(temp, 0, nframes*pcmPacketSize); for (int i=0; i 0) { writer.writePacket(temp, 0, encsize); } } } catch (EOFException e) {} writer.close(); } /** * Converts Little Endian (Windows) bytes to an int (Java uses Big Endian). * @param data the data to read. * @param offset the offset from which to start reading. * @return the integer value of the reassembled bytes. */ protected static int readInt(final byte[] data, final int offset) { return (data[offset] & 0xff) | ((data[offset+1] & 0xff) << 8) | ((data[offset+2] & 0xff) << 16) | (data[offset+3] << 24); // no 0xff on the last one to keep the sign } /** * Converts Little Endian (Windows) bytes to an short (Java uses Big Endian). * @param data the data to read. * @param offset the offset from which to start reading. * @return the integer value of the reassembled bytes. */ protected static int readShort(final byte[] data, final int offset) { return (data[offset] & 0xff) | (data[offset+1] << 8); // no 0xff on the last one to keep the sign } } jspeex/src/java/org/xiph/speex/ant/package.html0000644000175000017500000000041010135522576021751 0ustar twernertwerner JSpeex Ant Package

JSpeex Ant package.

It contains the Ant tasks for encoding and decoding Speex files.

$Id: package.html,v 1.1 2004/10/20 17:50:54 mgimpel Exp $ jspeex/src/java/org/xiph/speex/spi/0000755000175000017500000000000010245633324017502 5ustar twernertwernerjspeex/src/java/org/xiph/speex/spi/FilteredAudioInputStream.java0000644000175000017500000004601710135761046025272 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: FilteredAudioInputStream.java * * * * Author: Marc GIMPEL * * * * Date: 12th July 2003 * * * ******************************************************************************/ /* $Id: FilteredAudioInputStream.java,v 1.2 2004/10/21 16:21:58 mgimpel Exp $ */ package org.xiph.speex.spi; import java.io.IOException; import java.io.InputStream; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; /** * A FilteredAudioInputStream is an AudioInputStream with buffers * to facilitate transcoding the audio. * A first byte array can buffer the data from the underlying inputstream until * sufficient data for transcoding is present. * A second byte array can hold the transcoded audio data, ready to be read out * by the stream user. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public abstract class FilteredAudioInputStream extends AudioInputStream { /** The default size of the buffer. */ public static final int DEFAULT_BUFFER_SIZE = 2048; /** The underlying inputStream. */ protected InputStream in; /** * The internal buffer array where the data is stored. When necessary, * it may be replaced by another array of a different size. */ protected byte[] buf; /** * The index one greater than the index of the last valid byte in the buffer. * This value is always in the range 0 through buf.length; * elements buf[0] through buf[count-1] contain * buffered input data obtained and filtered from the underlying inputstream. */ protected int count; /** * The current position in the buffer. This is the index of the next * character to be read from the buf array. *

* This value is always in the range 0 through count. * If it is less than count, then buf[pos] is the * next byte to be supplied as input. * If it is equal to count, then the next read or * skip operation will require more bytes to be read and * filtered from the underlying inputstream. * * @see #buf */ protected int pos; /** * The value of the pos field at the time the last * mark method was called. *

* This value is always in the range -1 through pos. * If there is no marked position in the inputstream, this field is -1. * If there is a marked position in the inputstream, then * buf[markpos] is the first byte to be supplied as input after * a reset operation. * If markpos is not -1, then all bytes from positions * buf[markpos] through buf[pos-1] must remain in * the buffer array (though they may be moved to another place in the buffer * array, with suitable adjustments to the values of count, * pos, and markpos); they may not be discarded * unless and until the difference between pos and * markpos exceeds marklimit. * * @see #mark(int) * @see #pos */ protected int markpos; /** * The maximum read ahead allowed after a call to the mark * method before subsequent calls to the reset method fail. * Whenever the difference between pos and markpos * exceeds marklimit, then the mark may be dropped by setting * markpos to -1. * * @see #mark(int) * @see #reset() */ protected int marklimit; /** * Array of size 1, used by the read method to read just 1 byte. */ private final byte[] single = new byte[1]; /** * The internal buffer array where the unfiltered data is temporarily stored. */ protected byte[] prebuf; /** * The index one greater than the index of the last valid byte in the * unfiltered data buffer. * This value is always in the range 0 through prebuf.length; * elements prebuf[0] through prebuf[count-1] * contain buffered input data obtained from the underlying input stream. */ protected int precount; /** * The current position in the unfiltered data buffer. This is the index of * the next character to be read from the prebuf array. *

* This value is always in the range 0 through precount. * If it is less than precount, then prebuf[pos] is * the next byte to be supplied as input. * If it is equal to precount, then the next read * or skip operation will require more bytes to be read from the * contained inputstream. * * @see #prebuf */ protected int prepos; /** * Check to make sure that this stream has not been closed * @exception IOException */ protected void checkIfStillOpen() throws IOException { if (in == null) throw new IOException("Stream closed"); } /** * Creates a FilteredAudioInputStream and saves its argument, * the input stream in, for later use. * An internal buffer array is created and stored in buf. * * @param in the underlying input stream. * @param format the format of this stream's audio data. * @param length the length in sample frames of the data in this stream. * @exception IllegalArgumentException if size <= 0 or presize <= 0. */ public FilteredAudioInputStream(final InputStream in, final AudioFormat format, final long length) { this(in, format, length, DEFAULT_BUFFER_SIZE); } /** * Creates a FilteredAudioInputStream with the specified buffer * size, and saves its argument, the inputstream in for later use. * An internal buffer array of length size is created and stored * in buf. * * @param in the underlying input stream. * @param format the format of this stream's audio data. * @param length the length in sample frames of the data in this stream. * @param size the buffer sizes. * @exception IllegalArgumentException if size <= 0. */ public FilteredAudioInputStream(final InputStream in, final AudioFormat format, final long length, final int size) { this(in, format, length, size, size); } /** * Creates a FilteredAudioInputStream with the specified buffer * size, and saves its argument, the inputstream in for later use. * An internal buffer array of length size is created and stored * in buf. * * @param in the underlying input stream. * @param format the format of this stream's audio data. * @param length the length in sample frames of the data in this stream. * @param size the buffer size. * @param presize the prebuffer size. * @exception IllegalArgumentException if size <= 0 or presize <= 0. */ public FilteredAudioInputStream(final InputStream in, final AudioFormat format, final long length, final int size, final int presize) { super(in, format, length); this.in = in; if ((size <= 0) || (presize <= 0)) { throw new IllegalArgumentException("Buffer size <= 0"); } buf = new byte[size]; count = 0; prebuf = new byte[presize]; precount = 0; marklimit = size; markpos = -1; } /** * Fills the buffer with more data, taking into account shuffling and other * tricks for dealing with marks. * Assumes that it is being called by a synchronized method. * This method also assumes that all data has already been read in, * hence pos > count. * @exception IOException */ protected void fill() throws IOException { makeSpace(); while (true) { int read = in.read(prebuf, precount, prebuf.length - precount); if (read < 0) { // inputstream has ended // do last stuff here break; } else if (read > 0) { // do stuff here precount += read; break; } else { // read == 0 // read 0 bytes from underlying stream yet it is not finished. } } } /** * Free up some space in the buffers. */ protected void makeSpace() { if (markpos < 0) pos = 0; /* no mark: throw away the buffer */ else if (pos >= buf.length) /* no room left in buffer */ if (markpos > 0) { /* can throw away early part of the buffer */ int sz = pos - markpos; System.arraycopy(buf, markpos, buf, 0, sz); pos = sz; markpos = 0; } else if (buf.length >= marklimit) { markpos = -1; /* buffer got too big, invalidate mark */ pos = 0; /* drop buffer contents */ } else { /* grow buffer */ int nsz = pos * 2; if (nsz > marklimit) nsz = marklimit; byte[] nbuf = new byte[nsz]; System.arraycopy(buf, 0, nbuf, 0, pos); buf = nbuf; } count = pos; } /** * See the general contract of the read method of * InputStream. * * @return the next byte of data, or -1 if the end of the * stream is reached. * @exception IOException if an I/O error occurs. * @see #in */ public synchronized int read() throws IOException { if (read(single, 0, 1) == -1) { return (-1); } else { return (single[0] & 0xFF); } } /** * Reads bytes from this byte-input stream into the specified byte array, * starting at the given offset. * *

This method implements the general contract of the corresponding * {@link InputStream#read(byte[], int, int) read} method of * the {@link InputStream} class. As an additional * convenience, it attempts to read as many bytes as possible by repeatedly * invoking the read method of the underlying stream. This * iterated read continues until one of the following * conditions becomes true:

    * *
  • The specified number of bytes have been read, * *
  • The read method of the underlying stream returns * -1, indicating end-of-file, or * *
  • The available method of the underlying stream * returns zero, indicating that further input requests would block. * *
If the first read on the underlying stream returns * -1 to indicate end-of-file then this method returns * -1. Otherwise this method returns the number of bytes * actually read. * *

Subclasses of this class are encouraged, but not required, to * attempt to read as many bytes as possible in the same fashion. * * @param b destination buffer. * @param off offset at which to start storing bytes. * @param len maximum number of bytes to read. * @return the number of bytes read, or -1 if the end of * the stream has been reached. * @exception IOException if an I/O error occurs. */ public synchronized int read(final byte[] b, final int off, final int len) throws IOException { checkIfStillOpen(); if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int avail = count - pos; if (avail <= 0) { fill(); avail = count - pos; if (avail <= 0) return -1; } int cnt = (avail < len) ? avail : len; System.arraycopy(buf, pos, b, off, cnt); pos += cnt; return cnt; } /** * See the general contract of the skip method of * InputStream. * * @param n the number of bytes to be skipped. * @return the actual number of bytes skipped. * @exception IOException if an I/O error occurs. */ public synchronized long skip(final long n) throws IOException { checkIfStillOpen(); // Sanity check if (n <= 0) { return 0; } // Skip buffered data if there is any if (pos < count) { int avail = count - pos; if (avail > n) { pos += n; return n; } else { pos = count; return avail; } } // Read into buffers and skip else { fill(); // This is potentially blocking (i.e. the read on the underlying inputStream could be blocking) int avail = count - pos; if (avail <= 0) return 0; long skipped = (avail < n) ? avail : n; pos += skipped; return skipped; } } /** * Returns the number of bytes that can be read from this inputstream without * blocking. *

* The available method of FilteredAudioInputStream * returns the sum of the the number of bytes remaining to be read in the * buffer (count - pos). * The result of calling the available method of the underlying * inputstream is not used, as this data will have to be filtered, and thus * may not be the same size after processing (although subclasses that do the * filtering should override this method and use the amount of data available * in the underlying inputstream). * * @return the number of bytes that can be read from this inputstream without * blocking. * @exception IOException if an I/O error occurs. * @see #in */ public synchronized int available() throws IOException { checkIfStillOpen(); return (count - pos); } /** * See the general contract of the mark method of * InputStream. * * @param readlimit the maximum limit of bytes that can be read before * the mark position becomes invalid. * @see #reset() */ public synchronized void mark(final int readlimit) { if (readlimit > buf.length - pos) { // not enough room byte[] newbuf; if (readlimit <= buf.length) { newbuf = buf; // just shift buffer } else { newbuf = new byte[readlimit]; // need a new buffer } System.arraycopy(buf, pos, newbuf, 0, count - pos); buf = newbuf; count -= pos; pos = markpos = 0; } else { markpos = pos; } marklimit = readlimit; } /** * See the general contract of the reset method of * InputStream. *

* If markpos is -1 (no mark has been set or the mark has been * invalidated), an IOException is thrown. * Otherwise, pos is set equal to markpos. * * @exception IOException if this stream has not been marked or * if the mark has been invalidated. * @see #mark(int) */ public synchronized void reset() throws IOException { checkIfStillOpen(); if (markpos < 0) throw new IOException("Attempt to reset when no mark is valid"); pos = markpos; } /** * Tests if this input stream supports the mark and * reset methods. The markSupported method of * FilteredAudioInputStream returns true. * * @return a boolean indicating if this stream type supports * the mark and reset methods. * @see #mark(int) * @see #reset() */ public boolean markSupported() { return true; } /** * Closes this input stream and releases any system resources associated with * the stream. * * @exception IOException if an I/O error occurs. */ public synchronized void close() throws IOException { if (in == null) return; in.close(); in = null; buf = null; prebuf = null; } } jspeex/src/java/org/xiph/speex/spi/Pcm2SpeexAudioInputStream.java0000644000175000017500000005675510135761046025354 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Pcm2SpeexAudioInputStream.java * * * * Author: Marc GIMPEL * * * * Date: 12th July 2003 * * * ******************************************************************************/ /* $Id: Pcm2SpeexAudioInputStream.java,v 1.2 2004/10/21 16:21:58 mgimpel Exp $ */ package org.xiph.speex.spi; import java.util.Random; import java.io.IOException; import java.io.InputStream; import java.io.StreamCorruptedException; import javax.sound.sampled.AudioFormat; import org.xiph.speex.AudioFileWriter; import org.xiph.speex.OggCrc; import org.xiph.speex.Encoder; import org.xiph.speex.SpeexEncoder; /** * Converts a PCM 16bits/sample mono audio stream to Ogg Speex * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class Pcm2SpeexAudioInputStream extends FilteredAudioInputStream { /** The default size of the buffer (UWB stereo requires at least 2560b). */ public static final int DEFAULT_BUFFER_SIZE = 2560; // public static final boolean DEFAULT_VBR = true; /** The default sample rate if none is given in the constructor. */ public static final int DEFAULT_SAMPLERATE = 8000; /** The default number of channels if none is given in the constructor. */ public static final int DEFAULT_CHANNELS = 1; /** The default quality setting for the Speex encoder. */ public static final int DEFAULT_QUALITY = 3; /** The default number of Speex frames that will be put in each Ogg packet. */ public static final int DEFAULT_FRAMES_PER_PACKET = 1; /** The default number of Ogg packets that will be put in each Ogg page. */ public static final int DEFAULT_PACKETS_PER_OGG_PAGE = 20; // .4s of audio /** Indicates the value is unknown or undetermined. */ public static final int UNKNOWN = -1; // Speex variables /** The Speex Encoder class. */ private SpeexEncoder encoder; /** The encoder mode (0=NB, 1=WB, 2=UWB). */ private int mode; /** The size in bytes of PCM data that will be encoded into 1 Speex frame. */ private int frameSize; /** The number of Speex frames that will be put in each Ogg packet. */ private int framesPerPacket; /** The number of audio channels (1=mono, 2=stereo). */ private int channels; // Ogg variables /** The comment String that will appear in the Ogg comment packet. */ private String comment = null; /** A counter for the number of PCM samples that have been encoded. */ private int granulepos; /** A unique serial number that identifies the Ogg stream. */ private int streamSerialNumber; /** The number of Ogg packets that will be put in each Ogg page. */ private int packetsPerOggPage; /** The number of Ogg packets that have been encoded in the current page. */ private int packetCount; /** The number of Ogg pages that have been written to the stream. */ private int pageCount; /** Pointer in the buffer to the point where Ogg data is added. */ private int oggCount; /** Flag to indicate if this is the first time a encode method is called. */ private boolean first; /** * Constructor * @param in the underlying input stream. * @param format the target format of this stream's audio data. * @param length the length in sample frames of the data in this stream. */ public Pcm2SpeexAudioInputStream(final InputStream in, final AudioFormat format, final long length) { this(UNKNOWN, UNKNOWN, in, format, length, DEFAULT_BUFFER_SIZE); } /** * Constructor * @param mode the mode of the encoder (0=NB, 1=WB, 2=UWB). * @param quality the quality setting of the encoder (between 0 and 10). * @param in the underlying input stream. * @param format the target format of this stream's audio data. * @param length the length in sample frames of the data in this stream. */ public Pcm2SpeexAudioInputStream(final int mode, final int quality, final InputStream in, final AudioFormat format, final long length) { this(mode, quality, in, format, length, DEFAULT_BUFFER_SIZE); } /** * Constructor * @param in the underlying input stream. * @param format the target format of this stream's audio data. * @param length the length in sample frames of the data in this stream. * @param size the buffer size. * @exception IllegalArgumentException if size <= 0. */ public Pcm2SpeexAudioInputStream(final InputStream in, final AudioFormat format, final long length, final int size) { this(UNKNOWN, UNKNOWN, in, format, length, size); } /** * Constructor * @param mode the mode of the encoder (0=NB, 1=WB, 2=UWB). * @param quality the quality setting of the encoder (between 0 and 10). * @param in the underlying input stream. * @param format the target format of this stream's audio data. * @param length the length in sample frames of the data in this stream. * @param size the buffer size. * @exception IllegalArgumentException if size <= 0. */ public Pcm2SpeexAudioInputStream(int mode, int quality, final InputStream in, final AudioFormat format, final long length, final int size) { super(in, format, length, size); // Ogg initialisation granulepos = 0; if (streamSerialNumber == 0) streamSerialNumber = new Random().nextInt(); packetsPerOggPage = DEFAULT_PACKETS_PER_OGG_PAGE; packetCount = 0; pageCount = 0; // Speex initialisation framesPerPacket = DEFAULT_FRAMES_PER_PACKET; int samplerate = (int) format.getSampleRate(); if (samplerate < 0) samplerate = DEFAULT_SAMPLERATE; channels = format.getChannels(); if (channels < 0) channels = DEFAULT_CHANNELS; if (mode < 0) mode = (samplerate < 12000) ? 0 : ((samplerate < 24000) ? 1 : 2); this.mode = mode; AudioFormat.Encoding encoding = format.getEncoding(); if (quality < 0) { if (encoding instanceof SpeexEncoding) { quality = ((SpeexEncoding) encoding).getQuality(); } else { quality = DEFAULT_QUALITY; } } encoder = new SpeexEncoder(); encoder.init(mode, quality, samplerate, channels); if (encoding instanceof SpeexEncoding && ((SpeexEncoding) encoding).isVBR()) { setVbr(true); } else { setVbr(false); } frameSize = 2 * channels * encoder.getFrameSize(); // Misc initialsation comment = "Encoded with " + SpeexEncoder.VERSION; first = true; } /** * Sets the Stream Serial Number. * Must not be changed mid stream. * @param serialNumber */ public void setSerialNumber(final int serialNumber) { if (first) { this.streamSerialNumber = serialNumber; } } /** * Sets the number of Audio Frames that are to be put in every Speex Packet. * An Audio Frame contains 160 samples for narrowband, 320 samples for * wideband and 640 samples for ultra-wideband. * @param framesPerPacket * @see #DEFAULT_FRAMES_PER_PACKET */ public void setFramesPerPacket(int framesPerPacket) { if (framesPerPacket <= 0) { framesPerPacket = DEFAULT_FRAMES_PER_PACKET; } this.framesPerPacket = framesPerPacket; } /** * Sets the number of Speex Packets that are to be put in every Ogg Page. * This value must be less than 256 as the value is encoded in 1 byte in the * Ogg Header (just before the array of packet sizes) * @param packetsPerOggPage * @see #DEFAULT_PACKETS_PER_OGG_PAGE */ public void setPacketsPerOggPage(int packetsPerOggPage) { if (packetsPerOggPage <= 0) { packetsPerOggPage = DEFAULT_PACKETS_PER_OGG_PAGE; } if (packetsPerOggPage > 255) { packetsPerOggPage = 255; } this.packetsPerOggPage = packetsPerOggPage; } /** * Sets the comment for the Ogg Comment Header. * @param comment * @param appendVersion */ public void setComment(final String comment, final boolean appendVersion) { this.comment = comment; if (appendVersion) { this.comment += SpeexEncoder.VERSION; } } /** * Sets the Speex encoder Quality. * @param quality */ public void setQuality(final int quality) { encoder.getEncoder().setQuality(quality); if (encoder.getEncoder().getVbr()) { encoder.getEncoder().setVbrQuality((float)quality); } } /** * Sets whether of not the encoder is to use VBR. * @param vbr */ public void setVbr(final boolean vbr) { encoder.getEncoder().setVbr(vbr); } /** * Returns the Encoder. * @return the Encoder. */ public Encoder getEncoder() { return encoder.getEncoder(); } /** * Fills the buffer with more data, taking into account * shuffling and other tricks for dealing with marks. * Assumes that it is being called by a synchronized method. * This method also assumes that all data has already been read in, * hence pos > count. * @exception IOException */ protected void fill() throws IOException { makeSpace(); if (first) { writeHeaderFrames(); first = false; } while (true) { if ((prebuf.length - prepos) < framesPerPacket*frameSize*packetsPerOggPage) { // grow prebuf int nsz = prepos + framesPerPacket*frameSize*packetsPerOggPage; byte[] nbuf = new byte[nsz]; System.arraycopy(prebuf, 0, nbuf, 0, precount); prebuf = nbuf; } int read = in.read(prebuf, precount, prebuf.length - precount); if (read < 0) { // inputstream has ended if ((precount-prepos) % 2 != 0) { // we don't have a complete last PCM sample throw new StreamCorruptedException("Incompleted last PCM sample when stream ended"); } while (prepos < precount) { // still data to encode if ((precount - prepos) < framesPerPacket*frameSize) { // fill end of frame with zeros for (;precount < (prepos+framesPerPacket*frameSize); precount++) { prebuf[precount] = 0; } } if (packetCount == 0) { writeOggPageHeader(packetsPerOggPage, 0); } for (int i=0; i= packetsPerOggPage) { writeOggPageChecksum(); return; } } if (packetCount > 0) { // we have less than the normal number of packets in this page. buf[count+5] = (byte)(0xff & 4); // set page header type to end of stream buf[count+26] = (byte)(0xff & packetCount); System.arraycopy(buf, count+27+packetsPerOggPage, buf, count+27+packetCount, oggCount-(count+27+packetsPerOggPage)); oggCount -= packetsPerOggPage-packetCount; writeOggPageChecksum(); } return; } else if (read > 0) { precount += read; if ((precount - prepos) >= framesPerPacket*frameSize*packetsPerOggPage) { // enough data to encode frame while ((precount - prepos) >= framesPerPacket*frameSize*packetsPerOggPage) { // lets encode all we can if (packetCount == 0) { writeOggPageHeader(packetsPerOggPage, 0); } while (packetCount < packetsPerOggPage) { for (int i=0; i= packetsPerOggPage) { writeOggPageChecksum(); } } System.arraycopy(prebuf, prepos, prebuf, 0, precount-prepos); precount -= prepos; prepos = 0; // we have encoded some data (all that we could), // so we can leave now, otherwise we return to a potentially // blocking read of the underlying inputstream. return; } } else { // read == 0 // read 0 bytes from underlying stream yet it is not finished. if (precount >= prebuf.length) { // no more room in buffer if (prepos > 0) { // free some space System.arraycopy(prebuf, prepos, prebuf, 0, precount-prepos); precount -= prepos; prepos = 0; } else { // we could grow the pre-buffer but that risks in turn growing the // buffer which could lead sooner or later to an // OutOfMemoryException. return; } } else { return; } } } } /** * Returns the number of bytes that can be read from this inputstream without * blocking. *

* The available method of FilteredAudioInputStream * returns the sum of the the number of bytes remaining to be read in the * buffer (count - pos) and the result of calling the * available method of the underlying inputstream. * * @return the number of bytes that can be read from this inputstream without * blocking. * @exception IOException if an I/O error occurs. * @see #in */ public synchronized int available() throws IOException { int avail = super.available(); int unencoded = precount - prepos + in.available(); if (encoder.getEncoder().getVbr()) { switch (mode) { case 0: // Narrowband // ogg header size = 27 + packetsPerOggPage // count 1 byte (min 5 bits) for each block available return avail + (27 + 2 * packetsPerOggPage) * (unencoded / (packetsPerOggPage*framesPerPacket*320)); case 1: // Wideband // ogg header size = 27 + packetsPerOggPage // count 2 byte (min 9 bits) for each block available return avail + (27 + 2 * packetsPerOggPage) * (unencoded / (packetsPerOggPage*framesPerPacket*640)); case 2: // Ultra wideband // ogg header size = 27 + packetsPerOggPage // count 2 byte (min 13 bits) for each block available return avail + (27 + 3 * packetsPerOggPage) * (unencoded / (packetsPerOggPage*framesPerPacket*1280)); default: return avail; } } else { // Calculate size of a packet of Speex data. int spxpacketsize = encoder.getEncoder().getEncodedFrameSize(); if (channels > 1) { spxpacketsize += 17; // 1+4(14=inband)+4(9=stereo)+8(stereo data) } spxpacketsize *= framesPerPacket; spxpacketsize = (spxpacketsize + 7) >> 3; // convert bits to bytes // Calculate size of an Ogg packet containing X Speex packets. // Ogg Packet = Ogg header + size of each packet + Ogg packets int oggpacketsize = 27 + packetsPerOggPage * (spxpacketsize + 1); int pcmframesize; // size of PCM data necessary to encode 1 Speex packet. switch (mode) { case 0: // Narrowband // 1 frame = 20ms = 160ech * channels = 320bytes * channels pcmframesize = framesPerPacket * 320 * encoder.getChannels(); avail += oggpacketsize * (unencoded / (packetsPerOggPage * pcmframesize)); return avail; case 1: // Wideband // 1 frame = 20ms = 320ech * channels = 640bytes * channels pcmframesize = framesPerPacket * 640 * encoder.getChannels(); avail += oggpacketsize * (unencoded / (packetsPerOggPage * pcmframesize)); return avail; case 2: // Ultra wideband // 1 frame = 20ms = 640ech * channels = 1280bytes * channels pcmframesize = framesPerPacket * 1280 * encoder.getChannels(); avail += oggpacketsize * (unencoded / (packetsPerOggPage * pcmframesize)); return avail; default: return avail; } } } //--------------------------------------------------------------------------- // Ogg Specific Code //--------------------------------------------------------------------------- /** * Write an OGG page header. * @param packets - the number of packets in the Ogg Page (must be between 1 and 255) * @param headertype - 2=bos: beginning of sream, 4=eos: end of sream */ private void writeOggPageHeader(final int packets, final int headertype) { while ((buf.length - count) < (27 + packets)) { // grow buffer int nsz = buf.length * 2; byte[] nbuf = new byte[nsz]; System.arraycopy(buf, 0, nbuf, 0, count); buf = nbuf; } AudioFileWriter.writeOggPageHeader(buf, count, headertype, granulepos, streamSerialNumber, pageCount++, packets, new byte[packets]); oggCount = count + 27 + packets; } /** * Calculate and write the OGG page checksum. This now closes the Ogg page. */ private void writeOggPageChecksum() { // write the granulpos granulepos += framesPerPacket * frameSize * packetCount / 2; AudioFileWriter.writeLong(buf, count+6, granulepos); // write the checksum int chksum = OggCrc.checksum(0, buf, count, oggCount-count); AudioFileWriter.writeInt(buf, count+22, chksum); // reset variables for a new page. count = oggCount; packetCount = 0; } /** * Write the OGG Speex header then the comment header. */ private void writeHeaderFrames() { int length = comment.length(); if (length > 247) { comment = comment.substring(0, 247); length = 247; } while ((buf.length - count) < length + 144) { // grow buffer (108 = 28 + 80 = size of Ogg Header Frame) // (28 + length + 8 = size of Comment Frame) int nsz = buf.length * 2; byte[] nbuf = new byte[nsz]; System.arraycopy(buf, 0, nbuf, 0, count); buf = nbuf; } // writes the OGG header page AudioFileWriter.writeOggPageHeader(buf, count, 2, granulepos, streamSerialNumber, pageCount++, 1, new byte[] {80}); oggCount = count + 28; /* writes the Speex header */ AudioFileWriter.writeSpeexHeader(buf, oggCount, encoder.getSampleRate(), mode, encoder.getChannels(), encoder.getEncoder().getVbr(), framesPerPacket); oggCount += 80; /* Calculate Checksum */ int chksum = OggCrc.checksum(0, buf, count, oggCount-count); AudioFileWriter.writeInt(buf, count+22, chksum); count = oggCount; // writes the OGG header page AudioFileWriter.writeOggPageHeader(buf, count, 0, granulepos, streamSerialNumber, pageCount++, 1, new byte[] {(byte)(length+8)}); oggCount = count + 28; /* writes the OGG comment page */ AudioFileWriter.writeSpeexComment(buf, oggCount, comment); oggCount += length+8; /* Calculate Checksum */ chksum = OggCrc.checksum(0, buf, count, oggCount-count); AudioFileWriter.writeInt(buf, count+22, chksum); count = oggCount; // reset variables for a new page. packetCount = 0; } } jspeex/src/java/org/xiph/speex/spi/Speex2PcmAudioInputStream.java0000644000175000017500000005167610245641604025350 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Speex2PcmAudioInputStream.java * * * * Author: Marc GIMPEL * * * * Date: 12th July 2003 * * * ******************************************************************************/ /* $Id: Speex2PcmAudioInputStream.java,v 1.5 2005/05/27 15:57:55 mgimpel Exp $ */ package org.xiph.speex.spi; import java.io.InputStream; import java.io.IOException; import java.io.StreamCorruptedException; import javax.sound.sampled.AudioFormat; import org.xiph.speex.Bits; import org.xiph.speex.Decoder; import org.xiph.speex.NbDecoder; import org.xiph.speex.SbDecoder; /** * Converts an Ogg Speex bitstream into a PCM 16bits/sample audio stream. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.5 $ */ public class Speex2PcmAudioInputStream extends FilteredAudioInputStream { // InputStream variables /** Flag to indicate if this Stream has been initialised. */ private boolean initialised; // audio parameters /** The sample rate of the audio, in samples per seconds (Hz). */ private int sampleRate; /** The number of audio channels (1=mono, 2=stereo). */ private int channelCount; // Speex variables /** Array containing the decoded audio samples. */ private float[] decodedData; /** Array containing the decoded audio samples converted into bytes. */ private byte[] outputData; /** Speex bit packing and unpacking class. */ private Bits bits; /** Speex Decoder. */ private Decoder decoder; /** The frame size, in samples. */ private int frameSize; /** The number of Speex frames that will be put in each Ogg packet. */ private int framesPerPacket; // Ogg variables /** A unique serial number that identifies the Ogg stream. */ private int streamSerialNumber; /** The number of Ogg packets that are in each Ogg page. */ private int packetsPerOggPage; /** The number of Ogg packets that have been decoded in the current page. */ private int packetCount; /** Array containing the sizes of Ogg packets in the current page.*/ private byte[] packetSizes; /** * Constructor * @param in the underlying input stream. * @param format the target format of this stream's audio data. * @param length the length in sample frames of the data in this stream. */ public Speex2PcmAudioInputStream(final InputStream in, final AudioFormat format, final long length) { this(in, format, length, DEFAULT_BUFFER_SIZE); } /** * Constructor * @param in the underlying input stream. * @param format the target format of this stream's audio data. * @param length the length in sample frames of the data in this stream. * @param size the buffer size. * @exception IllegalArgumentException if size <= 0. */ public Speex2PcmAudioInputStream(final InputStream in, final AudioFormat format, final long length, final int size) { super(in, format, length, size); bits = new Bits(); packetSizes = new byte[256]; initialised = false; } /** * Initialises the Ogg Speex to PCM InputStream. * Read the Ogg Speex header and extract the speex decoder parameters to * initialise the decoder. Then read the Comment header. * Ogg Header description: *

   *  0 -  3: capture_pattern
   *       4: stream_structure_version
   *       5: header_type_flag (2=bos: beginning of sream)
   *  6 - 13: absolute granule position
   * 14 - 17: stream serial number
   * 18 - 21: page sequence no
   * 22 - 25: page checksum
   *      26: page_segments
   * 27 -...: segment_table
   * 
* Speex Header description *
   *  0 -  7: speex_string
   *  8 - 27: speex_version
   * 28 - 31: speex_version_id
   * 32 - 35: header_size
   * 36 - 39: rate
   * 40 - 43: mode (0=narrowband, 1=wb, 2=uwb)
   * 44 - 47: mode_bitstream_version
   * 48 - 51: nb_channels
   * 52 - 55: bitrate
   * 56 - 59: frame_size
   * 60 - 63: vbr
   * 64 - 67: frames_per_packet
   * 68 - 71: extra_headers
   * 72 - 75: reserved1
   * 76 - 79: reserved2
   * 
* @param blocking whether the method should block until initialisation is * successfully completed or not. * @exception IOException */ protected void initialise(final boolean blocking) throws IOException { while (!initialised) { int readsize = prebuf.length - precount - 1; int avail = in.available(); if (!blocking && avail <= 0) { return; } readsize = (avail > 0 ? Math.min(avail, readsize) : readsize); int n = in.read(prebuf, precount, readsize); if (n < 0) { throw new StreamCorruptedException("Incomplete Ogg Headers"); } if (n == 0) { // This should never happen. //assert false : "Read 0 bytes from stream - possible infinate loop"; } precount += n; if (decoder==null && precount>=108) { // we can process the speex header if (!(new String(prebuf, 0, 4).equals("OggS"))) { throw new StreamCorruptedException("The given stream does not appear to be Ogg."); } streamSerialNumber = readInt(prebuf, 14); if (!(new String(prebuf, 28, 8).equals("Speex "))) { throw new StreamCorruptedException("The given stream does not appear to be Ogg Speex."); } sampleRate = readInt(prebuf, 28+36); channelCount = readInt(prebuf, 28+48); framesPerPacket = readInt(prebuf, 28+64); int mode = readInt(prebuf, 28+40); switch (mode) { case 0: decoder = new NbDecoder(); ((NbDecoder)decoder).nbinit(); break; case 1: decoder = new SbDecoder(); ((SbDecoder)decoder).wbinit(); break; case 2: decoder = new SbDecoder(); ((SbDecoder)decoder).uwbinit(); break; default: } /* initialize the speex decoder */ decoder.setPerceptualEnhancement(true); /* set decoder format and properties */ frameSize = decoder.getFrameSize(); decodedData = new float[frameSize*channelCount]; outputData = new byte[2*frameSize*channelCount*framesPerPacket]; bits.init(); } if (decoder!=null && precount>=108+27) { // we can process the comment (skip them) packetsPerOggPage = 0xff & prebuf[108+26]; if (precount>=108+27+packetsPerOggPage) { int size = 0; for (int i=0; i=108+27+packetsPerOggPage+size) { // we have read the complete comment page prepos = 108+27+packetsPerOggPage+size; packetsPerOggPage = 0; packetCount = 255; initialised = true; } } } } } /** * Fills the buffer with more data, taking into account shuffling and other * tricks for dealing with marks. * Assumes that it is being called by a synchronized method. * This method also assumes that all data has already been read in, hence * pos > count. * @exception IOException */ protected void fill() throws IOException { makeSpace(); while (!initialised) { initialise(true); } while (true) { int read = in.read(prebuf, precount, prebuf.length - precount); if (read < 0) { // inputstream has ended while (prepos < precount) { // still data to decode if (packetCount >= packetsPerOggPage) { // read new Ogg Page header readOggPageHeader(); } if (packetCount < packetsPerOggPage) { // Ogg Page might be empty (0 packets) int n = packetSizes[packetCount++]; if ((precount-prepos) < n) { // we don't have enough data for a complete speex frame throw new StreamCorruptedException("Incompleted last Speex packet"); } // do last stuff here decode(prebuf, prepos, n); prepos += n; while ((buf.length - count) < outputData.length) { // grow buffer int nsz = buf.length * 2; byte[] nbuf = new byte[nsz]; System.arraycopy(buf, 0, nbuf, 0, count); buf = nbuf; } System.arraycopy(outputData, 0, buf, count, outputData.length); count += outputData.length; } } return; } // if read=0 but the prebuffer contains data, it is decoded and returned. // if read=0 but the prebuffer is almost empty, it loops back to read. else if (read >= 0) { precount += read; // do stuff here if (packetCount >= packetsPerOggPage) { // read new Ogg Page header readOggPageHeader(); } if (packetCount < packetsPerOggPage) { // read the next packet if ((precount-prepos) >= packetSizes[packetCount]) { // we have enough data, lets start decoding while (((precount-prepos) >= packetSizes[packetCount]) && (packetCount < packetsPerOggPage)) { // lets decode all we can int n = packetSizes[packetCount++]; decode(prebuf, prepos, n); prepos += n; while ((buf.length - count) < outputData.length) { // grow buffer int nsz = buf.length * 2; byte[] nbuf = new byte[nsz]; System.arraycopy(buf, 0, nbuf, 0, count); buf = nbuf; } System.arraycopy(outputData, 0, buf, count, outputData.length); count += outputData.length; if (packetCount >= packetsPerOggPage) { // read new Ogg Page header readOggPageHeader(); } } System.arraycopy(prebuf, prepos, prebuf, 0, precount-prepos); precount -= prepos; prepos = 0; return; // we have decoded some data (all that we could), so we can leave now, otherwise we return to a potentially blocking read of the underlying inputstream. } } } } } /** * This is where the actual decoding takes place. * @param data the array of data to decode. * @param offset the offset from which to start reading the data. * @param len the length of data to read from the array. * @throws StreamCorruptedException If the input stream not valid Ogg Speex * data. */ protected void decode(final byte[] data, final int offset, final int len) throws StreamCorruptedException { int i; short val; int outputSize = 0; /* read packet bytes into bitstream */ bits.read_from(data, offset, len); for (int frame=0; frame 32767.0f) decodedData[i] = 32767.0f; else if (decodedData[i] < -32768.0f) decodedData[i] = -32768.0f; } /* convert to short and save to buffer */ for (i=0; i0) ? (short)(decodedData[i]+.5) : (short)(decodedData[i]-.5); outputData[outputSize++] = (byte) (val & 0xff); outputData[outputSize++] = (byte) ((val >> 8) & 0xff ); } } } /** * See the general contract of the skip method of * InputStream. * * @param n the number of bytes to be skipped. * @return the actual number of bytes skipped. * @exception IOException if an I/O error occurs. */ public synchronized long skip(long n) throws IOException { while (!initialised) { initialise(true); } checkIfStillOpen(); // Sanity check if (n <= 0) { return 0; } // Skip buffered data if there is any if (pos < count) { return super.skip(n); } // Nothing in the buffers to skip else { int decodedPacketSize = 2*framesPerPacket*frameSize*channelCount; if (markpos < 0 && n >= decodedPacketSize) { // We aren't buffering and skipping more than a complete Speex packet: // Lets try to skip complete Speex packets without decoding if (packetCount >= packetsPerOggPage) { // read new Ogg Page header readOggPageHeader(); } if (packetCount < packetsPerOggPage) { // read the next packet int skipped = 0; if ((precount-prepos) < packetSizes[packetCount]) { // we don't have enough data int avail = in.available(); if (avail > 0) { int size = Math.min(prebuf.length - precount, avail); int read = in.read(prebuf, precount, size); if (read < 0) { // inputstream has ended throw new IOException("End of stream but there are still supposed to be packets to decode"); } precount += read; } } while (((precount-prepos) >= packetSizes[packetCount]) && (packetCount < packetsPerOggPage) && (n >= decodedPacketSize)) { // lets skip all we can prepos += packetSizes[packetCount++]; skipped += decodedPacketSize; n -= decodedPacketSize; if (packetCount >= packetsPerOggPage) { // read new Ogg Page header readOggPageHeader(); } } System.arraycopy(prebuf, prepos, prebuf, 0, precount-prepos); precount -= prepos; prepos = 0; return skipped; // we have skipped some data (all that we could), so we can leave now, otherwise we return to a potentially blocking read of the underlying inputstream. } } // We are buffering, or couldn't skip a complete Speex packet: // Read (decode) into buffers and skip (this is potentially blocking) return super.skip(n); } } /** * Returns the number of bytes that can be read from this inputstream without * blocking. *

* The available method of FilteredAudioInputStream * returns the sum of the the number of bytes remaining to be read in the * buffer (count - pos). * The result of calling the available method of the underlying * inputstream is not used, as this data will have to be filtered, and thus * may not be the same size after processing (although subclasses that do the * filtering should override this method and use the amount of data available * in the underlying inputstream). * * @return the number of bytes that can be read from this inputstream without * blocking. * @exception IOException if an I/O error occurs. * @see #in */ public synchronized int available() throws IOException { if (!initialised) { initialise(false); if (!initialised) { return 0; } } int avail = super.available(); if (packetCount >= packetsPerOggPage) { // read new Ogg Page header readOggPageHeader(); } // See how much we could decode from the underlying stream. if (packetCount < packetsPerOggPage) { int undecoded = precount - prepos + in.available(); int size = packetSizes[packetCount]; int tempCount = 0; while (size < undecoded && packetCount + tempCount < packetsPerOggPage) { undecoded -= size; avail += 2 * frameSize * framesPerPacket; tempCount++; size = packetSizes[packetCount + tempCount]; } } return avail; } //--------------------------------------------------------------------------- // Ogg Specific code //--------------------------------------------------------------------------- /** * Read the Ogg Page header and extract the speex packet sizes. * Note: the checksum is ignores. * Note: the method should no block on a read because it will not read more * then is available */ private void readOggPageHeader() throws IOException { int packets = 0; if (precount-prepos<27) { int avail = in.available(); if (avail > 0) { int size = Math.min(prebuf.length - precount, avail); int read = in.read(prebuf, precount, size); if (read < 0) { // inputstream has ended throw new IOException("End of stream but available was positive"); } precount += read; } } if (precount-prepos>=27) { // can read beginning of Page header if (!(new String(prebuf, prepos, 4).equals("OggS"))) { throw new StreamCorruptedException("Lost Ogg Sync"); } if (streamSerialNumber != readInt(prebuf, prepos+14)) { throw new StreamCorruptedException("Ogg Stream Serial Number mismatch"); } packets = 0xff & prebuf[prepos+26]; } if (precount-prepos<27+packets) { int avail = in.available(); if (avail > 0) { int size = Math.min(prebuf.length - precount, avail); int read = in.read(prebuf, precount, size); if (read < 0) { // inputstream has ended throw new IOException("End of stream but available was positive"); } precount += read; } } if (precount-prepos>=27+packets) { // can read entire Page header System.arraycopy(prebuf, prepos+27, packetSizes, 0, packets); packetCount = 0; prepos += 27+packets; packetsPerOggPage = packets; } } /** * Converts Little Endian (Windows) bytes to an int (Java uses Big Endian). * @param data the data to read. * @param offset the offset from which to start reading. * @return the integer value of the reassembled bytes. */ private static int readInt(final byte[] data, final int offset) { return (data[offset] & 0xff) | ((data[offset+1] & 0xff) << 8) | ((data[offset+2] & 0xff) << 16) | (data[offset+3] << 24); // no & 0xff at the end to keep the sign } } jspeex/src/java/org/xiph/speex/spi/SpeexAudioFileReader.java0000644000175000017500000004121210135761046024337 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: SpeexAudioFileReader.java * * * * Author: Marc GIMPEL * * * * Date: 12th July 2003 * * * ******************************************************************************/ /* $Id: SpeexAudioFileReader.java,v 1.2 2004/10/21 16:21:58 mgimpel Exp $ */ package org.xiph.speex.spi; import java.io.File; import java.io.InputStream; import java.io.IOException; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.SequenceInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.net.URL; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.UnsupportedAudioFileException; import javax.sound.sampled.spi.AudioFileReader; import org.xiph.speex.OggCrc; /** * Provider for Speex audio file reading services. * This implementation can parse the format information from Speex audio file, * and can produce audio input streams from files of this type. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class SpeexAudioFileReader extends AudioFileReader { /** */ public static final int OGG_HEADERSIZE = 27; /** The size of the Speex header. */ public static final int SPEEX_HEADERSIZE = 80; /** */ public static final int SEGOFFSET = 26; /** The String that identifies the beginning of an Ogg packet. */ public static final String OGGID = "OggS"; /** The String that identifies the beginning of the Speex header. */ public static final String SPEEXID = "Speex "; /** * Obtains the audio file format of the File provided. * The File must point to valid audio file data. * @param file the File from which file format information should be * extracted. * @return an AudioFileFormat object describing the audio file format. * @exception UnsupportedAudioFileException if the File does not point to * a valid audio file data recognized by the system. * @exception IOException if an I/O exception occurs. */ public AudioFileFormat getAudioFileFormat(final File file) throws UnsupportedAudioFileException, IOException { InputStream inputStream = null; try { inputStream = new FileInputStream(file); return getAudioFileFormat(inputStream, (int) file.length()); } finally { inputStream.close(); } } /** * Obtains an audio input stream from the URL provided. * The URL must point to valid audio file data. * @param url the URL for which the AudioInputStream should be constructed. * @return an AudioInputStream object based on the audio file data pointed to * by the URL. * @exception UnsupportedAudioFileException if the File does not point to * a valid audio file data recognized by the system. * @exception IOException if an I/O exception occurs. */ public AudioFileFormat getAudioFileFormat(final URL url) throws UnsupportedAudioFileException, IOException { InputStream inputStream = url.openStream(); try { return getAudioFileFormat(inputStream); } finally { inputStream.close(); } } /** * Obtains an audio input stream from the input stream provided. * @param stream the input stream from which the AudioInputStream should be * constructed. * @return an AudioInputStream object based on the audio file data contained * in the input stream. * @exception UnsupportedAudioFileException if the File does not point to * a valid audio file data recognized by the system. * @exception IOException if an I/O exception occurs. */ public AudioFileFormat getAudioFileFormat(final InputStream stream) throws UnsupportedAudioFileException, IOException { return getAudioFileFormat(stream, AudioSystem.NOT_SPECIFIED); } /** * Return the AudioFileFormat from the given InputStream. * @param stream the input stream from which the AudioInputStream should be * constructed. * @param medialength * @return an AudioInputStream object based on the audio file data contained * in the input stream. * @exception UnsupportedAudioFileException if the File does not point to * a valid audio file data recognized by the system. * @exception IOException if an I/O exception occurs. */ protected AudioFileFormat getAudioFileFormat(final InputStream stream, final int medialength) throws UnsupportedAudioFileException, IOException { return getAudioFileFormat(stream, null, medialength); } /** * Return the AudioFileFormat from the given InputStream. Implementation. * @param bitStream * @param baos * @param mediaLength * @return an AudioInputStream object based on the audio file data contained * in the input stream. * @exception UnsupportedAudioFileException if the File does not point to * a valid audio file data recognized by the system. * @exception IOException if an I/O exception occurs. */ protected AudioFileFormat getAudioFileFormat(final InputStream bitStream, ByteArrayOutputStream baos, final int mediaLength) throws UnsupportedAudioFileException, IOException { AudioFormat format; try { // If we can't read the format of this stream, we must restore stream to // beginning so other providers can attempt to read the stream. if (bitStream.markSupported()) { // maximum number of bytes to determine the stream encoding: // Size of 1st Ogg Packet (Speex header) = OGG_HEADERSIZE + SPEEX_HEADERSIZE + 1 // Size of 2nd Ogg Packet (Comment) = OGG_HEADERSIZE + comment_size + 1 // Size of 3rd Ogg Header (First data) = OGG_HEADERSIZE + number_of_frames // where number_of_frames < 256 and comment_size < 256 (if within 1 frame) bitStream.mark(3*OGG_HEADERSIZE + SPEEX_HEADERSIZE + 256 + 256 + 2); } int mode = -1; int sampleRate = 0; int channels = 0; int frameSize = AudioSystem.NOT_SPECIFIED; float frameRate = AudioSystem.NOT_SPECIFIED; byte[] header = new byte[128]; int segments = 0; int bodybytes = 0; DataInputStream dis = new DataInputStream(bitStream); if (baos == null) baos = new ByteArrayOutputStream(128); int origchksum; int chksum; // read the OGG header dis.readFully(header, 0, OGG_HEADERSIZE); baos.write(header, 0, OGG_HEADERSIZE); origchksum = readInt(header, 22); header[22] = 0; header[23] = 0; header[24] = 0; header[25] = 0; chksum=OggCrc.checksum(0, header, 0, OGG_HEADERSIZE); // make sure its a OGG header if (!OGGID.equals(new String(header, 0, 4))) { throw new UnsupportedAudioFileException("missing ogg id!"); } // how many segments are there? segments = header[SEGOFFSET] & 0xFF; if (segments > 1) { throw new UnsupportedAudioFileException("Corrupt Speex Header: more than 1 segments"); } dis.readFully(header, OGG_HEADERSIZE, segments); baos.write(header, OGG_HEADERSIZE, segments); chksum=OggCrc.checksum(chksum, header, OGG_HEADERSIZE, segments); // get the number of bytes in the segment bodybytes = header[OGG_HEADERSIZE] & 0xFF; if (bodybytes!=SPEEX_HEADERSIZE) { throw new UnsupportedAudioFileException("Corrupt Speex Header: size=" + bodybytes); } // read the Speex header dis.readFully(header, OGG_HEADERSIZE+1, bodybytes); baos.write(header, OGG_HEADERSIZE+1, bodybytes); chksum=OggCrc.checksum(chksum, header, OGG_HEADERSIZE+1, bodybytes); // make sure its a Speex header if (!SPEEXID.equals(new String(header, OGG_HEADERSIZE+1, 8))) { throw new UnsupportedAudioFileException("Corrupt Speex Header: missing Speex ID"); } mode = readInt(header, OGG_HEADERSIZE+1+40); sampleRate = readInt(header, OGG_HEADERSIZE+1+36); channels = readInt(header, OGG_HEADERSIZE+1+48); int nframes = readInt(header, OGG_HEADERSIZE+1+64); boolean vbr = readInt(header, OGG_HEADERSIZE+1+60) == 1; // Checksum if (chksum != origchksum) throw new IOException("Ogg CheckSums do not match"); // Calculate frameSize if (!vbr) { // Frames size is a constant so: // Read Comment Packet the Ogg Header of 1st data packet; // the array table_segment repeats the frame size over and over. } // Calculate frameRate if (mode >= 0 && mode <= 2 && nframes > 0) { frameRate = ((float) sampleRate) / ((mode == 0 ? 160f : (mode == 1 ? 320f : 640f)) * ((float) nframes)); } format = new AudioFormat(SpeexEncoding.SPEEX, (float)sampleRate, AudioSystem.NOT_SPECIFIED, channels, frameSize, frameRate, false); } catch(UnsupportedAudioFileException e) { // reset the stream for other providers if (bitStream.markSupported()) { bitStream.reset(); } // just rethrow this exception throw e; } catch (IOException ioe) { // reset the stream for other providers if (bitStream.markSupported()) { bitStream.reset(); } throw new UnsupportedAudioFileException(ioe.getMessage()); } return new AudioFileFormat(SpeexFileFormatType.SPEEX, format, AudioSystem.NOT_SPECIFIED); } /** * Obtains an audio input stream from the File provided. * The File must point to valid audio file data. * @param file the File for which the AudioInputStream should be constructed. * @return an AudioInputStream object based on the audio file data pointed to * by the File. * @exception UnsupportedAudioFileException if the File does not point to * a valid audio file data recognized by the system. * @exception IOException if an I/O exception occurs. */ public AudioInputStream getAudioInputStream(final File file) throws UnsupportedAudioFileException, IOException { InputStream inputStream = new FileInputStream(file); try { return getAudioInputStream(inputStream, (int) file.length()); } catch (UnsupportedAudioFileException e) { inputStream.close(); throw e; } catch (IOException e) { inputStream.close(); throw e; } } /** * Obtains an audio input stream from the URL provided. * The URL must point to valid audio file data. * @param url the URL for which the AudioInputStream should be constructed. * @return an AudioInputStream object based on the audio file data pointed to * by the URL. * @exception UnsupportedAudioFileException if the File does not point to * a valid audio file data recognized by the system. * @exception IOException if an I/O exception occurs. */ public AudioInputStream getAudioInputStream(final URL url) throws UnsupportedAudioFileException, IOException { InputStream inputStream = url.openStream(); try { return getAudioInputStream(inputStream); } catch (UnsupportedAudioFileException e) { inputStream.close(); throw e; } catch (IOException e) { inputStream.close(); throw e; } } /** * Obtains an audio input stream from the input stream provided. * The stream must point to valid audio file data. * @param stream the input stream from which the AudioInputStream should be * constructed. * @return an AudioInputStream object based on the audio file data contained * in the input stream. * @exception UnsupportedAudioFileException if the File does not point to * a valid audio file data recognized by the system. * @exception IOException if an I/O exception occurs. */ public AudioInputStream getAudioInputStream(final InputStream stream) throws UnsupportedAudioFileException, IOException { return getAudioInputStream(stream, AudioSystem.NOT_SPECIFIED); } /** * Obtains an audio input stream from the input stream provided. * The stream must point to valid audio file data. * @param inputStream the input stream from which the AudioInputStream should * be constructed. * @param medialength * @return an AudioInputStream object based on the audio file data contained * in the input stream. * @exception UnsupportedAudioFileException if the File does not point to * a valid audio file data recognized by the system. * @exception IOException if an I/O exception occurs. */ protected AudioInputStream getAudioInputStream(final InputStream inputStream, final int medialength) throws UnsupportedAudioFileException, IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(128); AudioFileFormat audioFileFormat = getAudioFileFormat(inputStream, baos, medialength); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); SequenceInputStream sequenceInputStream = new SequenceInputStream(bais, inputStream); return new AudioInputStream(sequenceInputStream, audioFileFormat.getFormat(), audioFileFormat.getFrameLength()); } /** * Converts Little Endian (Windows) bytes to an int (Java uses Big Endian). * @param data the data to read. * @param offset the offset from which to start reading. * @return the integer value of the reassembled bytes. */ private static int readInt(final byte[] data, final int offset) { return (data[offset] & 0xff) | ((data[offset+1] & 0xff) << 8) | ((data[offset+2] & 0xff) << 16) | (data[offset+3] << 24); // no & 0xff at the end to keep the sign } } jspeex/src/java/org/xiph/speex/spi/SpeexAudioFileWriter.java0000644000175000017500000002000310203125356024376 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: SpeexAudioFileWriter.java * * * * Author: Marc GIMPEL * * * * Date: 12th July 2003 * * * ******************************************************************************/ /* $Id: SpeexAudioFileWriter.java,v 1.3 2005/02/11 12:54:05 mgimpel Exp $ */ package org.xiph.speex.spi; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.FileOutputStream; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.spi.AudioFileWriter; /** * Provider for Speex audio file writing services. * This implementation can write Speex audio files from an audio stream. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.3 $ */ public class SpeexAudioFileWriter extends AudioFileWriter { /** */ public static final AudioFileFormat.Type[] NO_FORMAT = {}; /** */ public static final AudioFileFormat.Type[] SPEEX_FORMAT = {SpeexFileFormatType.SPEEX}; /** * Obtains the file types for which file writing support is provided by this audio file writer. * @return array of file types. If no file types are supported, an array of length 0 is returned. */ public AudioFileFormat.Type[] getAudioFileTypes() { return SPEEX_FORMAT; } /** * Obtains the file types that this audio file writer can write from the * audio input stream specified. * @param stream - the audio input stream for which audio file type support * is queried. * @return array of file types. If no file types are supported, an array of * length 0 is returned. */ public AudioFileFormat.Type[] getAudioFileTypes(final AudioInputStream stream) { if (stream.getFormat().getEncoding() instanceof SpeexEncoding) { return SPEEX_FORMAT; } else { return NO_FORMAT; } } /** * Writes a stream of bytes representing an audio file of the file type * indicated to the output stream provided. Some file types require that the * length be written into the file header, and cannot be written from start * to finish unless the length is known in advance. * An attempt to write such a file type will fail with an IOException if the * length in the audio file format is AudioSystem.NOT_SPECIFIED. * @param stream - the audio input stream containing audio data to be written * to the output stream. * @param fileType - file type to be written to the output stream. * @param out - stream to which the file data should be written. * @return the number of bytes written to the output stream. * @exception IOException - if an I/O exception occurs. * @exception IllegalArgumentException - if the file type is not supported by the system. * @see #isFileTypeSupported(AudioFileFormat.Type, AudioInputStream) * @see #getAudioFileTypes() */ public int write(final AudioInputStream stream, final AudioFileFormat.Type fileType, final OutputStream out) throws IOException { AudioFileFormat.Type[] formats = getAudioFileTypes(stream); if (formats != null && formats.length > 0) { return write(stream, out); } else { throw new IllegalArgumentException("cannot write given file type"); } } /** * Writes a stream of bytes representing an audio file of the file format * indicated to the external file provided. * @param stream - the audio input stream containing audio data to be written * to the file. * @param fileType - file type to be written to the file. * @param out - external file to which the file data should be written. * @return the number of bytes written to the file. * @exception IOException - if an I/O exception occurs. * @exception IllegalArgumentException - if the file format is not supported by the system * @see #isFileTypeSupported(javax.sound.sampled.AudioFileFormat.Type) * @see #getAudioFileTypes() */ public int write(final AudioInputStream stream, final AudioFileFormat.Type fileType, final File out) throws IOException { AudioFileFormat.Type[] formats = getAudioFileTypes(stream); if (formats != null && formats.length > 0) { FileOutputStream fos = new FileOutputStream(out); return write(stream, fos); } else { throw new IllegalArgumentException("cannot write given file type"); } } /** * Writes a stream of bytes representing an audio file of the file type * indicated to the output stream provided. * @param stream - the audio input stream containing audio data to be written * to the output stream. * @param out - stream to which the file data should be written. * @return the number of bytes written to the output stream. * @exception IOException - if an I/O exception occurs. */ private int write(final AudioInputStream stream, final OutputStream out) throws IOException { byte[] data = new byte[2048]; int read = 0; int temp; while ((temp = stream.read(data, 0, 2048)) > 0) { out.write(data, 0, temp); read += temp; } /* According to jsresources.org, the write() method is supposed to close the File or FileOutputStream on completion. Without it, people passing in a File parameter are not able to close the file on their own, and hence can't delete the audio file (especially on FAT32 systems), since it's still technically open. */ out.flush(); out.close(); return read; } } jspeex/src/java/org/xiph/speex/spi/SpeexEncoding.java0000644000175000017500000002014410135761046023102 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: SpeexEncoding.java * * * * Author: Marc GIMPEL * * * * Date: 12th July 2003 * * * ******************************************************************************/ /* $Id: SpeexEncoding.java,v 1.2 2004/10/21 16:21:58 mgimpel Exp $ */ package org.xiph.speex.spi; import javax.sound.sampled.AudioFormat; /** * Encodings used by the Speex audio decoder. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class SpeexEncoding extends AudioFormat.Encoding { /** Specifies any Speex encoding. */ public static final SpeexEncoding SPEEX = new SpeexEncoding("SPEEX"); /** Specifies constant bitrate, quality 0, Speex encoding. */ public static final SpeexEncoding SPEEX_Q0 = new SpeexEncoding("SPEEX_quality_0", 0, false); /** Specifies constant bitrate, quality 1, Speex encoding. */ public static final SpeexEncoding SPEEX_Q1 = new SpeexEncoding("SPEEX_quality_1", 1, false); /** Specifies constant bitrate, quality 2, Speex encoding. */ public static final SpeexEncoding SPEEX_Q2 = new SpeexEncoding("SPEEX_quality_2", 2, false); /** Specifies constant bitrate, quality 3, Speex encoding. */ public static final SpeexEncoding SPEEX_Q3 = new SpeexEncoding("SPEEX_quality_3", 3, false); /** Specifies constant bitrate, quality 4, Speex encoding. */ public static final SpeexEncoding SPEEX_Q4 = new SpeexEncoding("SPEEX_quality_4", 4, false); /** Specifies constant bitrate, quality 5, Speex encoding. */ public static final SpeexEncoding SPEEX_Q5 = new SpeexEncoding("SPEEX_quality_5", 5, false); /** Specifies constant bitrate, quality 6, Speex encoding. */ public static final SpeexEncoding SPEEX_Q6 = new SpeexEncoding("SPEEX_quality_6", 6, false); /** Specifies constant bitrate, quality 7, Speex encoding. */ public static final SpeexEncoding SPEEX_Q7 = new SpeexEncoding("SPEEX_quality_7", 7, false); /** Specifies constant bitrate, quality 8, Speex encoding. */ public static final SpeexEncoding SPEEX_Q8 = new SpeexEncoding("SPEEX_quality_8", 8, false); /** Specifies constant bitrate, quality 9, Speex encoding. */ public static final SpeexEncoding SPEEX_Q9 = new SpeexEncoding("SPEEX_quality_9", 9, false); /** Specifies constant bitrate, quality 10, Speex encoding. */ public static final SpeexEncoding SPEEX_Q10 = new SpeexEncoding("SPEEX_quality_10", 10, false); /** Specifies variable bitrate, quality 0, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR0 = new SpeexEncoding("SPEEX_VBR_quality_0", 0, true); /** Specifies variable bitrate, quality 1, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR1 = new SpeexEncoding("SPEEX_VBR_quality_1", 1, true); /** Specifies variable bitrate, quality 2, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR2 = new SpeexEncoding("SPEEX_VBR_quality_2", 2, true); /** Specifies variable bitrate, quality 3, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR3 = new SpeexEncoding("SPEEX_VBR_quality_3", 3, true); /** Specifies variable bitrate, quality 4, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR4 = new SpeexEncoding("SPEEX_VBR_quality_4", 4, true); /** Specifies variable bitrate, quality 5, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR5 = new SpeexEncoding("SPEEX_VBR_quality_5", 5, true); /** Specifies variable bitrate, quality 6, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR6 = new SpeexEncoding("SPEEX_VBR_quality_6", 6, true); /** Specifies variable bitrate, quality 7, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR7 = new SpeexEncoding("SPEEX_VBR_quality_7", 7, true); /** Specifies variable bitrate, quality 8, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR8 = new SpeexEncoding("SPEEX_VBR_quality_8", 8, true); /** Specifies variable bitrate, quality 9, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR9 = new SpeexEncoding("SPEEX_VBR_quality_9", 9, true); /** Specifies variable bitrate, quality 10, Speex encoding. */ public static final SpeexEncoding SPEEX_VBR10 = new SpeexEncoding("SPEEX_VBR_quality_10", 10, true); /** Default quality setting for the Speex encoding. */ public static final int DEFAULT_QUALITY = 3; /** Default VBR setting for the Speex encoding. */ public static final boolean DEFAULT_VBR = false; /** Quality setting for the Speex encoding. */ protected int quality; /** Defines whether or not the encoding is Variable Bit Rate. */ protected boolean vbr; /** * Constructs a new encoding. * @param name - Name of the Speex encoding. * @param quality - Quality setting for the Speex encoding. * @param vbr - Defines whether or not the encoding is Variable Bit Rate. */ public SpeexEncoding(final String name, final int quality, final boolean vbr) { super(name); this.quality = quality; this.vbr = vbr; } /** * Constructs a new encoding. * @param name - Name of the Speex encoding. */ public SpeexEncoding(final String name) { this(name, DEFAULT_QUALITY, DEFAULT_VBR); } /** * Returns the quality setting for the Speex encoding. * @return the quality setting for the Speex encoding. */ public int getQuality() { return quality; } /** * Returns whether or not the encoding is Variable Bit Rate. * @return whether or not the encoding is Variable Bit Rate. */ public boolean isVBR() { return vbr; } } jspeex/src/java/org/xiph/speex/spi/SpeexFileFormatType.java0000644000175000017500000000664410135761046024257 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: SpeexFileFormatType.java * * * * Author: Marc GIMPEL * * * * Date: 12th July 2003 * * * ******************************************************************************/ /* $Id: SpeexFileFormatType.java,v 1.2 2004/10/21 16:21:58 mgimpel Exp $ */ package org.xiph.speex.spi; import javax.sound.sampled.AudioFileFormat; /** * FileFormatTypes used by the Speex audio decoder. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class SpeexFileFormatType extends AudioFileFormat.Type { /** * Specifies an OGG Speex file. */ public static final AudioFileFormat.Type SPEEX =new SpeexFileFormatType("SPEEX", "spx"); /** * Constructs a file type. * @param name - the name of the Speex File Format. * @param extension - the file extension for this Speex File Format. */ public SpeexFileFormatType(final String name, final String extension) { super(name, extension); } } jspeex/src/java/org/xiph/speex/spi/SpeexFormatConvertionProvider.java0000644000175000017500000003556410135761046026402 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: SpeexFormatConvertionProvider.java * * * * Author: Marc GIMPEL * * * * Date: 12th July 2003 * * * ******************************************************************************/ /* $Id: SpeexFormatConvertionProvider.java,v 1.2 2004/10/21 16:21:58 mgimpel Exp $ */ package org.xiph.speex.spi; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.spi.FormatConversionProvider; /** * A format conversion provider provides format conversion services from one or * more input formats to one or more output formats. Converters include codecs, * which encode and/or decode audio data, as well as transcoders, etc. * Format converters provide methods for determining what conversions are * supported and for obtaining an audio stream from which converted data can be * read. * * The source format represents the format of the incoming audio data, which * will be converted. * * The target format represents the format of the processed, converted audio * data. This is the format of the data that can be read from the stream * returned by one of the getAudioInputStream methods. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class SpeexFormatConvertionProvider extends FormatConversionProvider { /** */ public static final AudioFormat.Encoding[] NO_ENCODING = {}; /** */ public static final AudioFormat.Encoding[] PCM_ENCODING = {AudioFormat.Encoding.PCM_SIGNED}; /** */ public static final AudioFormat.Encoding[] SPEEX_ENCODING = {SpeexEncoding.SPEEX}; /** */ public static final AudioFormat.Encoding[] BOTH_ENCODINGS = {SpeexEncoding.SPEEX, AudioFormat.Encoding.PCM_SIGNED}; /** */ public static final AudioFormat[] NO_FORMAT = {}; /** * Obtains the set of source format encodings from which format conversion * services are provided by this provider. * @return array of source format encodings. * The array will always have a length of at least 1. */ public AudioFormat.Encoding[] getSourceEncodings() { AudioFormat.Encoding[] encodings = {SpeexEncoding.SPEEX, AudioFormat.Encoding.PCM_SIGNED}; return encodings; } /** * Obtains the set of target format encodings to which format conversion * services are provided by this provider. * @return array of target format encodings. * The array will always have a length of at least 1. */ public AudioFormat.Encoding[] getTargetEncodings() { AudioFormat.Encoding[] encodings = {SpeexEncoding.SPEEX_Q0, SpeexEncoding.SPEEX_Q1, SpeexEncoding.SPEEX_Q2, SpeexEncoding.SPEEX_Q3, SpeexEncoding.SPEEX_Q4, SpeexEncoding.SPEEX_Q5, SpeexEncoding.SPEEX_Q6, SpeexEncoding.SPEEX_Q7, SpeexEncoding.SPEEX_Q8, SpeexEncoding.SPEEX_Q9, SpeexEncoding.SPEEX_Q10, SpeexEncoding.SPEEX_VBR0, SpeexEncoding.SPEEX_VBR1, SpeexEncoding.SPEEX_VBR2, SpeexEncoding.SPEEX_VBR3, SpeexEncoding.SPEEX_VBR4, SpeexEncoding.SPEEX_VBR5, SpeexEncoding.SPEEX_VBR6, SpeexEncoding.SPEEX_VBR7, SpeexEncoding.SPEEX_VBR8, SpeexEncoding.SPEEX_VBR9, SpeexEncoding.SPEEX_VBR10, AudioFormat.Encoding.PCM_SIGNED}; return encodings; } /** * Obtains the set of target format encodings supported by the format * converter given a particular source format. If no target format encodings * are supported for this source format, an array of length 0 is returned. * @param sourceFormat format of the incoming data. * @return array of supported target format encodings. */ public AudioFormat.Encoding[] getTargetEncodings(final AudioFormat sourceFormat) { if (sourceFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) { AudioFormat.Encoding[] encodings = {SpeexEncoding.SPEEX_Q0, SpeexEncoding.SPEEX_Q1, SpeexEncoding.SPEEX_Q2, SpeexEncoding.SPEEX_Q3, SpeexEncoding.SPEEX_Q4, SpeexEncoding.SPEEX_Q5, SpeexEncoding.SPEEX_Q6, SpeexEncoding.SPEEX_Q7, SpeexEncoding.SPEEX_Q8, SpeexEncoding.SPEEX_Q9, SpeexEncoding.SPEEX_Q10, SpeexEncoding.SPEEX_VBR0, SpeexEncoding.SPEEX_VBR1, SpeexEncoding.SPEEX_VBR2, SpeexEncoding.SPEEX_VBR3, SpeexEncoding.SPEEX_VBR4, SpeexEncoding.SPEEX_VBR5, SpeexEncoding.SPEEX_VBR6, SpeexEncoding.SPEEX_VBR7, SpeexEncoding.SPEEX_VBR8, SpeexEncoding.SPEEX_VBR9, SpeexEncoding.SPEEX_VBR10}; return encodings; } else if (sourceFormat.getEncoding() instanceof SpeexEncoding) { AudioFormat.Encoding[] encodings = {AudioFormat.Encoding.PCM_SIGNED}; return encodings; } else { AudioFormat.Encoding[] encodings = {}; return encodings; } } /** * Obtains the set of target formats with the encoding specified supported by * the format converter. If no target formats with the specified encoding are * supported for this source format, an array of length 0 is returned. * @param targetEncoding desired encoding of the outgoing data. * @param sourceFormat format of the incoming data. * @return array of supported target formats. */ public AudioFormat[] getTargetFormats(final AudioFormat.Encoding targetEncoding, final AudioFormat sourceFormat) { if (sourceFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED) && targetEncoding instanceof SpeexEncoding) { if (sourceFormat.getChannels() > 2 || sourceFormat.getChannels() <= 0 || sourceFormat.isBigEndian()) { AudioFormat[] formats = {}; return formats; } else { AudioFormat[] formats = {new AudioFormat(targetEncoding, sourceFormat.getSampleRate(), -1, // sample size in bits sourceFormat.getChannels(), -1, // frame size -1, // frame rate false)}; // little endian return formats; } } else if (sourceFormat.getEncoding() instanceof SpeexEncoding && targetEncoding.equals(AudioFormat.Encoding.PCM_SIGNED)) { AudioFormat[] formats = {new AudioFormat(sourceFormat.getSampleRate(), 16, // sample size in bits sourceFormat.getChannels(), true, // signed false)}; // little endian (for PCM wav) return formats; } else { AudioFormat[] formats = {}; return formats; } } /** * Obtains an audio input stream with the specified encoding from the given * audio input stream. * @param targetEncoding - desired encoding of the stream after processing. * @param sourceStream - stream from which data to be processed should be read. * @return stream from which processed data with the specified target * encoding may be read. * @exception IllegalArgumentException - if the format combination supplied * is not supported. */ public AudioInputStream getAudioInputStream(final AudioFormat.Encoding targetEncoding, final AudioInputStream sourceStream) { if (isConversionSupported(targetEncoding, sourceStream.getFormat())) { AudioFormat[] formats = getTargetFormats(targetEncoding, sourceStream.getFormat()); if (formats != null && formats.length > 0) { AudioFormat sourceFormat = sourceStream.getFormat(); AudioFormat targetFormat = formats[0]; if (sourceFormat.equals(targetFormat)) { return sourceStream; } else if (sourceFormat.getEncoding() instanceof SpeexEncoding && targetFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) { return new Speex2PcmAudioInputStream(sourceStream, targetFormat, -1); } else if (sourceFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED) && targetFormat.getEncoding() instanceof SpeexEncoding) { return new Pcm2SpeexAudioInputStream(sourceStream, targetFormat, -1); } else { throw new IllegalArgumentException("unable to convert " + sourceFormat.toString() + " to " + targetFormat.toString()); } } else { throw new IllegalArgumentException("target format not found"); } } else { throw new IllegalArgumentException("conversion not supported"); } } /** * Obtains an audio input stream with the specified format from the given * audio input stream. * @param targetFormat - desired data format of the stream after processing. * @param sourceStream - stream from which data to be processed should be read. * @return stream from which processed data with the specified format may be * read. * @exception IllegalArgumentException - if the format combination supplied * is not supported. */ public AudioInputStream getAudioInputStream(final AudioFormat targetFormat, final AudioInputStream sourceStream) { if (isConversionSupported(targetFormat, sourceStream.getFormat())) { AudioFormat[] formats = getTargetFormats(targetFormat.getEncoding(), sourceStream.getFormat()); if (formats != null && formats.length > 0) { AudioFormat sourceFormat = sourceStream.getFormat(); if (sourceFormat.equals(targetFormat)) { return sourceStream; } else if (sourceFormat.getEncoding() instanceof SpeexEncoding && targetFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) { return new Speex2PcmAudioInputStream(sourceStream, targetFormat, -1); } else if (sourceFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED) && targetFormat.getEncoding() instanceof SpeexEncoding) { return new Pcm2SpeexAudioInputStream(sourceStream, targetFormat, -1); } else { throw new IllegalArgumentException("unable to convert " + sourceFormat.toString() + " to " + targetFormat.toString()); } } else { throw new IllegalArgumentException("target format not found"); } } else { throw new IllegalArgumentException("conversion not supported"); } } } jspeex/src/java/org/xiph/speex/spi/package.html0000644000175000017500000000045110135522576021767 0ustar twernertwerner JSpeex JavaSound SPI Package

JSpeex JavaSound SPI package.

It contains the JavaSound SPI (Service Provider Interface) classes for Speex.

$Id: package.html,v 1.1 2004/10/20 17:50:54 mgimpel Exp $ jspeex/src/java/org/xiph/speex/player/0000755000175000017500000000000010245633324020203 5ustar twernertwernerjspeex/src/java/org/xiph/speex/player/Player.java0000644000175000017500000005063710135761046022316 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Player.java * * * * Author: Marc GIMPEL * * * * Date: Jun 1, 2004 * * * ******************************************************************************/ /* $Id: Player.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ package org.xiph.speex.player; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.Timer; /** * JavaSound Player. * Here is the Finite State Machine describing it's state. *

 *          +----+
 *          |Init|
 *          +----+
 *             V
 *    ----->+----+
 *   /     >|Stop| \
 *  /     / +----+< \
 * /     /         \ V
 * | +-----+ ---> +----+
 * | |Pause|      |Play|
 * | +-----+ <--- +----+
 *  \     A        / A
 *   \     \+----+< /
 *    ------|Buff| /
 *          +----+
 * 
* * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class Player extends JPanel implements ActionListener { /** Build Number */ public static final String BUILD = "@BUILD@"; /** Version Number */ public static final String VERSION = "@VERSION@"; /** Revision Number */ public static final String REVISION = "$Revision: 1.2 $"; // Possible States for the Finite State Machine /** Finite State Machine State: Initialised */ protected static final int STATE_INIT = 0; /** Finite State Machine State: Stopped */ protected static final int STATE_STOPPED = 1; /** Finite State Machine State: Playing */ protected static final int STATE_PLAYING = 2; /** Finite State Machine State: Paused */ protected static final int STATE_PAUSED = 3; /** Finite State Machine State: Buffering */ protected static final int STATE_BUFFERING = 4; /** Finite State Machine State: Error */ protected static final int STATE_ERROR = 5; /** The Players Scroll Panel */ protected JPanel playerScrollPane; /** The Players Button Panel */ protected JPanel playerButtonPane; /** Play Button */ protected JButton playButton; /** Pause Button */ protected JButton pauseButton; /** Stop Button */ protected JButton stopButton; /** Progress Bar */ protected JSlider progressBar; protected Timer timer; /** Current State of the Finite State Machine */ protected int state; /** Previous State of the Finite State Machine */ protected int oldstate; protected String audioFilename; protected URL audioFile; protected int audioLength; protected Playback playback; //-------------------------------------------------------------------------- // Initialization code //-------------------------------------------------------------------------- /** * Command Line entrance. * @param args */ public static void main(final String[] args) { String filename = null; if (args.length > 0) { filename = args[0]; } final Player player = new Player(filename); player.init(); JFrame frame = new JFrame("Player"); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} public void windowDeiconified(WindowEvent e) { player.start(); } public void windowIconified(WindowEvent e) { player.stop(); } }); frame.getContentPane().add("Center", player); frame.pack(); frame.setVisible(true); } /** * Build a Player. * @param file */ public Player(final String file) { this.audioFilename = file; createGUI(); } /** * Initialize the Player Component. */ public void init() { state = STATE_STOPPED; if (!audioFilename.startsWith("http://") && !audioFilename.startsWith("file:/")) audioFilename = "file:/" + audioFilename; try { audioFile = new URL(audioFilename); } catch (MalformedURLException e) { e.printStackTrace(); } audioLength = 0; playback = new Playback(); } /** * Start the Player Component. */ public void start() { } /** * Stop the Player Component. */ public void stop() { if (state != STATE_STOPPED) { stopButton.doClick(); } } /** * Returns an InputSteam containing the Audio to playback. * @return an InputSteam containing the Audio to playback. * @throws IOException */ protected InputStream getAudioStream() throws IOException { return new BufferedInputStream(audioFile.openStream()); } //-------------------------------------------------------------------------- // Running code //-------------------------------------------------------------------------- /** * Playback thread */ protected class Playback implements Runnable { protected InputStream audioStream; protected AudioInputStream audioInputStream; protected AudioFormat audioFormat; protected DataLine.Info info; protected SourceDataLine line; protected byte[] buffer; protected int written; protected int read; protected Thread thread; /** * Start the playback thread which fills the JavaSound playback buffer. */ protected void start() { thread = new Thread(this); thread.setName("Playback"); thread.start(); } /** * Stop the playback thread and destroy all resources. */ protected void stop() { // Stop the thread thread = null; // Close the line if (line != null) { line.stop(); line.close(); line = null; } // Close the audio InputStream try { audioInputStream.close(); } catch (IOException e) { e.printStackTrace(); } audioInputStream = null; } /** * Setup the JavaSound System to play the Audio. */ protected void setupSound() { // We have to read in the sound file. try { audioStream = getAudioStream(); if (audioStream instanceof AudioInputStream) { audioInputStream = (AudioInputStream) audioStream; } else { audioInputStream = AudioSystem.getAudioInputStream(audioStream); } } catch (Exception e) { e.printStackTrace(); } /* From the AudioInputStream, i.e. from the sound file, we fetch information about the format of the audio data. This information includes the sampling frequency, the number of channels and the size of the samples. This information is needed to ask JavaSound for a suitable output line for this audio file. */ audioFormat = audioInputStream.getFormat(); /* Asking for a line is a rather tricky thing. We have to construct an Info object that specifies the desired properties for the line. First, we have to say which kind of line we want. The possibilities are: SourceDataLine (for playback), Clip (for repeated playback) and TargetDataLine (for recording). Here, we want to do normal playback, so we ask for a SourceDataLine. Then, we have to pass an AudioFormat object, so that the Line knows which format the data passed to it will have. Furthermore, we can give JavaSound a hint about how big the internal buffer for the line should be. This isn't used here, signaling that we don't care about the exact size. JavaSound will use some default value for the buffer size. */ info = new DataLine.Info(SourceDataLine.class, audioFormat); // If the audioFormat is not directly supported if (!AudioSystem.isLineSupported(info)) { AudioFormat sourceFormat = audioFormat; AudioFormat targetFormat = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED, sourceFormat.getSampleRate(), 16, sourceFormat.getChannels(), sourceFormat.getChannels() * 2, sourceFormat.getSampleRate(), false); audioInputStream = AudioSystem.getAudioInputStream(targetFormat, audioInputStream); audioFormat = audioInputStream.getFormat(); info = new DataLine.Info(SourceDataLine.class, audioFormat); } // We have to open the line for it to be ready to receive audio data. try { line = (SourceDataLine) AudioSystem.getLine(info); // We have to open the line for it to be ready to receive audio data. line.open(audioFormat); } catch (LineUnavailableException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } // setup copying buffer buffer = new byte[128000]; written = 0; read = 0; } /** * The code that runs in the thread and fills the JavaSound playback buffer. * Implemented from Runnable interface. */ public void run() { while (thread != null && state == STATE_PLAYING && read != -1) { if (written >= read) { try { read = audioInputStream.read(buffer, 0, buffer.length); written = 0; } catch (IOException e) { e.printStackTrace(); } } if (read > written) { int temp = line.write(buffer, written, read-written); written += temp; } } if (state == STATE_PLAYING) { /* Wait until all data are played. This is only necessary because of the bug noted below. (If we do not wait, we would interrupt the playback by prematurely closing the line and exiting the VM.) */ line.drain(); // All data are played. We can close the shop. line.close(); stopButton.doClick(); } } } // End class Playback //-------------------------------------------------------------------------- // Action processing code //-------------------------------------------------------------------------- /** * Process Actions when button are pressed. * Implemented from ActionListener interface. * @param e */ public void actionPerformed(final ActionEvent e) { if (e.getSource() == timer) { progressBar.setValue(getProgress()); } else { if ("Play".equals(e.getActionCommand())) { playIt(); } else if ("Pause".equals(e.getActionCommand())) { if (state == STATE_PAUSED) { playIt(); } else if (state == STATE_PLAYING) { pauseIt(); } } else if ("Stop".equals(e.getActionCommand())) { stopIt(); } else { } } } /** * */ public synchronized void stopIt() { playButton.setEnabled(false); pauseButton.setEnabled(false); stopButton.setEnabled(false); oldstate = state; state = STATE_STOPPED; playback.stop(); timer.stop(); progressBar.setValue(0); playButton.setEnabled(true); pauseButton.setEnabled(false); stopButton.setEnabled(false); } /** * */ public synchronized void playIt() { playButton.setEnabled(false); pauseButton.setEnabled(false); stopButton.setEnabled(false); oldstate = state; state = STATE_PLAYING; if (oldstate == STATE_STOPPED) { playback.setupSound(); } if (playback.thread == null || !playback.thread.isAlive()) { playback.start(); } playback.line.start(); timer.start(); playButton.setEnabled(false); pauseButton.setEnabled(true); stopButton.setEnabled(true); } /** * Pause */ public synchronized void pauseIt() { playButton.setEnabled(false); pauseButton.setEnabled(false); stopButton.setEnabled(false); oldstate = state; state = STATE_PAUSED; playback.line.stop(); timer.stop(); playButton.setEnabled(true); pauseButton.setEnabled(true); stopButton.setEnabled(true); } /** * Return the progress of the playback. * @return the progress of the playback. */ protected int getProgress() { audioLength = 500000; if (state == STATE_PLAYING || state == STATE_PAUSED) { return playback.line.getFramePosition() * 1000 / audioLength; } else { return 0; } } //-------------------------------------------------------------------------- // GUI code //-------------------------------------------------------------------------- /** * Create GUI for the player. * The player panel that should look something like this: *
 
   * +-----------------------+
   * |  ----|--------------  |  Scroll Panel
   * +-----------------------+
   * | +----+ +-----+ +----+ |
   * | |play| |pause| |stop| |  Button Panel
   * | +----+ +-----+ +----+ |
   * +-----------------------+
   * 
*/ protected void createGUI() { // Create a player panel: setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); playerScrollPane = new JPanel(new FlowLayout()); playerButtonPane = new JPanel(new FlowLayout()); createScrollPanel(); createButtonPanel(); add(playerScrollPane); add(playerButtonPane); setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.black)); } /** * Create the ScrollPanel for the player. * The player scroll panel that should look something like this: *
 
   * +-----------------------+
   * |  ----|--------------  |  Scroll Panel
   * +-----------------------+
   * 
*/ protected void createScrollPanel() { // Create the Progress Bar progressBar = new JSlider(); progressBar.setMinimum(0); progressBar.setMaximum(1000); progressBar.setValue(0); progressBar.setPreferredSize(new Dimension(120, 16)); progressBar.setBackground(Color.WHITE); progressBar.setEnabled(false); playerScrollPane.add(progressBar); playerScrollPane.setBackground(Color.WHITE); // Create the timer timer = new Timer(100, this); } /** * Create the ButtonPanel for the player. * The player button panel that should look something like this: *
 
   * +-----------------------+
   * | +----+ +-----+ +----+ |
   * | |play| |pause| |stop| |  Button Panel
   * | +----+ +-----+ +----+ |
   * +-----------------------+
   * 
*/ protected void createButtonPanel() { playButton = buildButton("Play", "Play", "/images/player_play.gif", "/images/player_play2.gif", "/images/player_play3.gif", this); playerButtonPane.add(playButton); pauseButton = buildButton("Pause", "Pause", "/images/player_pause.gif", "/images/player_pause2.gif", "/images/player_pause3.gif", this); playerButtonPane.add(pauseButton); stopButton = buildButton("Stop", "Stop", "/images/player_stop.gif", "/images/player_stop2.gif", "/images/player_stop3.gif", this); playerButtonPane.add(stopButton); playerButtonPane.setBackground(Color.WHITE); // Make the player panel the content pane. setOpaque(true); } /** * Build a Button. * @param actionCommand * @param toolTip * @param pathIconDefault * @param pathIconDisabled * @param pathIconRollover * @param listener * @return the Button that was built. */ protected static JButton buildButton(final String actionCommand, final String toolTip, final String pathIconDefault, final String pathIconDisabled, final String pathIconRollover, final ActionListener listener) { ImageIcon IconDefault = createImageIcon(pathIconDefault); ImageIcon IconDisabled = createImageIcon(pathIconDisabled); ImageIcon IconRollover = createImageIcon(pathIconRollover); JButton button = new JButton(); button.setActionCommand(actionCommand); button.setToolTipText(toolTip); button.setIcon(IconDefault); button.setDisabledIcon(IconDisabled); button.setRolloverIcon(IconRollover); button.setBorderPainted(false); button.setBackground(Color.WHITE); button.setPreferredSize(new Dimension(IconDefault.getIconWidth(), IconDefault.getIconHeight())); button.addActionListener(listener); return button; } /** * Returns an ImageIcon, or null if the path was invalid. * @param path * @return an ImageIcon, or null if the path was invalid. */ protected static ImageIcon createImageIcon(final String path) { URL imgURL = Player.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { System.err.println("Couldn't find file: " + path); System.err.println("path: " + Player.class.getResource(".")); return null; } } } jspeex/src/java/org/xiph/speex/player/PlayerApplet.java0000644000175000017500000001224310135761046023453 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: PlayerApplet.java * * * * Author: Marc GIMPEL * * * * Date: Jun 8, 2004 * * * ******************************************************************************/ /* $Id: PlayerApplet.java,v 1.2 2004/10/21 16:21:58 mgimpel Exp $ */ package org.xiph.speex.player; import javax.swing.JApplet; import javax.swing.SwingUtilities; /** * JavaSound Player Applet. * This is simply a Player Panel placed inside an applet. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class PlayerApplet extends JApplet { private Player player; private String filename; /** * Initialize Applet. * Called by the browser or applet viewer to inform this applet that it has * been loaded into the system. It is always called before the first time * that the start method is called. */ public void init() { System.out.println("****** Player Applet starting, copyright Wimba 2004"); System.out.println("****** Version: " + Player.VERSION + ", Revision: " + Player.REVISION + ", build: " + Player.BUILD); filename = getParameter("file"); // Some initialising should be done on the event-dispatching thread. try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { initGUI(); } }); } catch (Exception e) { System.err.println("couldn't successfully initialise from event thread"); } // The rest of the initialising is done from the applet launching thread. player.init(); } /** * Initialize Applet, but run from the event-dispatching thread. */ public void initGUI() { player = new Player(filename); setContentPane(player); } /** * Called by the browser or applet viewer to inform this applet that it * should start its execution. It is called after the init * method and each time the applet is revisited in a Web page. */ public void start() { player.start(); } /** * Called by the browser or applet viewer to inform this applet that it * should stop its execution. It is called when the Web page that contains * this applet has been replaced by another page, and also just before the * applet is to be destroyed. */ public void stop() { player.stop(); } /** * Called by the browser or applet viewer to inform this applet that it is * being reclaimed and that it should destroy any resources that it has * allocated. The stop method will always be called before * destroy. */ public void destroy() { player = null; } } jspeex/src/java/org/xiph/speex/player/Recorder.java0000644000175000017500000003604410135761046022623 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Recorder.java * * * * Author: Marc GIMPEL * * * * Date: Jun 1, 2004 * * * ******************************************************************************/ /* $Id: Recorder.java,v 1.2 2004/10/21 16:21:58 mgimpel Exp $ */ package org.xiph.speex.player; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.TargetDataLine; import javax.swing.JButton; import javax.swing.JFrame; import org.xiph.speex.spi.SpeexEncoding; /** * JavaSound Recorder. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class Recorder extends Player { /** Revision Number */ public static final String REVISION = "$Revision: 1.2 $"; /** Audio sampled at 8 kHz (telephone quality). */ public static final String SAMPLERATE_8KHZ = "8000 Hz"; /** Audio sampled at 11 kHz. */ public static final String SAMPLERATE_11KHZ = "11025 Hz"; /** Audio sampled at 16 kHz (wideband). */ public static final String SAMPLERATE_16KHZ = "16000 Hz"; /** Audio sampled at 22 kHz (FM radio quality). */ public static final String SAMPLERATE_22KHZ = "22050 Hz"; /** Audio sampled at 32 kHz (ultra-wideband). */ public static final String SAMPLERATE_32KHZ = "32000 Hz"; /** Audio sampled at 44 kHz (CD quality). */ public static final String SAMPLERATE_44KHZ = "44100 Hz"; /** Mono Audio (1 channel). */ public static final String CHANNELS_MONO = "mono"; /** Stereo Audio (2 channels). */ public static final String CHANNELS_STEREO = "stereo"; // Possible States for the Finite State Machine /** Finite State Machine State: Recording */ protected static final int STATE_RECORDING = 6; /** Finite State Machine State: Recording Paused */ protected static final int STATE_REC_PAUSED = 7; /** Record Button */ protected JButton recordButton; protected Capture capture; protected byte[] audio; //-------------------------------------------------------------------------- // Initialization code //-------------------------------------------------------------------------- /** * Command Line entrance. * @param args */ public static void main(final String[] args) { String filename = null; if (args.length > 0) { filename = args[0]; } final Recorder recorder = new Recorder(filename); recorder.init(); JFrame frame = new JFrame("Recorder"); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} public void windowDeiconified(WindowEvent e) { recorder.start(); } public void windowIconified(WindowEvent e) { recorder.stop(); } }); frame.getContentPane().add("Center", recorder); frame.pack(); frame.setVisible(true); } /** * Build a Recorder. * @param file */ public Recorder(final String file) { super(file); } /** * Initialize the Player Component. */ public void init() { super.init(); capture = new Capture(); } /** * Returns an InputSteam containing the Audio to playback. * @return an InputSteam containing the Audio to playback. * @throws IOException */ protected InputStream getAudioStream() throws IOException { if (audio == null) { return new BufferedInputStream(audioFile.openStream()); } else { return new ByteArrayInputStream(audio); } } //-------------------------------------------------------------------------- // Running code //-------------------------------------------------------------------------- /** * Capture thread */ protected class Capture implements Runnable { protected ByteArrayOutputStream out; protected AudioInputStream audioInputStream; protected AudioFormat audioFormat; protected DataLine.Info info; protected AudioFileFormat.Type targetType; protected TargetDataLine line; protected byte[] buffer; protected Thread thread; /** * Start the playback thread which fills the JavaSound playback buffer. */ protected void start() { thread = new Thread(this); thread.setName("Capture"); thread.start(); } /** * Stop the playback thread and destroy all resources. */ protected void stop() { // Stop the thread thread = null; // Close the line if (line != null) { line.stop(); line.close(); line = null; } // stop and close the output stream try { out.flush(); out.close(); } catch (IOException ex) { ex.printStackTrace(); } // load bytes into the audio input stream for playback audio = out.toByteArray(); System.out.println("size="+audio.length); } /** * Setup the JavaSound System to play the Audio. */ protected void setupSound() { // define the required attributes for our line, // and make sure a compatible line is supported. audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100.0F, 16, 1, 2, 44100.0F, false); /* Now, we are trying to get a TargetDataLine. The TargetDataLine is used later to read audio data from it. If requesting the line was successful, we are opening it (important!). */ info = new DataLine.Info(TargetDataLine.class, audioFormat); try { line = (TargetDataLine) AudioSystem.getLine(info); line.open(audioFormat); } catch (LineUnavailableException e) { e.printStackTrace(); } catch (SecurityException e) { // An applet requires the following permissions to record audio: // permission javax.sound.sampled.AudioPermission : record e.printStackTrace(); } audioInputStream = new AudioInputStream(line); AudioFormat targetFormat = new AudioFormat(SpeexEncoding.SPEEX_Q6, audioFormat.getSampleRate(), -1, // sample size in bits audioFormat.getChannels(), -1, // frame size -1, // frame rate false); // little endian audioInputStream = AudioSystem.getAudioInputStream(targetFormat, audioInputStream); audioFormat = audioInputStream.getFormat(); out = new ByteArrayOutputStream(); // setup copying buffer buffer = new byte[128000]; } /** * The code that runs in the thread and recovers the JavaSound capture * buffer. * Implemented from Runnable interface. */ public void run() { int read = 0; while (thread != null && state == STATE_RECORDING && read != -1) { try { read = audioInputStream.read(buffer, 0, buffer.length); } catch (IOException e) { e.printStackTrace(); } if (read > 0) { out.write(buffer, 0, read); } } } } // End class Capture //-------------------------------------------------------------------------- // Action processing code //-------------------------------------------------------------------------- /** * Process Actions when button are pressed. * Implemented from ActionListener interface. */ public void actionPerformed(final ActionEvent e) { if (e.getSource() == timer) { progressBar.setValue(getProgress()); } else { if ("Play".equals(e.getActionCommand())) { playIt(); } else if ("Record".equals(e.getActionCommand())) { recordIt(); } else if ("Pause".equals(e.getActionCommand())) { if (state == STATE_PAUSED) { playIt(); } else if (state == STATE_REC_PAUSED) { recordIt(); } else { pauseIt(); } } else if ("Stop".equals(e.getActionCommand())) { stopIt(); } else { } } } /** * */ public synchronized void stopIt() { recordButton.setEnabled(false); playButton.setEnabled(false); pauseButton.setEnabled(false); stopButton.setEnabled(false); oldstate = state; state = STATE_STOPPED; if (oldstate == STATE_PLAYING || oldstate == STATE_PAUSED) { playback.stop(); } else if (oldstate == STATE_RECORDING || oldstate == STATE_REC_PAUSED) { capture.stop(); } timer.stop(); progressBar.setValue(0); recordButton.setEnabled(true); playButton.setEnabled(true); pauseButton.setEnabled(false); stopButton.setEnabled(false); } /** * */ public synchronized void playIt() { recordButton.setEnabled(false); playButton.setEnabled(false); pauseButton.setEnabled(false); stopButton.setEnabled(false); oldstate = state; state = STATE_PLAYING; if (oldstate == STATE_STOPPED) { playback.setupSound(); } if (playback.thread == null || !playback.thread.isAlive()) { playback.start(); } playback.line.start(); timer.start(); recordButton.setEnabled(false); playButton.setEnabled(false); pauseButton.setEnabled(true); stopButton.setEnabled(true); } /** * */ public synchronized void pauseIt() { recordButton.setEnabled(false); playButton.setEnabled(false); pauseButton.setEnabled(false); stopButton.setEnabled(false); oldstate = state; if (oldstate == STATE_PLAYING) { state = STATE_PAUSED; playback.line.stop(); recordButton.setEnabled(false); playButton.setEnabled(true); } else if (oldstate == STATE_RECORDING) { state = STATE_REC_PAUSED; capture.line.stop(); recordButton.setEnabled(true); playButton.setEnabled(false); } timer.stop(); pauseButton.setEnabled(true); stopButton.setEnabled(true); } /** * */ public synchronized void recordIt() { recordButton.setEnabled(false); playButton.setEnabled(false); pauseButton.setEnabled(false); stopButton.setEnabled(false); oldstate = state; state = STATE_RECORDING; if (oldstate == STATE_STOPPED) { capture.setupSound(); } if (capture.thread == null || !capture.thread.isAlive()) { capture.start(); } capture.line.start(); timer.start(); recordButton.setEnabled(false); playButton.setEnabled(false); pauseButton.setEnabled(true); stopButton.setEnabled(true); } /** * Return the progress of the playback. * @return the progress of the playback. */ protected int getProgress() { audioLength = 500000; if (state == STATE_PLAYING || state == STATE_PAUSED) { return super.getProgress(); } else if (state == STATE_RECORDING || state == STATE_REC_PAUSED) { return capture.line.getFramePosition() * 1000 / audioLength; } else { return 0; } } //-------------------------------------------------------------------------- // GUI code //-------------------------------------------------------------------------- /** * Create the ButtonPanel for the recorder. * The recorder button panel that should look something like this: *
 
   * +--------------------------------+
   * | +------+ +----+ +-----+ +----+ |
   * | |record| |play| |pause| |stop| |  Button Panel
   * | +------+ +----+ +-----+ +----+ |
   * +--------------------------------+
   * 
*/ protected void createButtonPanel() { recordButton = buildButton("Record", "Record", "/images/player_record.gif", "/images/player_record2.gif", "/images/player_record3.gif", this); playerButtonPane.add(recordButton); super.createButtonPanel(); } } jspeex/src/java/org/xiph/speex/player/RecorderApplet.java0000644000175000017500000001230510135761046023763 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: RecorderApplet.java * * * * Author: Marc GIMPEL * * * * Date: Jun 8, 2004 * * * ******************************************************************************/ /* $Id: RecorderApplet.java,v 1.2 2004/10/21 16:21:58 mgimpel Exp $ */ package org.xiph.speex.player; import javax.swing.JApplet; import javax.swing.SwingUtilities; /** * JavaSound Recorder Applet. * This is simply a Recorder Panel placed inside an applet. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class RecorderApplet extends JApplet { private Recorder recorder; private String filename; /** * Initialize Applet. * Called by the browser or applet viewer to inform this applet that it has * been loaded into the system. It is always called before the first time * that the start method is called. */ public void init() { System.out.println("****** Recorder Applet starting, copyright Wimba 2004"); System.out.println("****** Version: " + Recorder.VERSION + ", Revision: " + Recorder.REVISION + ", build: " + Recorder.BUILD); filename = getParameter("file"); // Some initialising should be done on the event-dispatching thread. try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { initGUI(); } }); } catch (Exception e) { System.err.println("couldn't successfully initialise from event thread"); } // The rest of the initialising is done from the applet launching thread. recorder.init(); } /** * Initialize Applet, but run from the event-dispatching thread. */ public void initGUI() { recorder = new Recorder(filename); setContentPane(recorder); } /** * Called by the browser or applet viewer to inform this applet that it * should start its execution. It is called after the init * method and each time the applet is revisited in a Web page. */ public void start() { recorder.start(); } /** * Called by the browser or applet viewer to inform this applet that it * should stop its execution. It is called when the Web page that contains * this applet has been replaced by another page, and also just before the * applet is to be destroyed. */ public void stop() { recorder.stop(); } /** * Called by the browser or applet viewer to inform this applet that it is * being reclaimed and that it should destroy any resources that it has * allocated. The stop method will always be called before * destroy. */ public void destroy() { recorder = null; } } jspeex/src/java/org/xiph/speex/player/package.html0000644000175000017500000000042610135522576022472 0ustar twernertwerner JSpeex player Package

JSpeex player package.

It contains an example swing player and recorder application and applet.

$Id: package.html,v 1.1 2004/10/20 17:50:54 mgimpel Exp $ jspeex/src/java/org/xiph/speex/AudioFileWriter.java0000644000175000017500000003306510135761046022620 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: RawWriter.java * * * * Author: Marc GIMPEL * * * * Date: 6th January 2004 * * * ******************************************************************************/ /* $Id: AudioFileWriter.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ package org.xiph.speex; import java.io.DataOutput; import java.io.File; import java.io.IOException; import java.io.OutputStream; /** * Abstract Class that defines an Audio File Writer. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public abstract class AudioFileWriter { /** * Closes the output file. * @exception IOException if there was an exception closing the Audio Writer. */ public abstract void close() throws IOException; /** * Open the output file. * @param file - file to open. * @exception IOException if there was an exception opening the Audio Writer. */ public abstract void open(File file) throws IOException; /** * Open the output file. * @param filename - file to open. * @exception IOException if there was an exception opening the Audio Writer. */ public abstract void open(String filename) throws IOException; /** * Writes the header pages that start the Ogg Speex file. * Prepares file for data to be written. * @param comment description to be included in the header. * @exception IOException */ public abstract void writeHeader(String comment) throws IOException; /** * Writes a packet of audio. * @param data audio data * @param offset the offset from which to start reading the data. * @param len the length of data to read. * @exception IOException */ public abstract void writePacket(byte[] data, int offset, int len) throws IOException; /** * Writes an Ogg Page Header to the given byte array. * @param buf the buffer to write to. * @param offset the from which to start writing. * @param headerType the header type flag * (0=normal, 2=bos: beginning of stream, 4=eos: end of stream). * @param granulepos the absolute granule position. * @param streamSerialNumber * @param pageCount * @param packetCount * @param packetSizes * @return the amount of data written to the buffer. */ public static int writeOggPageHeader(byte[] buf, int offset, int headerType, long granulepos, int streamSerialNumber, int pageCount, int packetCount, byte[] packetSizes) { writeString(buf, offset, "OggS"); // 0 - 3: capture_pattern buf[offset+4] = 0; // 4: stream_structure_version buf[offset+5] = (byte) headerType; // 5: header_type_flag writeLong(buf, offset+6, granulepos); // 6 - 13: absolute granule position writeInt(buf, offset+14, streamSerialNumber); // 14 - 17: stream serial number writeInt(buf, offset+18, pageCount); // 18 - 21: page sequence no writeInt(buf, offset+22, 0); // 22 - 25: page checksum buf[offset+26] = (byte) packetCount; // 26: page_segments System.arraycopy(packetSizes, 0, // 27 - x: segment_table buf, offset+27, packetCount); return packetCount+27; } /** * Builds and returns an Ogg Page Header. * @param headerType the header type flag * (0=normal, 2=bos: beginning of stream, 4=eos: end of stream). * @param granulepos the absolute granule position. * @param streamSerialNumber * @param pageCount * @param packetCount * @param packetSizes * @return an Ogg Page Header. */ public static byte[] buildOggPageHeader(int headerType, long granulepos, int streamSerialNumber, int pageCount, int packetCount, byte[] packetSizes) { byte[] data = new byte[packetCount+27]; writeOggPageHeader(data, 0, headerType, granulepos, streamSerialNumber, pageCount, packetCount, packetSizes); return data; } /** * Writes a Speex Header to the given byte array. * @param buf the buffer to write to. * @param offset the from which to start writing. * @param sampleRate * @param mode * @param channels * @param vbr * @param nframes * @return the amount of data written to the buffer. */ public static int writeSpeexHeader(byte[] buf, int offset, int sampleRate, int mode, int channels, boolean vbr, int nframes) { writeString(buf, offset, "Speex "); // 0 - 7: speex_string writeString(buf, offset+8, "speex-1.0"); // 8 - 27: speex_version System.arraycopy(new byte[11], 0, buf, offset+17, 11); // : speex_version (fill in up to 20 bytes) writeInt(buf, offset+28, 1); // 28 - 31: speex_version_id writeInt(buf, offset+32, 80); // 32 - 35: header_size writeInt(buf, offset+36, sampleRate); // 36 - 39: rate writeInt(buf, offset+40, mode); // 40 - 43: mode (0=NB, 1=WB, 2=UWB) writeInt(buf, offset+44, 4); // 44 - 47: mode_bitstream_version writeInt(buf, offset+48, channels); // 48 - 51: nb_channels writeInt(buf, offset+52, -1); // 52 - 55: bitrate writeInt(buf, offset+56, 160 << mode); // 56 - 59: frame_size (NB=160, WB=320, UWB=640) writeInt(buf, offset+60, vbr?1:0); // 60 - 63: vbr writeInt(buf, offset+64, nframes); // 64 - 67: frames_per_packet writeInt(buf, offset+68, 0); // 68 - 71: extra_headers writeInt(buf, offset+72, 0); // 72 - 75: reserved1 writeInt(buf, offset+76, 0); // 76 - 79: reserved2 return 80; } /** * Builds a Speex Header. * @param sampleRate * @param mode * @param channels * @param vbr * @param nframes * @return a Speex Header. */ public static byte[] buildSpeexHeader(int sampleRate, int mode, int channels, boolean vbr, int nframes) { byte[] data = new byte[80]; writeSpeexHeader(data, 0, sampleRate, mode, channels, vbr, nframes); return data; } /** * Writes a Speex Comment to the given byte array. * @param buf the buffer to write to. * @param offset the from which to start writing. * @param comment the comment. * @return the amount of data written to the buffer. */ public static int writeSpeexComment(byte[] buf, int offset, String comment) { int length = comment.length(); writeInt(buf, offset, length); // vendor comment size writeString(buf, offset+4, comment); // vendor comment writeInt(buf, offset+length+4, 0); // user comment list length return length+8; } /** * Builds and returns a Speex Comment. * @param comment the comment. * @return a Speex Comment. */ public static byte[] buildSpeexComment(String comment) { byte[] data = new byte[comment.length()+8]; writeSpeexComment(data, 0, comment); return data; } /** * Writes a Little-endian short. * @param out the data output to write to. * @param v value to write. * @exception IOException */ public static void writeShort(DataOutput out, short v) throws IOException { out.writeByte((0xff & v)); out.writeByte((0xff & (v >>> 8))); } /** * Writes a Little-endian int. * @param out the data output to write to. * @param v value to write. * @exception IOException */ public static void writeInt(DataOutput out, int v) throws IOException { out.writeByte(0xff & v); out.writeByte(0xff & (v >>> 8)); out.writeByte(0xff & (v >>> 16)); out.writeByte(0xff & (v >>> 24)); } /** * Writes a Little-endian short. * @param os - the output stream to write to. * @param v - the value to write. * @exception IOException */ public static void writeShort(OutputStream os, short v) throws IOException { os.write((0xff & v)); os.write((0xff & (v >>> 8))); } /** * Writes a Little-endian int. * @param os - the output stream to write to. * @param v - the value to write. * @exception IOException */ public static void writeInt(OutputStream os, int v) throws IOException { os.write(0xff & v); os.write(0xff & (v >>> 8)); os.write(0xff & (v >>> 16)); os.write(0xff & (v >>> 24)); } /** * Writes a Little-endian long. * @param os - the output stream to write to. * @param v - the value to write. * @exception IOException */ public static void writeLong(OutputStream os, long v) throws IOException { os.write((int)(0xff & v)); os.write((int)(0xff & (v >>> 8))); os.write((int)(0xff & (v >>> 16))); os.write((int)(0xff & (v >>> 24))); os.write((int)(0xff & (v >>> 32))); os.write((int)(0xff & (v >>> 40))); os.write((int)(0xff & (v >>> 48))); os.write((int)(0xff & (v >>> 56))); } /** * Writes a Little-endian short. * @param data the array into which the data should be written. * @param offset the offset from which to start writing in the array. * @param v the value to write. */ public static void writeShort(byte[] data, int offset, int v) { data[offset] = (byte) (0xff & v); data[offset+1] = (byte) (0xff & (v >>> 8)); } /** * Writes a Little-endian int. * @param data the array into which the data should be written. * @param offset the offset from which to start writing in the array. * @param v the value to write. */ public static void writeInt(byte[] data, int offset, int v) { data[offset] = (byte) (0xff & v); data[offset+1] = (byte) (0xff & (v >>> 8)); data[offset+2] = (byte) (0xff & (v >>> 16)); data[offset+3] = (byte) (0xff & (v >>> 24)); } /** * Writes a Little-endian long. * @param data the array into which the data should be written. * @param offset the offset from which to start writing in the array. * @param v the value to write. */ public static void writeLong(byte[] data, int offset, long v) { data[offset] = (byte) (0xff & v); data[offset+1] = (byte) (0xff & (v >>> 8)); data[offset+2] = (byte) (0xff & (v >>> 16)); data[offset+3] = (byte) (0xff & (v >>> 24)); data[offset+4] = (byte) (0xff & (v >>> 32)); data[offset+5] = (byte) (0xff & (v >>> 40)); data[offset+6] = (byte) (0xff & (v >>> 48)); data[offset+7] = (byte) (0xff & (v >>> 56)); } /** * Writes a String. * @param data the array into which the data should be written. * @param offset the offset from which to start writing in the array. * @param v the value to write. */ public static void writeString(byte[] data, int offset, String v) { byte[] str = v.getBytes(); System.arraycopy(str, 0, data, offset, str.length); } } jspeex/src/java/org/xiph/speex/Bits.java0000644000175000017500000001707510135761046020466 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Bits.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: Bits.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Speex bit packing and unpacking class. * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class Bits { /** Default buffer size */ public static final int DEFAULT_BUFFER_SIZE = 1024; /** "raw" data */ private byte[] bytes; /** Position of the byte "cursor" */ private int bytePtr; /** Position of the bit "cursor" within the current byte */ private int bitPtr; /** * Initialise the bit packing variables. */ public void init() { bytes = new byte[DEFAULT_BUFFER_SIZE]; bytePtr=0; bitPtr=0; } /** * Advance n bits. * @param n - the number of bits to advance. */ public void advance(final int n) { bytePtr += n >> 3; bitPtr += n & 7; if (bitPtr>7) { bitPtr-=8; bytePtr++; } } /** * Sets the buffer to the given value. * @param newBuffer */ protected void setBuffer(final byte[] newBuffer) { bytes = newBuffer; } /** * Take a peek at the next bit. * @return the next bit. */ public int peek() { return ((bytes[bytePtr] & 0xFF) >> (7-bitPtr)) & 1; } /** * Read the given array into the buffer. * @param newbytes * @param offset * @param len */ public void read_from(final byte[] newbytes, final int offset, final int len) { for (int i=0; i>(7-bitPtr))&1; bitPtr++; if (bitPtr==8) { bitPtr=0; bytePtr++; } nbBits--; } return d; } /** * Write N bits of the given data to the buffer. * @param data - the data to write. * @param nbBits - the number of bits of the data to write. */ public void pack(int data, int nbBits) { int d=data; while (bytePtr+((nbBits+bitPtr)>>3) >= bytes.length) { // System.err.println("Buffer too small to pack bits"); /* Expand the buffer as needed. */ int size = bytes.length*2; byte[] tmp = new byte[size]; System.arraycopy(bytes, 0, tmp, 0, bytes.length); bytes = tmp; } while (nbBits>0) { int bit; bit = (d>>(nbBits-1))&1; bytes[bytePtr] |= bit<<(7-bitPtr); bitPtr++; if (bitPtr==8) { bitPtr=0; bytePtr++; } nbBits--; } } /** * Returns the current buffer array. * @return the current buffer array. */ public byte[] getBuffer() { return bytes; } /** * Returns the number of bytes used in the current buffer. * @return the number of bytes used in the current buffer. */ public int getBufferSize() { return bytePtr + (bitPtr > 0 ? 1 : 0); } } jspeex/src/java/org/xiph/speex/CbSearch.java0000644000175000017500000001326410135761046021233 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: CbSearch.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: CbSearch.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Abstract class that is the base for the various Codebook search methods. * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public abstract class CbSearch { /** * Codebook Search Quantification. * @param target target vector * @param ak LPCs for this subframe * @param awk1 Weighted LPCs for this subframe * @param awk2 Weighted LPCs for this subframe * @param p number of LPC coeffs * @param nsf number of samples in subframe * @param exc excitation array. * @param es position in excitation array. * @param r * @param bits Speex bits buffer. * @param complexity */ public abstract void quant(float[] target, float[] ak, float[] awk1, float[] awk2, int p, int nsf, float[] exc, int es, float[] r, Bits bits, int complexity); /** * Codebook Search Unquantification. * @param exc - excitation array. * @param es - position in excitation array. * @param nsf - number of samples in subframe. * @param bits - Speex bits buffer. */ public abstract void unquant(float[] exc, int es, int nsf, Bits bits); } jspeex/src/java/org/xiph/speex/Codebook.java0000644000175000017500000013067210135761046021311 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Codebook.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: Codebook.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Codebook tables * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public interface Codebook { /** * Excitation Codebook */ public static final int[] exc_20_32_table = { 12,32,25,46,36,33,9,14,-3,6,1,-8,0,-10,-5,-7,-7,-7,-5,-5, 31,-27,24,-32,-4,10,-11,21,-3,19,23,-9,22,24,-10,-1,-10,-13,-7,-11, 42,-33,31,19,-8,0,-10,-16,1,-21,-17,10,-8,14,8,4,11,-2,5,-2, -33,11,-16,33,11,-4,9,-4,11,2,6,-5,8,-5,11,-4,-6,26,-36,-16, 0,4,-2,-8,12,6,-1,34,-46,-22,9,9,21,9,5,-66,-5,26,2,10, 13,2,19,9,12,-81,3,13,13,0,-14,22,-35,6,-7,-4,6,-6,10,-6, -31,38,-33,0,-10,-11,5,-12,12,-17,5,0,-6,13,-9,10,8,25,33,2, -12,8,-6,10,-2,21,7,17,43,5,11,-7,-9,-20,-36,-20,-23,-4,-4,-3, 27,-9,-9,-49,-39,-38,-11,-9,6,5,23,25,5,3,3,4,1,2,-3,-1, 87,39,17,-21,-9,-19,-9,-15,-13,-14,-17,-11,-10,-11,-8,-6,-1,-3,-3,-1, -54,-34,-27,-8,-11,-4,-5,0,0,4,8,6,9,7,9,7,6,5,5,5, 48,10,19,-10,12,-1,9,-3,2,5,-3,2,-2,-2,0,-2,-26,6,9,-7, -16,-9,2,7,7,-5,-43,11,22,-11,-9,34,37,-15,-13,-6,1,-1,1,1, -64,56,52,-11,-27,5,4,3,1,2,1,3,-1,-4,-4,-10,-7,-4,-4,2, -1,-7,-7,-12,-10,-15,-9,-5,-5,-11,-16,-13,6,16,4,-13,-16,-10,-4,2, -47,-13,25,47,19,-14,-20,-8,-17,0,-3,-13,1,6,-17,-14,15,1,10,6, -24,0,-10,19,-69,-8,14,49,17,-5,33,-29,3,-4,0,2,-8,5,-6,2, 120,-56,-12,-47,23,-9,6,-5,1,2,-5,1,-10,4,-1,-1,4,-1,0,-3, 30,-52,-67,30,22,11,-1,-4,3,0,7,2,0,1,-10,-4,-8,-13,5,1, 1,-1,5,13,-9,-3,-10,-62,22,48,-4,-6,2,3,5,1,1,4,1,13, 3,-20,10,-9,13,-2,-4,9,-20,44,-1,20,-32,-67,19,0,28,11,8,2, -11,15,-19,-53,31,2,34,10,6,-4,-58,8,10,13,14,1,12,2,0,0, -128,37,-8,44,-9,26,-3,18,2,6,11,-1,9,1,5,3,0,1,1,2, 12,3,-2,-3,7,25,9,18,-6,-37,3,-8,-16,3,-10,-7,17,-34,-44,11, 17,-15,-3,-16,-1,-13,11,-46,-65,-2,8,13,2,4,4,5,15,5,9,6, 8,2,8,3,10,-1,3,-3,6,-2,3,3,-5,10,-11,7,6,-2,6,-2, -9,19,-12,12,-28,38,29,-1,12,2,5,23,-10,3,4,-15,21,-4,3,3, 6,17,-9,-4,-8,-20,26,5,-10,6,1,-19,18,-15,-12,47,-6,-2,-7,-9, -1,-17,-2,-2,-14,30,-14,2,-7,-4,-1,-12,11,-25,16,-3,-12,11,-7,7, -17,1,19,-28,31,-7,-10,7,-10,3,12,5,-16,6,24,41,-29,-54,0,1, 7,-1,5,-6,13,10,-4,-8,8,-9,-27,-53,-38,-1,10,19,17,16,12,12, 0,3,-7,-4,13,12,-31,-14,6,-5,3,5,17,43,50,25,10,1,-6,-2 }; /** * Excitation Codebook */ public static final int[] exc_10_16_table = { 22,39,14,44,11,35,-2,23,-4,6, 46,-28,13,-27,-23,12,4,20,-5,9, 37,-18,-23,23,0,9,-6,-20,4,-1, -17,-5,-4,17,0,1,9,-2,1,2, 2,-12,8,-25,39,15,9,16,-55,-11, 9,11,5,10,-2,-60,8,13,-6,11, -16,27,-47,-12,11,1,16,-7,9,-3, -29,9,-14,25,-19,34,36,12,40,-10, -3,-24,-14,-37,-21,-35,-2,-36,3,-6, 67,28,6,-17,-3,-12,-16,-15,-17,-7, -59,-36,-13,1,7,1,2,10,2,11, 13,10,8,-2,7,3,5,4,2,2, -3,-8,4,-5,6,7,-42,15,35,-2, -46,38,28,-20,-9,1,7,-3,0,-2, -5,-4,-2,-4,-8,-3,-8,-5,-7,-4, -15,-28,52,32,5,-5,-17,-20,-10,-1 }; /** * Excitation Codebook */ public static final int[] exc_10_32_table = { 7,17,17,27,25,22,12,4,-3,0, 28,-36,39,-24,-15,3,-9,15,-5,10, 31,-28,11,31,-21,9,-11,-11,-2,-7, -25,14,-22,31,4,-14,19,-12,14,-5, 4,-7,4,-5,9,0,-2,42,-47,-16, 1,8,0,9,23,-57,0,28,-11,6, -31,55,-45,3,-5,4,2,-2,4,-7, -3,6,-2,7,-3,12,5,8,54,-10, 8,-7,-8,-24,-25,-27,-14,-5,8,5, 44,23,5,-9,-11,-11,-13,-9,-12,-8, -29,-8,-22,6,-15,3,-12,-1,-5,-3, 34,-1,29,-16,17,-4,12,2,1,4, -2,-4,2,-1,11,-3,-52,28,30,-9, -32,25,44,-20,-24,4,6,-1,0,0, -3,7,-4,-4,-7,-6,-9,-2,-10,-7, -25,-10,22,29,13,-13,-22,-13,-4,0, -4,-16,10,15,-36,-24,28,25,-1,-3, 66,-33,-11,-15,6,0,3,4,-2,5, 24,-20,-47,29,19,-2,-4,-1,0,-1, -2,3,1,8,-11,5,5,-57,28,28, 0,-16,4,-4,12,-6,-1,2,-20,61, -9,24,-22,-42,29,6,17,8,4,2, -65,15,8,10,5,6,5,3,2,-2, -3,5,-9,4,-5,23,13,23,-3,-63, 3,-5,-4,-6,0,-3,23,-36,-46,9, 5,5,8,4,9,-5,1,-3,10,1, -6,10,-11,24,-47,31,22,-12,14,-10, 6,11,-7,-7,7,-31,51,-12,-6,7, 6,-17,9,-11,-20,52,-19,3,-6,-6, -8,-5,23,-41,37,1,-21,10,-14,8, 7,5,-15,-15,23,39,-26,-33,7,2, -32,-30,-21,-8,4,12,17,15,14,11 }; /** * Excitation Codebook */ public static final int[] exc_5_256_table = { -8,-37,5,-43,5, 73,61,39,12,-3, -61,-32,2,42,30, -3,17,-27,9,34, 20,-1,-5,2,23, -7,-46,26,53,-47, 20,-2,-33,-89,-51, -64,27,11,15,-34, -5,-56,25,-9,-1, -29,1,40,67,-23, -16,16,33,19,7, 14,85,22,-10,-10, -12,-7,-1,52,89, 29,11,-20,-37,-46, -15,17,-24,-28,24, 2,1,0,23,-101, 23,14,-1,-23,-18, 9,5,-13,38,1, -28,-28,4,27,51, -26,34,-40,35,47, 54,38,-54,-26,-6, 42,-25,13,-30,-36, 18,41,-4,-33,23, -32,-7,-4,51,-3, 17,-52,56,-47,36, -2,-21,36,10,8, -33,31,19,9,-5, -40,10,-9,-21,19, 18,-78,-18,-5,0, -26,-36,-47,-51,-44, 18,40,27,-2,29, 49,-26,2,32,-54, 30,-73,54,3,-5, 36,22,53,10,-1, -84,-53,-29,-5,3, -44,53,-51,4,22, 71,-35,-1,33,-5, -27,-7,36,17,-23, -39,16,-9,-55,-15, -20,39,-35,6,-39, -14,18,48,-64,-17, -15,9,39,81,37, -68,37,47,-21,-6, -104,13,6,9,-2, 35,8,-23,18,42, 45,21,33,-5,-49, 9,-6,-43,-56,39, 2,-16,-25,87,1, -3,-9,17,-25,-11, -9,-1,10,2,-14, -14,4,-1,-10,28, -23,40,-32,26,-9, 26,4,-27,-23,3, 42,-60,1,49,-3, 27,10,-52,-40,-2, 18,45,-23,17,-44, 3,-3,17,-46,52, -40,-47,25,75,31, -49,53,30,-30,-32, -36,38,-6,-15,-16, 54,-27,-48,3,38, -29,-32,-22,-14,-4, -23,-13,32,-39,9, 8,-45,-13,34,-16, 49,40,32,31,28, 23,23,32,47,59, -68,8,62,44,25, -14,-24,-65,-16,36, 67,-25,-38,-21,4, -33,-2,42,5,-63, 40,11,26,-42,-23, -61,79,-31,23,-20, 10,-32,53,-25,-36, 10,-26,-5,3,0, -71,5,-10,-37,1, -24,21,-54,-17,1, -29,-25,-15,-27,32, 68,45,-16,-37,-18, -5,1,0,-77,71, -6,3,-20,71,-67, 29,-35,10,-30,19, 4,16,17,5,0, -14,19,2,28,26, 59,3,2,24,39, 55,-50,-45,-18,-17, 33,-35,14,-1,1, 8,87,-35,-29,0, -27,13,-7,23,-13, 37,-40,50,-35,14, 19,-7,-14,49,54, -5,22,-2,-29,-8, -27,38,13,27,48, 12,-41,-21,-15,28, 7,-16,-24,-19,-20, 11,-20,9,2,13, 23,-20,11,27,-27, 71,-69,8,2,-6, 22,12,16,16,9, -16,-8,-17,1,25, 1,40,-37,-33,66, 94,53,4,-22,-25, -41,-42,25,35,-16, -15,57,31,-29,-32, 21,16,-60,45,15, -1,7,57,-26,-47, -29,11,8,15,19, -105,-8,54,27,10, -17,6,-12,-1,-10, 4,0,23,-10,31, 13,11,10,12,-64, 23,-3,-8,-19,16, 52,24,-40,16,10, 40,5,9,0,-13, -7,-21,-8,-6,-7, -21,59,16,-53,18, -60,11,-47,14,-18, 25,-13,-24,4,-39, 16,-28,54,26,-67, 30,27,-20,-52,20, -12,55,12,18,-16, 39,-14,-6,-26,56, -88,-55,12,25,26, -37,6,75,0,-34, -81,54,-30,1,-7, 49,-23,-14,21,10, -62,-58,-57,-47,-34, 15,-4,34,-78,31, 25,-11,7,50,-10, 42,-63,14,-36,-4, 57,55,57,53,42, -42,-1,15,40,37, 15,25,-11,6,1, 31,-2,-6,-1,-7, -64,34,28,30,-1, 3,21,0,-88,-12, -56,25,-28,40,8, -28,-14,9,12,2, -6,-17,22,49,-6, -26,14,28,-20,4, -12,50,35,40,13, -38,-58,-29,17,30, 22,60,26,-54,-39, -12,58,-28,-63,10, -21,-8,-12,26,-62, 6,-10,-11,-22,-6, -7,4,1,18,2, -70,11,14,4,13, 19,-24,-34,24,67, 17,51,-21,13,23, 54,-30,48,1,-13, 80,26,-16,-2,13, -4,6,-30,29,-24, 73,-58,30,-27,20, -2,-21,41,45,30, -27,-3,-5,-18,-20, -49,-3,-35,10,42, -19,-67,-53,-11,9, 13,-15,-33,-51,-30, 15,7,25,-30,4, 28,-22,-34,54,-29, 39,-46,20,16,34, -4,47,75,1,-44, -55,-24,7,-1,9, -42,50,-8,-36,41, 68,0,-4,-10,-23, -15,-50,64,36,-9, -27,12,25,-38,-47, -37,32,-49,51,-36, 2,-4,69,-26,19, 7,45,67,46,13, -63,46,15,-47,4, -41,13,-6,5,-21, 37,26,-55,-7,33, -1,-28,10,-17,-64, -14,0,-36,-17,93, -3,-9,-66,44,-21, 3,-12,38,-6,-13, -12,19,13,43,-43, -10,-12,6,-5,9, -49,32,-5,2,4, 5,15,-16,10,-21, 8,-62,-8,64,8, 79,-1,-66,-49,-18, 5,40,-5,-30,-45, 1,-6,21,-32,93, -18,-30,-21,32,21, -18,22,8,5,-41, -54,80,22,-10,-7, -8,-23,-64,66,56, -14,-30,-41,-46,-14, -29,-37,27,-14,42, -2,-9,-29,34,14, 33,-14,22,4,10, 26,26,28,32,23, -72,-32,3,0,-14, 35,-42,-78,-32,6, 29,-18,-45,-5,7, -33,-45,-3,-22,-34, 8,-8,4,-51,-25, -9,59,-78,21,-5, -25,-48,66,-15,-17, -24,-49,-13,25,-23, -64,-6,40,-24,-19, -11,57,-33,-8,1, 10,-52,-54,28,39, 49,34,-11,-61,-41, -43,10,15,-15,51, 30,15,-51,32,-34, -2,-34,14,18,16, 1,1,-3,-3,1, 1,-18,6,16,48, 12,-5,-42,7,36, 48,7,-20,-10,7, 12,2,54,39,-38, 37,54,4,-11,-8, -46,-10,5,-10,-34, 46,-12,29,-37,39, 36,-11,24,56,17, 14,20,25,0,-25, -28,55,-7,-5,27, 3,9,-26,-8,6, -24,-10,-30,-31,-34, 18,4,22,21,40, -1,-29,-37,-8,-21, 92,-29,11,-3,11, 73,23,22,7,4, -44,-9,-11,21,-13, 11,9,-78,-1,47, 114,-12,-37,-19,-5, -11,-22,19,12,-30, 7,38,45,-21,-8, -9,55,-45,56,-21, 7,17,46,-57,-87, -6,27,31,31,7, -56,-12,46,21,-5, -12,36,3,3,-21, 43,19,12,-7,9, -14,0,-9,-33,-91, 7,26,3,-11,64, 83,-31,-46,25,2, 9,5,2,2,-1, 20,-17,10,-5,-27, -8,20,8,-19,16, -21,-13,-31,5,5, 42,24,9,34,-20, 28,-61,22,11,-39, 64,-20,-1,-30,-9, -20,24,-25,-24,-29, 22,-60,6,-5,41, -9,-87,14,34,15, -57,52,69,15,-3, -102,58,16,3,6, 60,-75,-32,26,7, -57,-27,-32,-24,-21, -29,-16,62,-46,31, 30,-27,-15,7,15 }; /** * Excitation Codebook */ public static final int[] exc_5_64_table = { 1,5,-15,49,-66, -48,-4,50,-44,7, 37,16,-18,25,-26, -26,-15,19,19,-27, -47,28,57,5,-17, -32,-41,68,21,-2, 64,56,8,-16,-13, -26,-9,-16,11,6, -39,25,-19,22,-31, 20,-45,55,-43,10, -16,47,-40,40,-20, -51,3,-17,-14,-15, -24,53,-20,-46,46, 27,-68,32,3,-18, -5,9,-31,16,-9, -10,-1,-23,48,95, 47,25,-41,-32,-3, 15,-25,-55,36,41, -27,20,5,13,14, -22,5,2,-23,18, 46,-15,17,-18,-34, -5,-8,27,-55,73, 16,2,-1,-17,40, -78,33,0,2,19, 4,53,-16,-15,-16, -28,-3,-13,49,8, -7,-29,27,-13,32, 20,32,-61,16,14, 41,44,40,24,20, 7,4,48,-60,-77, 17,-6,-48,65,-15, 32,-30,-71,-10,-3, -6,10,-2,-7,-29, -56,67,-30,7,-5, 86,-6,-10,0,5, -31,60,34,-38,-3, 24,10,-2,30,23, 24,-41,12,70,-43, 15,-17,6,13,16, -13,8,30,-15,-8, 5,23,-34,-98,-4, -13,13,-48,-31,70, 12,31,25,24,-24, 26,-7,33,-16,8, 5,-11,-14,-8,-65, 13,10,-2,-9,0, -3,-68,5,35,7, 0,-31,-1,-17,-9, -9,16,-37,-18,-1, 69,-48,-28,22,-21, -11,5,49,55,23, -86,-36,16,2,13, 63,-51,30,-11,13, 24,-18,-6,14,-19, 1,41,9,-5,27, -36,-44,-34,-37,-21, -26,31,-39,15,43, 5,-8,29,20,-8, -20,-52,-28,-1,13, 26,-34,-10,-9,27, -8,8,27,-66,4, 12,-22,49,10,-77, 32,-18,3,-38,12, -3,-1,2,2,0 }; /** * Excitation Codebook */ public static final int[] exc_8_128_table = { -14,9,13,-32,2,-10,31,-10, -8,-8,6,-4,-1,10,-64,23, 6,20,13,6,8,-22,16,34, 7,42,-49,-28,5,26,4,-15, 41,34,41,32,33,24,23,14, 8,40,34,4,-24,-41,-19,-15, 13,-13,33,-54,24,27,-44,33, 27,-15,-15,24,-19,14,-36,14, -9,24,-12,-4,37,-5,16,-34, 5,10,33,-15,-54,-16,12,25, 12,1,2,0,3,-1,-4,-4, 11,2,-56,54,27,-20,13,-6, -46,-41,-33,-11,-5,7,12,14, -14,-5,8,20,6,3,4,-8, -5,-42,11,8,-14,25,-2,2, 13,11,-22,39,-9,9,5,-45, -9,7,-9,12,-7,34,-17,-102, 7,2,-42,18,35,-9,-34,11, -5,-2,3,22,46,-52,-25,-9, -94,8,11,-5,-5,-5,4,-7, -35,-7,54,5,-32,3,24,-9, -22,8,65,37,-1,-12,-23,-6, -9,-28,55,-33,14,-3,2,18, -60,41,-17,8,-16,17,-11,0, -11,29,-28,37,9,-53,33,-14, -9,7,-25,-7,-11,26,-32,-8, 24,-21,22,-19,19,-10,29,-14, -10,-4,-3,-2,3,-1,-4,-4, -5,-52,10,41,6,-30,-4,16, 32,22,-27,-22,32,-3,-28,-3, 3,-35,6,17,23,21,8,2, 4,-45,-17,14,23,-4,-31,-11, -3,14,1,19,-11,2,61,-8, 9,-12,7,-10,12,-3,-24,99, -48,23,50,-37,-5,-23,0,8, -14,35,-64,-5,46,-25,13,-1, -49,-19,-15,9,34,50,25,11, -6,-9,-16,-20,-32,-33,-32,-27, 10,-8,12,-15,56,-14,-32,33, 3,-9,1,65,-9,-9,-10,-2, -6,-23,9,17,3,-28,13,-32, 4,-2,-10,4,-16,76,12,-52, 6,13,33,-6,4,-14,-9,-3, 1,-15,-16,28,1,-15,11,16, 9,4,-21,-37,-40,-6,22,12, -15,-23,-14,-17,-16,-9,-10,-9, 13,-39,41,5,-9,16,-38,25, 46,-47,4,49,-14,17,-2,6, 18,5,-6,-33,-22,44,50,-2, 1,3,-6,7,7,-3,-21,38, -18,34,-14,-41,60,-13,6,16, -24,35,19,-13,-36,24,3,-17, -14,-10,36,44,-44,-29,-3,3, -54,-8,12,55,26,4,-2,-5, 2,-11,22,-23,2,22,1,-25, -39,66,-49,21,-8,-2,10,-14, -60,25,6,10,27,-25,16,5, -2,-9,26,-13,-20,58,-2,7, 52,-9,2,5,-4,-15,23,-1, -38,23,8,27,-6,0,-27,-7, 39,-10,-14,26,11,-45,-12,9, -5,34,4,-35,10,43,-22,-11, 56,-7,20,1,10,1,-26,9, 94,11,-27,-14,-13,1,-11,0, 14,-5,-6,-10,-4,-15,-8,-41, 21,-5,1,-28,-8,22,-9,33, -23,-4,-4,-12,39,4,-7,3, -60,80,8,-17,2,-6,12,-5, 1,9,15,27,31,30,27,23, 61,47,26,10,-5,-8,-12,-13, 5,-18,25,-15,-4,-15,-11,12, -2,-2,-16,-2,-6,24,12,11, -4,9,1,-9,14,-45,57,12, 20,-35,26,11,-64,32,-10,-10, 42,-4,-9,-16,32,24,7,10, 52,-11,-57,29,0,8,0,-6, 17,-17,-56,-40,7,20,18,12, -6,16,5,7,-1,9,1,10, 29,12,16,13,-2,23,7,9, -3,-4,-5,18,-64,13,55,-25, 9,-9,24,14,-25,15,-11,-40, -30,37,1,-19,22,-5,-31,13, -2,0,7,-4,16,-67,12,66, -36,24,-8,18,-15,-23,19,0, -45,-7,4,3,-13,13,35,5, 13,33,10,27,23,0,-7,-11, 43,-74,36,-12,2,5,-8,6, -33,11,-16,-14,-5,-7,-3,17, -34,27,-16,11,-9,15,33,-31, 8,-16,7,-6,-7,63,-55,-17, 11,-1,20,-46,34,-30,6,9, 19,28,-9,5,-24,-8,-23,-2, 31,-19,-16,-5,-15,-18,0,26, 18,37,-5,-15,-2,17,5,-27, 21,-33,44,12,-27,-9,17,11, 25,-21,-31,-7,13,33,-8,-25, -7,7,-10,4,-6,-9,48,-82, -23,-8,6,11,-23,3,-3,49, -29,25,31,4,14,16,9,-4, -18,10,-26,3,5,-44,-9,9, -47,-55,15,9,28,1,4,-3, 46,6,-6,-38,-29,-31,-15,-6, 3,0,14,-6,8,-54,-50,33, -5,1,-14,33,-48,26,-4,-5, -3,-5,-3,-5,-28,-22,77,55, -1,2,10,10,-9,-14,-66,-49, 11,-36,-6,-20,10,-10,16,12, 4,-1,-16,45,-44,-50,31,-2, 25,42,23,-32,-22,0,11,20, -40,-35,-40,-36,-32,-26,-21,-13, 52,-22,6,-24,-20,17,-5,-8, 36,-25,-11,21,-26,6,34,-8, 7,20,-3,5,-25,-8,18,-5, -9,-4,1,-9,20,20,39,48, -24,9,5,-65,22,29,4,3, -43,-11,32,-6,9,19,-27,-10, -47,-14,24,10,-7,-36,-7,-1, -4,-5,-5,16,53,25,-26,-29, -4,-12,45,-58,-34,33,-5,2, -1,27,-48,31,-15,22,-5,4, 7,7,-25,-3,11,-22,16,-12, 8,-3,7,-11,45,14,-73,-19, 56,-46,24,-20,28,-12,-2,-1, -36,-3,-33,19,-6,7,2,-15, 5,-31,-45,8,35,13,20,0, -9,48,-13,-43,-3,-13,2,-5, 72,-68,-27,2,1,-2,-7,5, 36,33,-40,-12,-4,-5,23,19 }; /** * Gain Codebook (narrowband) */ public static final int[] gain_cdbk_nb = { //384 -32,-32,-32, -28,-67,-5, -42,-6,-32, -57,-10,-54, -16,27,-41, 19,-19,-40, -45,24,-21, -8,-14,-18, 1,14,-58, -18,-88,-39, -38,21,-18, -19,20,-43, 10,17,-48, -52,-58,-13, -44,-1,-11, -12,-11,-34, 14,0,-46, -37,-35,-34, -25,44,-30, 6,-4,-63, -31,43,-41, -23,30,-43, -43,26,-14, -33,1,-13, -13,18,-37, -46,-73,-45, -36,24,-25, -36,-11,-20, -25,12,-18, -36,-69,-59, -45,6,8, -22,-14,-24, -1,13,-44, -39,-48,-26, -32,31,-37, -33,15,-46, -24,30,-36, -41,31,-23, -50,22,-4, -22,2,-21, -17,30,-34, -7,-60,-28, -38,42,-28, -44,-11,21, -16,8,-44, -39,-55,-43, -11,-35,26, -9,0,-34, -8,121,-81, 7,-16,-22, -37,33,-31, -27,-7,-36, -34,70,-57, -37,-11,-48, -40,17,-1, -33,6,-6, -9,0,-20, -21,69,-33, -29,33,-31, -55,12,-1, -33,27,-22, -50,-33,-47, -50,54,51, -1,-5,-44, -4,22,-40, -39,-66,-25, -33,1,-26, -24,-23,-25, -11,21,-45, -25,-45,-19, -43,105,-16, 5,-21,1, -16,11,-33, -13,-99,-4, -37,33,-15, -25,37,-63, -36,24,-31, -53,-56,-38, -41,-4,4, -33,13,-30, 49,52,-94, -5,-30,-15, 1,38,-40, -23,12,-36, -17,40,-47, -37,-41,-39, -49,34,0, -18,-7,-4, -16,17,-27, 30,5,-62, 4,48,-68, -43,11,-11, -18,19,-15, -23,-62,-39, -42,10,-2, -21,-13,-13, -9,13,-47, -23,-62,-24, -44,60,-21, -18,-3,-52, -22,22,-36, -75,57,16, -19,3,10, -29,23,-38, -5,-62,-51, -51,40,-18, -42,13,-24, -34,14,-20, -56,-75,-26, -26,32,15, -26,17,-29, -7,28,-52, -12,-30,5, -5,-48,-5, 2,2,-43, 21,16,16, -25,-45,-32, -43,18,-10, 9,0,-1, -1,7,-30, 19,-48,-4, -28,25,-29, -22,0,-31, -32,17,-10, -64,-41,-62, -52,15,16, -30,-22,-32, -7,9,-38 }; /** * Gain Codebook (LBR) */ public static final int[] gain_cdbk_lbr = { //96 -32,-32,-32, -31,-58,-16, -41,-24,-43, -56,-22,-55, -13,33,-41, -4,-39,-9, -41,15,-12, -8,-15,-12, 1,2,-44, -22,-66,-42, -38,28,-23, -21,14,-37, 0,21,-50, -53,-71,-27, -37,-1,-19, -19,-5,-28, 6,65,-44, -33,-48,-33, -40,57,-14, -17,4,-45, -31,38,-33, -23,28,-40, -43,29,-12, -34,13,-23, -16,15,-27, -14,-82,-15, -31,25,-32, -21,5,-5, -47,-63,-51, -46,12,3, -28,-17,-29, -10,14,-40 }; /** * Excitation Codebook */ public static final int[] hexc_10_32_table = { -3, -2, -1, 0, -4, 5, 35, -40, -9, 13, -44, 5, -27, -1, -7, 6, -11, 7, -8, 7, 19, -14, 15, -4, 9, -10, 10, -8, 10, -9, -1, 1, 0, 0, 2, 5, -18, 22, -53, 50, 1, -23, 50, -36, 15, 3, -13, 14, -10, 6, 1, 5, -3, 4, -2, 5, -32, 25, 5, -2, -1, -4, 1, 11, -29, 26, -6, -15, 30, -18, 0, 15, -17, 40, -41, 3, 9, -2, -2, 3, -3, -1, -5, 2, 21, -6, -16, -21, 23, 2, 60, 15, 16, -16, -9, 14, 9, -1, 7, -9, 0, 1, 1, 0, -1, -6, 17, -28, 54, -45, -1, 1, -1, -6, -6, 2, 11, 26, -29, -2, 46, -21, 34, 12, -23, 32, -23, 16, -10, 3, 66, 19, -20, 24, 7, 11, -3, 0, -3, -1, -50, -46, 2, -18, -3, 4, -1, -2, 3, -3, -19, 41, -36, 9, 11, -24, 21, -16, 9, -3, -25, -3, 10, 18, -9, -2, -5, -1, -5, 6, -4, -3, 2, -26, 21, -19, 35, -15, 7, -13, 17, -19, 39, -43, 48, -31, 16, -9, 7, -2, -5, 3, -4, 9, -19, 27, -55, 63, -35, 10, 26, -44, -2, 9, 4, 1, -6, 8, -9, 5, -8, -1, -3, -16, 45, -42, 5, 15, -16, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -16, 24, -55, 47, -38, 27, -19, 7, -3, 1, 16, 27, 20, -19, 18, 5, -7, 1, -5, 2, -6, 8, -22, 0, -3, -3, 8, -1, 7, -8, 1, -3, 5, 0, 17, -48, 58, -52, 29, -7, -2, 3, -10, 6, -26, 58, -31, 1, -6, 3, 93, -29, 39, 3, 17, 5, 6, -1, -1, -1, 27, 13, 10, 19, -7, -34, 12, 10, -4, 9, -76, 9, 8, -28, -2, -11, 2, -1, 3, 1, -83, 38, -39, 4, -16, -6, -2, -5, 5, -2, }; /** * Excitation Codebook */ public static final int[] hexc_table = { //1024 -24, 21, -20, 5, -5, -7, 14, -10, 2, -27, 16, -20, 0, -32, 26, 19, 8, -11, -41, 31, 28, -27, -32, 34, 42, 34, -17, 22, -10, 13, -29, 18, -12, -26, -24, 11, 22, 5, -5, -5, 54, -68, -43, 57, -25, 24, 4, 4, 26, -8, -12, -17, 54, 30, -45, 1, 10, -15, 18, -41, 11, 68, -67, 37, -16, -24, -16, 38, -22, 6, -29, 30, 66, -27, 5, 7, -16, 13, 2, -12, -7, -3, -20, 36, 4, -28, 9, 3, 32, 48, 26, 39, 3, 0, 7, -21, -13, 5, -82, -7, 73, -20, 34, -9, -5, 1, -1, 10, -5, -10, -1, 9, 1, -9, 10, 0, -14, 11, -1, -2, -1, 11, 20, 96, -81, -22, -12, -9, -58, 9, 24, -30, 26, -35, 27, -12, 13, -18, 56, -59, 15, -7, 23, -15, -1, 6, -25, 14, -22, -20, 47, -11, 16, 2, 38, -23, -19, -30, -9, 40, -11, 5, 4, -6, 8, 26, -21, -11, 127, 4, 1, 6, -9, 2, -7, -2, -3, 7, -5, 10, -19, 7, -106, 91, -3, 9, -4, 21, -8, 26, -80, 8, 1, -2, -10, -17, -17, -27, 32, 71, 6, -29, 11, -23, 54, -38, 29, -22, 39, 87, -31, -12, -20, 3, -2, -2, 2, 20, 0, -1, -35, 27, 9, -6, -12, 3, -12, -6, 13, 1, 14, -22, -59, -15, -17, -25, 13, -7, 7, 3, 0, 1, -7, 6, -3, 61, -37, -23, -23, -29, 38, -31, 27, 1, -8, 2, -27, 23, -26, 36, -34, 5, 24, -24, -6, 7, 3, -59, 78, -62, 44, -16, 1, 6, 0, 17, 8, 45, 0, -110, 6, 14, -2, 32, -77, -56, 62, -3, 3, -13, 4, -16, 102, -15, -36, -1, 9, -113, 6, 23, 0, 9, 9, 5, -8, -1, -14, 5, -12, 121, -53, -27, -8, -9, 22, -13, 3, 2, -3, 1, -2, -71, 95, 38, -19, 15, -16, -5, 71, 10, 2, -32, -13, -5, 15, -1, -2, -14, -85, 30, 29, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, -65, -56, -9, 18, 18, 23, -14, -2, 0, 12, -29, 26, -12, 1, 2, -12, -64, 90, -6, 4, 1, 5, -5, -110, -3, -31, 22, -29, 9, 0, 8, -40, -5, 21, -5, -5, 13, 10, -18, 40, 1, 35, -20, 30, -28, 11, -6, 19, 7, 14, 18, -64, 9, -6, 16, 51, 68, 8, 16, 12, -8, 0, -9, 20, -22, 25, 7, -4, -13, 41, -35, 93, -18, -54, 11, -1, 1, -9, 4, -66, 66, -31, 20, -22, 25, -23, 11, 10, 9, 19, 15, 11, -5, -31, -10, -23, -28, -6, -6, -3, -4, 5, 3, -28, 22, -11, -42, 25, -25, -16, 41, 34, 47, -6, 2, 42, -19, -22, 5, -39, 32, 6, -35, 22, 17, -30, 8, -26, -11, -11, 3, -12, 33, 33, -37, 21, -1, 6, -4, 3, 0, -5, 5, 12, -12, 57, 27, -61, -3, 20, -17, 2, 0, 4, 0, -2, -33, -58, 81, -23, 39, -10, -5, 2, 6, -7, 5, 4, -3, -2, -13, -23, -72, 107, 15, -5, 0, -7, -3, -6, 5, -4, 15, 47, 12, -31, 25, -16, 8, 22, -25, -62, -56, -18, 14, 28, 12, 2, -11, 74, -66, 41, -20, -7, 16, -20, 16, -8, 0, -16, 4, -19, 92, 12, -59, -14, -39, 49, -25, -16, 23, -27, 19, -3, -33, 19, 85, -29, 6, -7, -10, 16, -7, -12, 1, -6, 2, 4, -2, 64, 10, -25, 41, -2, -31, 15, 0, 110, 50, 69, 35, 28, 19, -10, 2, -43, -49, -56, -15, -16, 10, 3, 12, -1, -8, 1, 26, -12, -1, 7, -11, -27, 41, 25, 1, -11, -18, 22, -7, -1, -47, -8, 23, -3, -17, -7, 18, -125, 59, -5, 3, 18, 1, 2, 3, 27, -35, 65, -53, 50, -46, 37, -21, -28, 7, 14, -37, -5, -5, 12, 5, -8, 78, -19, 21, -6, -16, 8, -7, 5, 2, 7, 2, 10, -6, 12, -60, 44, 11, -36, -32, 31, 0, 2, -2, 2, 1, -3, 7, -10, 17, -21, 10, 6, -2, 19, -2, 59, -38, -86, 38, 8, -41, -30, -45, -33, 7, 15, 28, 29, -7, 24, -40, 7, 7, 5, -2, 9, 24, -23, -18, 6, -29, 30, 2, 28, 49, -11, -46, 10, 43, -13, -9, -1, -3, -7, -7, -17, -6, 97, -33, -21, 3, 5, 1, 12, -43, -8, 28, 7, -43, -7, 17, -20, 19, -1, 2, -13, 9, 54, 34, 9, -28, -11, -9, -17, 110, -59, 44, -26, 0, 3, -12, -47, 73, -34, -43, 38, -33, 16, -5, -46, -4, -6, -2, -25, 19, -29, 28, -13, 5, 14, 27, -40, -43, 4, 32, -13, -2, -35, -4, 112, -42, 9, -12, 37, -28, 17, 14, -19, 35, -39, 23, 3, -14, -1, -57, -5, 94, -9, 3, -39, 5, 30, -10, -32, 42, -13, -14, -97, -63, 30, -9, 1, -7, 12, 5, 20, 17, -9, -36, -30, 25, 47, -9, -15, 12, -22, 98, -8, -50, 15, -27, 21, -16, -11, 2, 12, -10, 10, -3, 33, 36, -96, 0, -17, 31, -9, 9, 3, -20, 13, -11, 8, -4, 10, -10, 9, 1, 112, -70, -27, 5, -21, 2, -57, -3, -29, 10, 19, -21, 21, -10, -66, -3, 91, -35, 30, -12, 0, -7, 59, -28, 26, 2, 14, -18, 1, 1, 11, 17, 20, -54, -59, 27, 4, 29, 32, 5, 19, 12, -4, 1, 7, -10, 5, -2, 10, 0, 23, -5, 28, -104, 46, 11, 16, 3, 29, 1, -8, -14, 1, 7, -50, 88, -62, 26, 8, -17, -14, 50, 0, 32, -12, -3, -27, 18, -8, -5, 8, 3, -20, -11, 37, -12, 9, 33, 46, -101, -1, -4, 1, 6, -1, 28, -42, -15, 16, 5, -1, -2, -55, 85, 38, -9, -4, 11, -2, -9, -6, 3, -20, -10, -77, 89, 24, -3, -104, -57, -26, -31, -20, -6, -9, 14, 20, -23, 46, -15, -31, 28, 1, -15, -2, 6, -2, 31, 45, -76, 23, -25, }; /** * LSP Codebook (high) */ public static final int[] high_lsp_cdbk = { //512 39,12,-14,-20,-29,-61,-67,-76, -32,-71,-67,68,77,46,34,5, -13,-48,-46,-72,-81,-84,-60,-58, -40,-28,82,93,68,45,29,3, -19,-47,-28,-43,-35,-30,-8,-13, -39,-91,-91,-123,-96,10,10,-6, -18,-55,-60,-91,-56,-36,-27,-16, -48,-75,40,28,-10,-28,35,9, 37,19,1,-20,-31,-41,-18,-25, -35,-68,-80,45,27,-1,47,13, 0,-29,-35,-57,-50,-79,-73,-38, -19,5,35,14,-10,-23,16,-8, 5,-24,-40,-62,-23,-27,-22,-16, -18,-46,-72,-77,43,21,33,1, -80,-70,-70,-64,-56,-52,-39,-33, -31,-38,-19,-19,-15,32,33,-2, 7,-15,-15,-24,-23,-33,-41,-56, -24,-57,5,89,64,41,27,5, -9,-47,-60,-97,-97,-124,-20,-9, -44,-73,31,29,-4,64,48,7, -35,-57,0,-3,-26,-47,-3,-6, -40,-76,-79,-48,12,81,55,10, 9,-24,-43,-73,-57,-69,16,5, -28,-53,18,29,20,0,-4,-11, 6,-13,23,7,-17,-35,-37,-37, -30,-68,-63,6,24,-9,-14,3, 21,-13,-27,-57,-49,-80,-24,-41, -5,-16,-5,1,45,25,12,-7, 3,-15,-6,-16,-15,-8,6,-13, -42,-81,-80,-87,14,1,-10,-3, -43,-69,-46,-24,-28,-29,36,6, -43,-56,-12,12,54,79,43,9, 54,22,2,8,-12,-43,-46,-52, -38,-69,-89,-5,75,38,33,5, -13,-53,-62,-87,-89,-113,-99,-55, -34,-37,62,55,33,16,21,-2, -17,-46,-29,-38,-38,-48,-39,-42, -36,-75,-72,-88,-48,-30,21,2, -15,-57,-64,-98,-84,-76,25,1, -46,-80,-12,18,-7,3,34,6, 38,31,23,4,-1,20,14,-15, -43,-78,-91,-24,14,-3,54,16, 0,-27,-28,-44,-56,-83,-92,-89, -3,34,56,41,36,22,20,-8, -7,-35,-42,-62,-49,3,12,-10, -50,-87,-96,-66,92,70,38,9, -70,-71,-62,-42,-39,-43,-11,-7, -50,-79,-58,-50,-31,32,31,-6, -4,-25,7,-17,-38,-70,-58,-27, -43,-83,-28,59,36,20,31,2, -27,-71,-80,-109,-98,-75,-33,-32, -31,-2,33,15,-6,43,33,-5, 0,-22,-10,-27,-34,-49,-11,-20, -41,-91,-100,-121,-39,57,41,10, -19,-50,-38,-59,-60,-70,-18,-20, -8,-31,-8,-15,1,-14,-26,-25, 33,21,32,17,1,-19,-19,-26, -58,-81,-35,-22,45,30,11,-11, 3,-26,-48,-87,-67,-83,-58,3, -1,-26,-20,44,10,25,39,5, -9,-35,-27,-38,7,10,4,-9, -42,-85,-102,-127,52,44,28,10, -47,-61,-40,-39,-17,-1,-10,-33, -42,-74,-48,21,-4,70,52,10 }; /** * LSP Codebook (high) */ public static final int[] high_lsp_cdbk2 = { //512 -36,-62,6,-9,-10,-14,-56,23, 1,-26,23,-48,-17,12,8,-7, 23,29,-36,-28,-6,-29,-17,-5, 40,23,10,10,-46,-13,36,6, 4,-30,-29,62,32,-32,-1,22, -14,1,-4,-22,-45,2,54,4, -30,-57,-59,-12,27,-3,-31,8, -9,5,10,-14,32,66,19,9, 2,-25,-37,23,-15,18,-38,-31, 5,-9,-21,15,0,22,62,30, 15,-12,-14,-46,77,21,33,3, 34,29,-19,50,2,11,9,-38, -12,-37,62,1,-15,54,32,6, 2,-24,20,35,-21,2,19,24, -13,55,4,9,39,-19,30,-1, -21,73,54,33,8,18,3,15, 6,-19,-47,6,-3,-48,-50,1, 26,20,8,-23,-50,65,-14,-55, -17,-31,-37,-28,53,-1,-17,-53, 1,57,11,-8,-25,-30,-37,64, 5,-52,-45,15,23,31,15,14, -25,24,33,-2,-44,-56,-18,6, -21,-43,4,-12,17,-37,20,-10, 34,15,2,15,55,21,-11,-31, -6,46,25,16,-9,-25,-8,-62, 28,17,20,-32,-29,26,30,25, -19,2,-16,-17,26,-51,2,50, 42,19,-66,23,29,-2,3,19, -19,-37,32,15,6,30,-34,13, 11,-5,40,31,10,-42,4,-9, 26,-9,-70,17,-2,-23,20,-22, -55,51,-24,-31,22,-22,15,-13, 3,-10,-28,-16,56,4,-63,11, -18,-15,-18,-38,-35,16,-7,34, -1,-21,-49,-47,9,-37,7,8, 69,55,20,6,-33,-45,-10,-9, 6,-9,12,71,15,-3,-42,-7, -24,32,-35,-2,-42,-17,-5,0, -2,-33,-54,13,-12,-34,47,23, 19,55,7,-8,74,31,14,16, -23,-26,19,12,-18,-49,-28,-31, -20,2,-14,-20,-47,78,40,13, -23,-11,21,-6,18,1,47,5, 38,35,32,46,22,8,13,16, -14,18,51,19,40,39,11,-26, -1,-17,47,2,-53,-15,31,-22, 38,21,-15,-16,5,-33,53,15, -38,86,11,-3,-24,49,13,-4, -11,-18,28,20,-12,-27,-26,35, -25,-35,-3,-20,-61,30,10,-55, -12,-22,-52,-54,-14,19,-32,-12, 45,15,-8,-48,-9,11,-32,8, -16,-34,-13,51,18,38,-2,-32, -17,22,-2,-18,-28,-70,59,27, -28,-19,-10,-20,-9,-9,-8,-21, 21,-8,35,-2,45,-3,-9,12, 0,30,7,-39,43,27,-38,-91, 30,26,19,-55,-4,63,14,-17, 13,9,13,2,7,4,6,61, 72,-1,-17,29,-1,-22,-17,8, -28,-37,63,44,41,3,2,14, 9,-6,75,-8,-7,-12,-15,-12, 13,9,-4,30,-22,-65,15,0, -45,4,-4,1,5,22,11,23 }; /** */ public static final int NB_CDBK_SIZE = 64; /** */ public static final int NB_CDBK_SIZE_LOW1 = 64; /** */ public static final int NB_CDBK_SIZE_LOW2 = 64; /** */ public static final int NB_CDBK_SIZE_HIGH1 = 64; /** */ public static final int NB_CDBK_SIZE_HIGH2 = 64; /** * Codebook (narrowband) */ public static final int[] cdbk_nb = { //640 30,19,38,34,40,32,46,43,58,43, 5,-18,-25,-40,-33,-55,-52,20,34,28, -20,-63,-97,-92,61,53,47,49,53,75, -14,-53,-77,-79,0,-3,-5,19,22,26, -9,-53,-55,66,90,72,85,68,74,52, -4,-41,-58,-31,-18,-31,27,32,30,18, 24,3,8,5,-12,-3,26,28,74,63, -2,-39,-67,-77,-106,-74,59,59,73,65, 44,40,71,72,82,83,98,88,89,60, -6,-31,-47,-48,-13,-39,-9,7,2,79, -1,-39,-60,-17,87,81,65,50,45,19, -21,-67,-91,-87,-41,-50,7,18,39,74, 10,-31,-28,39,24,13,23,5,56,45, 29,10,-5,-13,-11,-35,-18,-8,-10,-8, -25,-71,-77,-21,2,16,50,63,87,87, 5,-32,-40,-51,-68,0,12,6,54,34, 5,-12,32,52,68,64,69,59,65,45, 14,-16,-31,-40,-65,-67,41,49,47,37, -11,-52,-75,-84,-4,57,48,42,42,33, -11,-51,-68,-6,13,0,8,-8,26,32, -23,-53,0,36,56,76,97,105,111,97, -1,-28,-39,-40,-43,-54,-44,-40,-18,35, 16,-20,-19,-28,-42,29,47,38,74,45, 3,-29,-48,-62,-80,-104,-33,56,59,59, 10,17,46,72,84,101,117,123,123,106, -7,-33,-49,-51,-70,-67,-27,-31,70,67, -16,-62,-85,-20,82,71,86,80,85,74, -19,-58,-75,-45,-29,-33,-18,-25,45,57, -12,-42,-5,12,28,36,52,64,81,82, 13,-9,-27,-28,22,3,2,22,26,6, -6,-44,-51,2,15,10,48,43,49,34, -19,-62,-84,-89,-102,-24,8,17,61,68, 39,24,23,19,16,-5,12,15,27,15, -8,-44,-49,-60,-18,-32,-28,52,54,62, -8,-48,-77,-70,66,101,83,63,61,37, -12,-50,-75,-64,33,17,13,25,15,77, 1,-42,-29,72,64,46,49,31,61,44, -8,-47,-54,-46,-30,19,20,-1,-16,0, 16,-12,-18,-9,-26,-27,-10,-22,53,45, -10,-47,-75,-82,-105,-109,8,25,49,77, 50,65,114,117,124,118,115,96,90,61, -9,-45,-63,-60,-75,-57,8,11,20,29, 0,-35,-49,-43,40,47,35,40,55,38, -24,-76,-103,-112,-27,3,23,34,52,75, 8,-29,-43,12,63,38,35,29,24,8, 25,11,1,-15,-18,-43,-7,37,40,21, -20,-56,-19,-19,-4,-2,11,29,51,63, -2,-44,-62,-75,-89,30,57,51,74,51, 50,46,68,64,65,52,63,55,65,43, 18,-9,-26,-35,-55,-69,3,6,8,17, -15,-61,-86,-97,1,86,93,74,78,67, -1,-38,-66,-48,48,39,29,25,17,-1, 13,13,29,39,50,51,69,82,97,98, -2,-36,-46,-27,-16,-30,-13,-4,-7,-4, 25,-5,-11,-6,-25,-21,33,12,31,29, -8,-38,-52,-63,-68,-89,-33,-1,10,74, -2,-15,59,91,105,105,101,87,84,62, -7,-33,-50,-35,-54,-47,25,17,82,81, -13,-56,-83,21,58,31,42,25,72,65, -24,-66,-91,-56,9,-2,21,10,69,75, 2,-24,11,22,25,28,38,34,48,33, 7,-29,-26,17,15,-1,14,0,-2,0, -6,-41,-67,6,-2,-9,19,2,85,74, -22,-67,-84,-71,-50,3,11,-9,2,62 }; /** * Codebook (narrowband) */ public static final int[] cdbk_nb_low1 = { //320 -34,-52,-15,45,2, 23,21,52,24,-33, -9,-1,9,-44,-41, -13,-17,44,22,-17, -6,-4,-1,22,38, 26,16,2,50,27, -35,-34,-9,-41,6, 0,-16,-34,51,8, -14,-31,-49,15,-33, 45,49,33,-11,-37, -62,-54,45,11,-5, -72,11,-1,-12,-11, 24,27,-11,-43,46, 43,33,-12,-9,-1, 1,-4,-23,-57,-71, 11,8,16,17,-8, -20,-31,-41,53,48, -16,3,65,-24,-8, -23,-32,-37,-32,-49, -10,-17,6,38,5, -9,-17,-46,8,52, 3,6,45,40,39, -7,-6,-34,-74,31, 8,1,-16,43,68, -11,-19,-31,4,6, 0,-6,-17,-16,-38, -16,-30,2,9,-39, -16,-1,43,-10,48, 3,3,-16,-31,-3, 62,68,43,13,3, -10,8,20,-56,12, 12,-2,-18,22,-15, -40,-36,1,7,41, 0,1,46,-6,-62, -4,-12,-2,-11,-83, -13,-2,91,33,-10, 0,4,-11,-16,79, 32,37,14,9,51, -21,-28,-56,-34,0, 21,9,-26,11,28, -42,-54,-23,-2,-15, 31,30,8,-39,-66, -39,-36,31,-28,-40, -46,35,40,22,24, 33,48,23,-34,14, 40,32,17,27,-3, 25,26,-13,-61,-17, 11,4,31,60,-6, -26,-41,-64,13,16, -26,54,31,-11,-23, -9,-11,-34,-71,-21, -34,-35,55,50,29, -22,-27,-50,-38,57, 33,42,57,48,26, 11,0,-49,-31,26, -4,-14,5,78,37, 17,0,-49,-12,-23, 26,14,2,2,-43, -17,-12,10,-8,-4, 8,18,12,-6,20, -12,-6,-13,-25,34, 15,40,49,7,8, 13,20,20,-19,-22, -2,-8,2,51,-51 }; /** * Codebook (narrowband) */ public static final int[] cdbk_nb_low2 = { //320 -6,53,-21,-24,4, 26,17,-4,-37,25, 17,-36,-13,31,3, -6,27,15,-10,31, 28,26,-10,-10,-40, 16,-7,15,13,41, -9,0,-4,50,-6, -7,14,38,22,0, -48,2,1,-13,-19, 32,-3,-60,11,-17, -1,-24,-34,-1,35, -5,-27,28,44,13, 25,15,42,-11,15, 51,35,-36,20,8, -4,-12,-29,19,-47, 49,-15,-4,16,-29, -39,14,-30,4,25, -9,-5,-51,-14,-3, -40,-32,38,5,-9, -8,-4,-1,-22,71, -3,14,26,-18,-22, 24,-41,-25,-24,6, 23,19,-10,39,-26, -27,65,45,2,-7, -26,-8,22,-12,16, 15,16,-35,-5,33, -21,-8,0,23,33, 34,6,21,36,6, -7,-22,8,-37,-14, 31,38,11,-4,-3, -39,-32,-8,32,-23, -6,-12,16,20,-28, -4,23,13,-52,-1, 22,6,-33,-40,-6, 4,-62,13,5,-26, 35,39,11,2,57, -11,9,-20,-28,-33, 52,-5,-6,-2,22, -14,-16,-48,35,1, -58,20,13,33,-1, -74,56,-18,-22,-31, 12,6,-14,4,-2, -9,-47,10,-3,29, -17,-5,61,14,47, -12,2,72,-39,-17, 92,64,-53,-51,-15, -30,-38,-41,-29,-28, 27,9,36,9,-35, -42,81,-21,20,25, -16,-5,-17,-35,21, 15,-28,48,2,-2, 9,-19,29,-40,30, -18,-18,18,-16,-57, 15,-20,-12,-15,-37, -15,33,-39,21,-22, -13,35,11,13,-38, -63,29,23,-27,32, 18,3,-26,42,33, -64,-66,-17,16,56, 2,36,3,31,21, -41,-39,8,-57,14, 37,-2,19,-36,-19, -23,-29,-16,1,-3, -8,-10,31,64,-65 }; /** * Codebook (narrowband) */ public static final int[] cdbk_nb_high1 = { //320 -26,-8,29,21,4, 19,-39,33,-7,-36, 56,54,48,40,29, -4,-24,-42,-66,-43, -60,19,-2,37,41, -10,-37,-60,-64,18, -22,77,73,40,25, 4,19,-19,-66,-2, 11,5,21,14,26, -25,-86,-4,18,1, 26,-37,10,37,-1, 24,-12,-59,-11,20, -6,34,-16,-16,42, 19,-28,-51,53,32, 4,10,62,21,-12, -34,27,4,-48,-48, -50,-49,31,-7,-21, -42,-25,-4,-43,-22, 59,2,27,12,-9, -6,-16,-8,-32,-58, -16,-29,-5,41,23, -30,-33,-46,-13,-10, -38,52,52,1,-17, -9,10,26,-25,-6, 33,-20,53,55,25, -32,-5,-42,23,21, 66,5,-28,20,9, 75,29,-7,-42,-39, 15,3,-23,21,6, 11,1,-29,14,63, 10,54,26,-24,-51, -49,7,-23,-51,15, -66,1,60,25,10, 0,-30,-4,-15,17, 19,59,40,4,-5, 33,6,-22,-58,-70, -5,23,-6,60,44, -29,-16,-47,-29,52, -19,50,28,16,35, 31,36,0,-21,6, 21,27,22,42,7, -66,-40,-8,7,19, 46,0,-4,60,36, 45,-7,-29,-6,-32, -39,2,6,-9,33, 20,-51,-34,18,-6, 19,6,11,5,-19, -29,-2,42,-11,-45, -21,-55,57,37,2, -14,-67,-16,-27,-38, 69,48,19,2,-17, 20,-20,-16,-34,-17, -25,-61,10,73,45, 16,-40,-64,-17,-29, -22,56,17,-39,8, -11,8,-25,-18,-13, -19,8,54,57,36, -17,-26,-4,6,-21, 40,42,-4,20,31, 53,10,-34,-53,31, -17,35,0,15,-6, -20,-63,-73,22,25, 29,17,8,-29,-39, -69,18,15,-15,-5 }; /** * Codebook (narrowband) */ public static final int[] cdbk_nb_high2 = { //320 11,47,16,-9,-46, -32,26,-64,34,-5, 38,-7,47,20,2, -73,-99,-3,-45,20, 70,-52,15,-6,-7, -82,31,21,47,51, 39,-3,9,0,-41, -7,-15,-54,2,0, 27,-31,9,-45,-22, -38,-24,-24,8,-33, 23,5,50,-36,-17, -18,-51,-2,13,19, 43,12,-15,-12,61, 38,38,7,13,0, 6,-1,3,62,9, 27,22,-33,38,-35, -9,30,-43,-9,-32, -1,4,-4,1,-5, -11,-8,38,31,11, -10,-42,-21,-37,1, 43,15,-13,-35,-19, -18,15,23,-26,59, 1,-21,53,8,-41, -50,-14,-28,4,21, 25,-28,-40,5,-40, -41,4,51,-33,-8, -8,1,17,-60,12, 25,-41,17,34,43, 19,45,7,-37,24, -15,56,-2,35,-10, 48,4,-47,-2,5, -5,-54,5,-3,-33, -10,30,-2,-44,-24, -38,9,-9,42,4, 6,-56,44,-16,9, -40,-26,18,-20,10, 28,-41,-21,-4,13, -18,32,-30,-3,37, 15,22,28,50,-40, 3,-29,-64,7,51, -19,-11,17,-27,-40, -64,24,-12,-7,-27, 3,37,48,-1,2, -9,-38,-34,46,1, 27,-6,19,-13,26, 10,34,20,25,40, 50,-6,-7,30,9, -24,0,-23,71,-61, 22,58,-34,-4,2, -49,-33,25,30,-8, -6,-16,77,2,38, -8,-35,-6,-30,56, 78,31,33,-20,13, -39,20,22,4,21, -8,4,-6,10,-83, -41,9,-25,-43,15, -7,-12,-34,-39,-37, -33,19,30,16,-33, 42,-25,25,-68,44, -15,-11,-4,23,50, 14,4,-39,-43,20, -30,60,9,-20,7, 16,19,-33,37,29, 16,-35,7,38,-27 }; /** * QMF (Quadratic Mirror Filter) table */ public static final float[] h0 = { 3.596189e-05f, -0.0001123515f, -0.0001104587f, 0.0002790277f, 0.0002298438f, -0.0005953563f, -0.0003823631f, 0.00113826f, 0.0005308539f, -0.001986177f, -0.0006243724f, 0.003235877f, 0.0005743159f, -0.004989147f, -0.0002584767f, 0.007367171f, -0.0004857935f, -0.01050689f, 0.001894714f, 0.01459396f, -0.004313674f, -0.01994365f, 0.00828756f, 0.02716055f, -0.01485397f, -0.03764973f, 0.026447f, 0.05543245f, -0.05095487f, -0.09779096f, 0.1382363f, 0.4600981f, 0.4600981f, 0.1382363f, -0.09779096f, -0.05095487f, 0.05543245f, 0.026447f, -0.03764973f, -0.01485397f, 0.02716055f, 0.00828756f, -0.01994365f, -0.004313674f, 0.01459396f, 0.001894714f, -0.01050689f, -0.0004857935f, 0.007367171f, -0.0002584767f, -0.004989147f, 0.0005743159f, 0.003235877f, -0.0006243724f, -0.001986177f, 0.0005308539f, 0.00113826f, -0.0003823631f, -0.0005953563f, 0.0002298438f, 0.0002790277f, -0.0001104587f, -0.0001123515f, 3.596189e-05f }; /** * QMF (Quadratic Mirror Filter) table */ public static final float[] h1 = { 3.596189e-05f, 0.0001123515f, -0.0001104587f, -0.0002790277f, 0.0002298438f, 0.0005953563f, -0.0003823631f, -0.00113826f, 0.0005308539f, 0.001986177f, -0.0006243724f, -0.003235877f, 0.0005743159f, 0.004989147f, -0.0002584767f, -0.007367171f, -0.0004857935f, 0.01050689f, 0.001894714f, -0.01459396f, -0.004313674f, 0.01994365f, 0.00828756f, -0.02716055f, -0.01485397f, 0.03764973f, 0.026447f, -0.05543245f, -0.05095487f, 0.09779096f, 0.1382363f, -0.4600981f, 0.4600981f, -0.1382363f, -0.09779096f, 0.05095487f, 0.05543245f, -0.026447f, -0.03764973f, 0.01485397f, 0.02716055f, -0.00828756f, -0.01994365f, 0.004313674f, 0.01459396f, -0.001894714f, -0.01050689f, 0.0004857935f, 0.007367171f, 0.0002584767f, -0.004989147f, -0.0005743159f, 0.003235877f, 0.0006243724f, -0.001986177f, -0.0005308539f, 0.00113826f, 0.0003823631f, -0.0005953563f, -0.0002298438f, 0.0002790277f, 0.0001104587f, -0.0001123515f, -3.596189e-05f }; } jspeex/src/java/org/xiph/speex/Decoder.java0000644000175000017500000001472510135761046021131 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Decoder.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: Decoder.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; import java.io.StreamCorruptedException; /** * Speex Decoder inteface, used as a base for the Narrowband and sideband * decoders. * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public interface Decoder { /** * Decode the given input bits. * @param bits - Speex bits buffer. * @param out - the decoded mono audio frame. * @return 1 if a terminator was found, 0 if not. * @throws StreamCorruptedException If there is an error detected in the * data stream. */ public int decode(Bits bits, float[] out) throws StreamCorruptedException; /** * Decode the given bits to stereo. * @param data - float array of size 2*frameSize, that contains the mono * audio samples in the first half. When the function has completed, the * array will contain the interlaced stereo audio samples. * @param frameSize - the size of a frame of mono audio samples. */ public void decodeStereo(float[] data, int frameSize); /** * Enables or disables perceptual enhancement. * @param enhanced */ public void setPerceptualEnhancement(boolean enhanced); /** * Returns whether perceptual enhancement is enabled or disabled. * @return whether perceptual enhancement is enabled or disabled. */ public boolean getPerceptualEnhancement(); /** * Returns the size of a frame. * @return the size of a frame. */ public int getFrameSize(); /** * Returns whether or not we are using Discontinuous Transmission encoding. * @return whether or not we are using Discontinuous Transmission encoding. */ public boolean getDtx(); /** * Returns the Pitch Gain array. * @return the Pitch Gain array. */ public float[] getPiGain(); /** * Returns the excitation array. * @return the excitation array. */ public float[] getExc(); /** * Returns the innovation array. * @return the innovation array. */ public float[] getInnov(); } jspeex/src/java/org/xiph/speex/Encoder.java0000644000175000017500000002120610135761046021133 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Encoder.java * * * * Author: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: 9th April 2003 * * * ******************************************************************************/ /* $Id: Encoder.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Speex Encoder interface, used as a base for the Narrowband and sideband * encoders. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public interface Encoder { /** * Encode the given input signal. * @param bits - Speex bits buffer. * @param in - the raw mono audio frame to encode. * @return 1 if successful. */ public int encode(Bits bits, float[] in); /** * Returns the size in bits of an audio frame encoded with the current mode. * @return the size in bits of an audio frame encoded with the current mode. */ public int getEncodedFrameSize(); //-------------------------------------------------------------------------- // Speex Control Functions //-------------------------------------------------------------------------- /** * Returns the size of a frame. * @return the size of a frame. */ public int getFrameSize(); /** * Sets the Quality (between 0 and 10). * @param quality - the desired Quality (between 0 and 10). */ public void setQuality(int quality); /** * Get the current Bit Rate. * @return the current Bit Rate. */ public int getBitRate(); // public void resetState(); /** * Returns the Pitch Gain array. * @return the Pitch Gain array. */ public float[] getPiGain(); /** * Returns the excitation array. * @return the excitation array. */ public float[] getExc(); /** * Returns the innovation array. * @return the innovation array. */ public float[] getInnov(); /** * Sets the encoding submode. * @param mode */ public void setMode(int mode); /** * Returns the encoding submode currently in use. * @return the encoding submode currently in use. */ public int getMode(); /** * Sets the bitrate. * @param bitrate */ public void setBitRate(int bitrate); /** * Sets whether or not to use Variable Bit Rate encoding. * @param vbr */ public void setVbr(boolean vbr); /** * Returns whether or not we are using Variable Bit Rate encoding. * @return whether or not we are using Variable Bit Rate encoding. */ public boolean getVbr(); /** * Sets whether or not to use Voice Activity Detection encoding. * @param vad */ public void setVad(boolean vad); /** * Returns whether or not we are using Voice Activity Detection encoding. * @return whether or not we are using Voice Activity Detection encoding. */ public boolean getVad(); /** * Sets whether or not to use Discontinuous Transmission encoding. * @param dtx */ public void setDtx(boolean dtx); /** * Returns whether or not we are using Discontinuous Transmission encoding. * @return whether or not we are using Discontinuous Transmission encoding. */ public boolean getDtx(); /** * Returns the Average Bit Rate used (0 if ABR is not turned on). * @return the Average Bit Rate used (0 if ABR is not turned on). */ public int getAbr(); /** * Sets the Average Bit Rate. * @param abr - the desired Average Bit Rate. */ public void setAbr(int abr); /** * Sets the Varible Bit Rate Quality. * @param quality - the desired Varible Bit Rate Quality. */ public void setVbrQuality(float quality); /** * Returns the Varible Bit Rate Quality. * @return the Varible Bit Rate Quality. */ public float getVbrQuality(); /** * Sets the algorithmic complexity. * @param complexity - the desired algorithmic complexity (between 1 and 10 - default is 3). */ public void setComplexity(int complexity); /** * Returns the algorthmic complexity. * @return the algorthmic complexity. */ public int getComplexity(); /** * Sets the sampling rate. * @param rate - the sampling rate. */ public void setSamplingRate(int rate); /** * Returns the sampling rate. * @return the sampling rate. */ public int getSamplingRate(); /** * Return LookAhead. * @return LookAhead. */ public int getLookAhead(); /** * Returns the relative quality. * @return the relative quality. */ public float getRelativeQuality(); } jspeex/src/java/org/xiph/speex/Filters.java0000644000175000017500000003744610135761046021201 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Filters.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: Filters.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Filters * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class Filters { private int last_pitch; private float[] last_pitch_gain; private float smooth_gain; private float[] xx; /** * Constructor */ public Filters() { last_pitch_gain = new float[3]; xx = new float[1024]; } /** * Initialisation */ public void init() { last_pitch=0; last_pitch_gain[0]=last_pitch_gain[1]=last_pitch_gain[2]=0; smooth_gain=1; } /** * bw_lpc * @param gamma * @param lpc_in * @param lpc_out * @param order */ public static final void bw_lpc(final float gamma, final float[] lpc_in, final float[] lpc_out, final int order) { float tmp=1; for (int i=0; i1.3f) comb_gain*=1.3f/g; if (g<.5f) comb_gain*=2.0f*g; step = 1.0f/nsf; fact=0; /* Apply pitch comb-filter (filter out noise between pitch harmonics)*/ for (i=0, j=esi; i1.0f) { gain=1.0f; } for (i=nsi;i>1; for (i=0; i tmp2 ? tmp1 : tmp2; } for (i=0;i tmp2 ? tmp1 : tmp2; } for (i=0;iThe next two functions calculate linear prediction coefficients * and/or the related reflection coefficients from the first P_MAX+1 * values of the autocorrelation function. * *

Invented by N. Levinson in 1947, modified by J. Durbin in 1959. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class Lpc { /** * Returns minimum mean square error. * @param lpc - float[0...p-1] LPC coefficients * @param ac - in: float[0...p] autocorrelation values * @param ref - out: float[0...p-1] reflection coef's * @param p * @return minimum mean square error. */ public static float wld(final float[] lpc, final float[] ac, final float[] ref, final int p) { int i, j; float r, error = ac[0]; if (ac[0] == 0) { for (i=0; i x(n) * x(n-i) for all n * `--' * for lags between 0 and lag-1, and x == 0 outside 0...n-1 * @param x - in: float[0...n-1] samples x * @param ac - out: float[0...lag-1] ac values * @param lag * @param n */ public static void autocorr(final float[] x, final float[] ac, int lag, final int n) { float d; int i; while (lag-- > 0) { for (i=lag, d=0; i> 1; /* Allocate memory for Chebyshev series formulation */ T = new float[m2+1]; /* Initialise values */ T[0] = 1; T[1] = x; /* Evaluate Chebyshev series formulation using iterative approach */ /* Evaluate polynomial and return value also free memory space */ sum = coef[m2] + coef[m2-1]*x; x *= 2; for (i=2; i<=m2; i++) { T[i] = x*T[i-1] - T[i-2]; sum += coef[m2-i] * T[i]; } return sum; } /*-------------------------------------------------------------------------*\ FUNCTION....: lpc_to_lsp() AUTHOR......: David Rowe DATE CREATED: 24/2/93 This function converts LPC coefficients to LSP coefficients. \*-------------------------------------------------------------------------*/ /** * This function converts LPC coefficients to LSP coefficients. * @param a - LPC coefficients. * @param lpcrdr - order of LPC coefficients (10). * @param freq - LSP frequencies in the x domain. * @param nb - number of sub-intervals (4). * @param delta - grid spacing interval (0.02). * @return the number of roots (the LSP coefs are returned in the array). */ public static int lpc2lsp (final float[] a, final int lpcrdr, final float[] freq, final int nb, final float delta) { float psuml, psumr, psumm, temp_xr, xl, xr, xm=0; float temp_psumr; int i, j, m, flag, k; float[] Q; // ptrs for memory allocation float[] P; int px; // ptrs of respective P'(z) & Q'(z) int qx; int p; int q; float[] pt; // ptr used for cheb_poly_eval() whether P' or Q' int roots = 0; // DR 8/2/94: number of roots found flag = 1; // program is searching for a root when, 1 else has found one m = lpcrdr/2; // order of P'(z) & Q'(z) polynomials /* Allocate memory space for polynomials */ Q = new float[m+1]; P = new float[m+1]; /* determine P'(z)'s and Q'(z)'s coefficients where P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */ px = 0; /* initialise ptrs */ qx = 0; p = px; q = qx; P[px++] = 1.0f; Q[qx++] = 1.0f; for (i=1; i<=m; i++){ P[px++] = a[i]+a[lpcrdr+1-i]-P[p++]; Q[qx++] = a[i]-a[lpcrdr+1-i]+Q[q++]; } px = 0; qx = 0; for (i=0; i= -1.0)) { float dd; /* Modified by JMV to provide smaller steps around x=+-1 */ dd=(float)(delta*(1-.9*xl*xl)); if (Math.abs(psuml)<.2) dd *= .5; xr = xl - dd; /* interval spacing */ psumr = cheb_poly_eva(pt, xr, lpcrdr); /* poly(xl-delta_x) */ temp_psumr = psumr; temp_xr = xr; /* if no sign change increment xr and re-evaluate poly(xr). Repeat til sign change. if a sign change has occurred the interval is bisected and then checked again for a sign change which determines in which interval the zero lies in. If there is no sign change between poly(xm) and poly(xl) set interval between xm and xr else set interval between xl and xr and repeat till root is located within the specified limits */ if ((psumr*psuml)<0.0) { roots++; psumm = psuml; for (k=0; k<=nb; k++){ xm = (xl+xr)/2; /* bisect the interval */ psumm = cheb_poly_eva(pt, xm, lpcrdr); if (psumm*psuml>0.) { psuml = psumm; xl = xm; } else { psumr = psumm; xr = xm; } } /* once zero is found, reset initial interval to xr */ freq[j] = xm; xl = xm; flag = 0; /* reset flag for next search */ } else { psuml = temp_psumr; xl = temp_xr; } } } return roots; } /** * Line Spectral Pair to Linear Prediction Coefficients * @param freq * @param ak * @param lpcrdr */ public void lsp2lpc(final float[] freq, final float[] ak, final int lpcrdr) { int i, j; float xout1, xout2, xin1, xin2; int n1, n2 ,n3, n4=0; int m = lpcrdr/2; for (i=0; i < 4*m+2; i++) { pw[i] = 0.0f; } xin1 = 1.0f; xin2 = 1.0f; /* reconstruct P(z) and Q(z) by cascading second order polynomials in form 1 - 2xz(-1) +z(-2), where x is the LSP coefficient */ for (j=0; j<=lpcrdr; j++) { int i2=0; for (i=0; i(float)Math.PI-margin) lsp[len-1]=(float)Math.PI-margin; for (i=1;ilsp[i+1]-margin) lsp[i]= .5f * (lsp[i] + lsp[i+1]-margin); } } } jspeex/src/java/org/xiph/speex/LspQuant.java0000644000175000017500000002022210135761046021320 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: LU.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: LspQuant.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Abstract class that is the base for the various LSP Quantisation and * Unquantisation methods. * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public abstract class LspQuant implements Codebook { /** */ public static final int MAX_LSP_SIZE = 20; /** * Constructor */ protected LspQuant() { } /** * Line Spectral Pair Quantification. * @param lsp - Line Spectral Pairs table. * @param qlsp - Quantified Line Spectral Pairs table. * @param order * @param bits - Speex bits buffer. */ public abstract void quant(final float[] lsp, final float[] qlsp, final int order, final Bits bits); /** * Line Spectral Pair Unquantification. * @param lsp - Line Spectral Pairs table. * @param order * @param bits - Speex bits buffer. */ public abstract void unquant(float[] lsp, int order, Bits bits); /** * Read the next 6 bits from the buffer, and using the value read and the * given codebook, rebuild LSP table. * @param lsp * @param tab * @param bits - Speex bits buffer. * @param k * @param ti * @param li */ protected void unpackPlus(final float[] lsp, final int[] tab, final Bits bits, final float k, final int ti, final int li) { int id=bits.unpack(6); for (int i=0;i best_score[N-1]) { float g1, g; g1 = corr[i-start]/(energy[i-start]+10); g = (float) Math.sqrt(g1*corr[i-start]/(e0+10)); if (g>g1) g=g1; if (g<0) g=0; for (j=0; j best_score[j]) { for (k=N-1; k>j; k--) { best_score[k]=best_score[k-1]; pitch[k]=pitch[k-1]; gain[k] = gain[k-1]; } best_score[j]=score[i-start]; pitch[j]=i; gain[j]=g; break; } } } } } } jspeex/src/java/org/xiph/speex/Ltp3Tap.java0000644000175000017500000003246510135761046021054 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Ltp3Tap.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: Ltp3Tap.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Long Term Prediction Quantisation and Unquantisation (3Tap) * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class Ltp3Tap extends Ltp { /** */ private float[] gain; /** */ private int[] gain_cdbk; /** */ private int gain_bits; /** */ private int pitch_bits; /** */ private float[][] e; /** * Constructor * @param gain_cdbk * @param gain_bits * @param pitch_bits */ public Ltp3Tap(final int[] gain_cdbk, final int gain_bits, final int pitch_bits) { this.gain = new float[3]; this.gain_cdbk = gain_cdbk; this.gain_bits = gain_bits; this.pitch_bits = pitch_bits; this.e = new float[3][128]; } /** * Long Term Prediction Quantification (3Tap). * @return pitch */ public final int quant(float[] target, float[] sw, int sws, float[] ak, float[] awk1, float[] awk2, float[] exc, int es, int start, int end, float pitch_coef, int p, int nsf, Bits bits, float[] exc2, int e2s, float[] r, int complexity) { int i,j; int[] cdbk_index = new int[1]; int pitch=0, best_gain_index=0; float[] best_exc; int best_pitch=0; float err, best_err=-1; int N; int[] nbest; float[] gains; N=complexity; if (N>10) N=10; nbest=new int[N]; gains = new float[N]; if (N==0 || endend-start+1) N=end-start+1; open_loop_nbest_pitch(sw, sws, start, end, nsf, nbest, gains, N); for (i=0;i subframe_offset) { float gain_sum = Math.abs(gain[1]); float tmp = count_lost < 4 ? last_pitch_gain : 0.4f * last_pitch_gain; if (tmp>.95f) tmp=.95f; if (gain[0]>0) gain_sum += gain[0]; else gain_sum -= .5f*gain[0]; if (gain[2]>0) gain_sum += gain[2]; else gain_sum -= .5f*gain[0]; if (gain_sum > tmp) { float fact = tmp/gain_sum; for (i=0;i<3;i++) gain[i]*=fact; } } gain_val[0]=gain[0]; gain_val[1]=gain[1]; gain_val[2]=gain[2]; for (i=0;i<3;i++) { int j, tmp1, tmp2, pp=pitch+1-i; tmp1=nsf; if (tmp1>pp) tmp1=pp; tmp2=nsf; if (tmp2>pp+pitch) tmp2=pp+pitch; for (j=0;j=0; i--) { int pp=pitch+1-i; for (j=0; j0) tot+=gain_cdbk[ptr]; if (gain_cdbk[ptr+2]>0) tot+=gain_cdbk[ptr+2]; if (tot>1) continue; } if (sum>best_sum || i==0) { best_sum=sum; best_cdbk=i; } } gain[0] = 0.015625f*gain_cdbk[best_cdbk*3] + .5f; gain[1] = 0.015625f*gain_cdbk[best_cdbk*3+1]+ .5f; gain[2] = 0.015625f*gain_cdbk[best_cdbk*3+2]+ .5f; cdbk_index[0]=best_cdbk; } for (i=0; i.99f) pitch_coef=.99f; for (i=0;i.99f) { pitch_coef=.99f; } for (i=0;i8) { /* Invalid mode */ throw new StreamCorruptedException("Invalid mode encountered: " + m); //return -2; } } while (m>8); submodeID = m; } /* Shift all buffers by one frame */ System.arraycopy(frmBuf, frameSize, frmBuf, 0, bufSize-frameSize); System.arraycopy(excBuf, frameSize, excBuf, 0, bufSize-frameSize); /* If null mode (no transmission), just set a couple things to zero*/ if (submodes[submodeID] == null) { Filters.bw_lpc(.93f, interp_qlpc, lpc, 10); float innov_gain=0; for (i=0;i1) dtx_enabled=0; /*Loop on subframes */ for (sub=0;sub max_pitch) pit_max = max_pitch; } else { pit_min = pit_max = ol_pitch; } } else { pit_min = min_pitch; pit_max = max_pitch; } /* Pitch synthesis */ pitch = submodes[submodeID].ltp.unquant(excBuf, extIdx, pit_min, ol_pitch_coef, subframeSize, pitch_gain, bits, count_lost, offset, last_pitch_gain); /* If we had lost frames, check energy of last received frame */ if (count_lost != 0 && ol_gain < last_ol_gain) { float fact = ol_gain/(last_ol_gain+1); for (i=0;i0) tmp += pitch_gain[0]; else tmp -= .5*pitch_gain[0]; if (pitch_gain[2]>0) tmp += pitch_gain[2]; else tmp -= .5*pitch_gain[0]; pitch_average += tmp; if (tmp>best_pitch_gain) { best_pitch = pitch; best_pitch_gain = tmp; } /* Unquantize the innovation */ int q_energy, ivi=sub*subframeSize; float ener; for (i=ivi;i=0) excBuf[extIdx+voc_offset]=(float)Math.sqrt(1.0f*ol_pitch); voc_offset+=ol_pitch; } voc_offset -= subframeSize; g=.5f+2*(g-.6f); if (g<0) g=0; if (g>1) g=1; for (i=0;i0) { filters.comb_filter(excBuf, extIdx, frmBuf, spIdx, subframeSize, pitch, pitch_gain, submodes[submodeID].comb_gain); } if (enhanced) { /* Use enhanced LPC filter */ Filters.filter_mem2(frmBuf, spIdx, awk2, awk1, subframeSize, lpcSize, mem_sp, lpcSize); Filters.filter_mem2(frmBuf, spIdx, awk3, interp_qlpc, subframeSize, lpcSize, mem_sp, 0); } else { /* Use regular filter */ for (i=0;i 2) /* rollover */ pitch_gain_buf_idx = 0; last_ol_gain = ol_gain; return 0; } /** * Decode when packets are lost. * @param out - the generated mono audio frame. * @return 0 if successful. */ public int decodeLost(final float[] out) { int i; float pitch_gain, fact, gain_med; fact = (float) Math.exp(-.04*count_lost*count_lost); // median3(a, b, c) = (a.95f) pitch_gain=.95f; pitch_gain *= fact; /* Shift all buffers by one frame */ System.arraycopy(frmBuf, frameSize, frmBuf, 0, bufSize-frameSize); System.arraycopy(excBuf, frameSize, excBuf, 0, bufSize-frameSize); for (int sub=0; sub.95) pitch_gain=.95;*/ { float innov_gain=0; for (i=0; i 2) /* rollover */ pitch_gain_buf_idx = 0; return 0; } /** * Decode the given bits to stereo. * @param data - float array of size 2*frameSize, that contains the mono * audio samples in the first half. When the function has completed, the * array will contain the interlaced stereo audio samples. * @param frameSize - the size of a frame of mono audio samples. */ public void decodeStereo(final float[] data, final int frameSize) { stereo.decode(data, frameSize); } /** * Enables or disables perceptual enhancement. * @param enhanced */ public void setPerceptualEnhancement(final boolean enhanced) { this.enhanced = enhanced; } /** * Returns whether perceptual enhancement is enabled or disabled. * @return whether perceptual enhancement is enabled or disabled. */ public boolean getPerceptualEnhancement() { return enhanced; } } jspeex/src/java/org/xiph/speex/NbEncoder.java0000644000175000017500000010200510135761046021410 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: NbEncoder.java * * * * Author: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: 9th April 2003 * * * ******************************************************************************/ /* $Id: NbEncoder.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Narrowband Speex Encoder * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class NbEncoder extends NbCodec implements Encoder { /** The Narrowband Quality map indicates which narrowband submode to use for the given narrowband quality setting */ public static final int[] NB_QUALITY_MAP = {1, 8, 2, 3, 3, 4, 4, 5, 5, 6, 7}; private int bounded_pitch; /** Next frame should not rely on previous frames for pitch */ private int[] pitch; /** */ private float pre_mem2; /** 1-element memory for pre-emphasis */ private float[] exc2Buf; /** "Pitch enhanced" excitation */ private int exc2Idx; /** "Pitch enhanced" excitation */ private float[] swBuf; /** Weighted signal buffer */ private int swIdx; /** Start of weighted signal frame */ private float[] window; /** Temporary (Hanning) window */ private float[] buf2; /** 2nd temporary buffer */ private float[] autocorr; /** auto-correlation */ private float[] lagWindow; /** Window applied to auto-correlation */ private float[] lsp; /** LSPs for current frame */ private float[] old_lsp; /** LSPs for previous frame */ private float[] interp_lsp; /** Interpolated LSPs */ private float[] interp_lpc; /** Interpolated LPCs */ private float[] bw_lpc1; /** LPCs after bandwidth expansion by gamma1 for perceptual weighting*/ private float[] bw_lpc2; /** LPCs after bandwidth expansion by gamma2 for perceptual weighting*/ private float[] rc; /** Reflection coefficients */ private float[] mem_sw; /** Filter memory for perceptually-weighted signal */ private float[] mem_sw_whole; /** Filter memory for perceptually-weighted signal (whole frame)*/ private float[] mem_exc; /** Filter memory for excitation (whole frame) */ private Vbr vbr; /** State of the VBR data */ private int dtx_count; /** Number of consecutive DTX frames */ private float[] innov2; protected int complexity; /** Complexity setting (0-10 from least complex to most complex) */ protected int vbr_enabled; /** 1 for enabling VBR, 0 otherwise */ protected int vad_enabled; /** 1 for enabling VAD, 0 otherwise */ protected int abr_enabled; /** ABR setting (in bps), 0 if off */ protected float vbr_quality; /** Quality setting for VBR encoding */ protected float relative_quality; /** Relative quality that will be needed by VBR */ protected float abr_drift; protected float abr_drift2; protected float abr_count; protected int sampling_rate; protected int submodeSelect; /** Mode chosen by the user (may differ from submodeID if VAD is on) */ /** * Initialisation * @param frameSize * @param subframeSize * @param lpcSize * @param bufSize */ public void init(final int frameSize, final int subframeSize, final int lpcSize, final int bufSize) { super.init(frameSize, subframeSize, lpcSize, bufSize); complexity = 3; // in C it's 2 here, but set to 3 automatically by the encoder vbr_enabled = 0; // disabled by default vad_enabled = 0; // disabled by default abr_enabled = 0; // disabled by default vbr_quality = 8; submodeSelect = 5; pre_mem2 = 0; bounded_pitch = 1; exc2Buf = new float[bufSize]; exc2Idx = bufSize - windowSize; swBuf = new float[bufSize]; swIdx = bufSize - windowSize; window = Misc.window(windowSize, subframeSize); lagWindow = Misc.lagWindow(lpcSize, lag_factor); autocorr = new float[lpcSize+1]; buf2 = new float[windowSize]; interp_lpc = new float[lpcSize+1]; interp_qlpc = new float[lpcSize+1]; bw_lpc1 = new float[lpcSize+1]; bw_lpc2 = new float[lpcSize+1]; lsp = new float[lpcSize]; qlsp = new float[lpcSize]; old_lsp = new float[lpcSize]; old_qlsp = new float[lpcSize]; interp_lsp = new float[lpcSize]; interp_qlsp = new float[lpcSize]; rc = new float[lpcSize]; mem_sp = new float[lpcSize]; // why was there a *5 before ?!? mem_sw = new float[lpcSize]; mem_sw_whole = new float[lpcSize]; mem_exc = new float[lpcSize]; vbr = new Vbr(); dtx_count = 0; abr_count = 0; sampling_rate = 8000; awk1 = new float[lpcSize+1]; awk2 = new float[lpcSize+1]; awk3 = new float[lpcSize+1]; innov2 = new float[40]; filters.init (); pitch = new int[nbSubframes]; } /** * Encode the given input signal. * @param bits - Speex bits buffer. * @param in - the raw mono audio frame to encode. * @return return 1 if successful. */ public int encode(final Bits bits, final float[] in) { int i; float[] res, target, mem; float[] syn_resp; float[] orig; /* Copy new data in input buffer */ System.arraycopy(frmBuf, frameSize, frmBuf, 0, bufSize-frameSize); frmBuf[bufSize-frameSize] = in[0] - preemph*pre_mem; for (i=1; i1) roots = Lsp.lpc2lsp (lpc, lpcSize, lsp, 11, 0.05f); if (roots==lpcSize) { /* LSP x-domain to angle domain*/ for (i=0;i.85*ol_pitch_coef) && (Math.abs(nol_pitch[i]-ol_pitch/2.0)<=1 || Math.abs(nol_pitch[i]-ol_pitch/3.0)<=1 || Math.abs(nol_pitch[i]-ol_pitch/4.0)<=1 || Math.abs(nol_pitch[i]-ol_pitch/5.0)<=1)) { /*ol_pitch_coef=nol_pitch_coef[i];*/ ol_pitch = nol_pitch[i]; } } /*if (ol_pitch>50) ol_pitch/=2;*/ /*ol_pitch_coef = sqrt(ol_pitch_coef);*/ } else { ol_pitch=0; ol_pitch_coef=0; } /*Compute "real" excitation*/ Filters.fir_mem2(frmBuf, frmIdx, interp_lpc, excBuf, excIdx, frameSize, lpcSize, mem_exc); /* Compute open-loop excitation gain */ ol_gain=0; for (i=0;i 0) { /* Only adapt if long-term and short-term drift are the same sign */ qual_change = -.00001f*abr_drift/(1+abr_count); if (qual_change>.05f) qual_change=.05f; if (qual_change<-.05f) qual_change=-.05f; } vbr_quality += qual_change; if (vbr_quality>10) vbr_quality=10; if (vbr_quality<0) vbr_quality=0; } relative_quality = vbr.analysis(in, frameSize, ol_pitch, ol_pitch_coef); /*if (delta_qual<0)*/ /* delta_qual*=.1*(3+st->vbr_quality);*/ if (vbr_enabled != 0) { int mode; int choice=0; float min_diff=100; mode = 8; while (mode > 0) { int v1; float thresh; v1=(int)Math.floor(vbr_quality); if (v1==10) thresh = Vbr.nb_thresh[mode][v1]; else thresh = (vbr_quality-v1)*Vbr.nb_thresh[mode][v1+1] + (1+v1-vbr_quality)*Vbr.nb_thresh[mode][v1]; if (relative_quality > thresh && relative_quality-thresh.05 || dtx_enabled==0 || dtx_count>20) { mode=1; dtx_count=1; } else { mode=0; dtx_count++; } } else { dtx_count=0; } setMode(mode); if (abr_enabled != 0) { int bitrate; bitrate = getBitRate(); abr_drift+=(bitrate-abr_enabled); abr_drift2 = .95f*abr_drift2 + .05f*(bitrate-abr_enabled); abr_count += 1.0; } } else { /*VAD only case*/ int mode; if (relative_quality<2) { if (dtx_count==0 || lsp_dist>.05 || dtx_enabled == 0 || dtx_count>20) { dtx_count=1; mode=1; } else { mode=0; dtx_count++; } } else { dtx_count = 0; mode=submodeSelect; } /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/ submodeID=mode; } } else { relative_quality = -1; } /* First, transmit a zero for narrowband */ bits.pack(0, 1); /* Transmit the sub-mode we use for this frame */ bits.pack(submodeID, NB_SUBMODE_BITS); /* If null mode (no transmission), just set a couple things to zero*/ if (submodes[submodeID] == null) { for (i=0;i15) quant=15; if (quant<0) quant=0; bits.pack(quant, 4); ol_pitch_coef=(float) 0.066667*quant; } /*Quantize and transmit open-loop excitation gain*/ { int qe = (int)(Math.floor(0.5+3.5*Math.log(ol_gain))); if (qe<0) qe=0; if (qe>31) qe=31; ol_gain = (float) Math.exp(qe/3.5); bits.pack(qe, 5); } /* Special case for first frame */ if (first != 0) { for (i=0;i=0) Filters.bw_lpc(gamma2, interp_lpc, bw_lpc2, lpcSize); else { bw_lpc2[0]=1; bw_lpc2[1]=-preemph; for (i=2;i<=lpcSize;i++) bw_lpc2[i]=0; } /* Compute impulse response of A(z/g1) / ( A(z)*A(z/g2) )*/ for (i=0;i max_pitch-margin) ol_pitch=max_pitch-margin; pit_min = ol_pitch-margin+1; pit_max = ol_pitch+margin; } else { pit_min=pit_max=ol_pitch; } } else { pit_min = min_pitch; pit_max = max_pitch; } /* Force pitch to use only the current frame if needed */ if (bounded_pitch != 0 && pit_max>offset) pit_max=offset; /* Perform pitch search */ pitchval = submodes[submodeID].ltp.quant(target, swBuf, sw, interp_qlpc, bw_lpc1, bw_lpc2, excBuf, exc, pit_min, pit_max, ol_pitch_coef, lpcSize, subframeSize, bits, exc2Buf, exc2, syn_resp, complexity); pitch[sub]=pitchval; // } else { // speex_error ("No pitch prediction, what's wrong"); // } /* Update target for adaptive codebook contribution */ Filters.syn_percep_zero(excBuf, exc, interp_qlpc, bw_lpc1, bw_lpc2, res, subframeSize, lpcSize); for (i=0;i=1) { for (i=0;i 10) { quality = 10; } submodeID = submodeSelect = NB_QUALITY_MAP[quality]; } /** * Gets the bitrate. * @return the bitrate. */ public int getBitRate() { if (submodes[submodeID] != null) return sampling_rate*submodes[submodeID].bits_per_frame/frameSize; else return sampling_rate*(NB_SUBMODE_BITS+1)/frameSize; } /** * */ // public void resetState() // { // } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- /** * Sets the encoding submode. * @param mode */ public void setMode(int mode) { if (mode < 0) { mode = 0; } submodeID = submodeSelect = mode; } /** * Returns the encoding submode currently in use. * @return the encoding submode currently in use. */ public int getMode() { return submodeID; } /** * Sets the bitrate. * @param bitrate */ public void setBitRate(final int bitrate) { for (int i=10; i>=0; i--) { setQuality(i); if (getBitRate() <= bitrate) return; } } /** * Sets whether or not to use Variable Bit Rate encoding. * @param vbr */ public void setVbr(final boolean vbr) { vbr_enabled = vbr ? 1 : 0; } /** * Returns whether or not we are using Variable Bit Rate encoding. * @return whether or not we are using Variable Bit Rate encoding. */ public boolean getVbr() { return vbr_enabled != 0; } /** * Sets whether or not to use Voice Activity Detection encoding. * @param vad */ public void setVad(final boolean vad) { vad_enabled = vad ? 1 : 0; } /** * Returns whether or not we are using Voice Activity Detection encoding. * @return whether or not we are using Voice Activity Detection encoding. */ public boolean getVad() { return vad_enabled != 0; } /** * Sets whether or not to use Discontinuous Transmission encoding. * @param dtx */ public void setDtx(final boolean dtx) { dtx_enabled = dtx ? 1 : 0; } /** * Returns the Average Bit Rate used (0 if ABR is not turned on). * @return the Average Bit Rate used (0 if ABR is not turned on). */ public int getAbr() { return abr_enabled; } /** * Sets the Average Bit Rate. * @param abr */ public void setAbr(final int abr) { abr_enabled = (abr!=0) ? 1 : 0; vbr_enabled = 1; { int i=10, rate, target; float vbr_qual; target = abr; while (i>=0) { setQuality(i); rate = getBitRate(); if (rate <= target) break; i--; } vbr_qual=i; if (vbr_qual<0) vbr_qual=0; setVbrQuality(vbr_qual); abr_count=0; abr_drift=0; abr_drift2=0; } } /** * Sets the Varible Bit Rate Quality. * @param quality */ public void setVbrQuality(float quality) { if (quality < 0f) quality = 0f; if (quality > 10f) quality = 10f; vbr_quality = quality; } /** * Returns the Varible Bit Rate Quality. * @return the Varible Bit Rate Quality. */ public float getVbrQuality() { return vbr_quality; } /** * Sets the algorthmic complexity. * @param complexity */ public void setComplexity(int complexity) { if (complexity < 0) complexity = 0; if (complexity > 10) complexity = 10; this.complexity = complexity; } /** * Returns the algorthmic complexity. * @return the algorthmic complexity. */ public int getComplexity() { return complexity; } /** * Sets the sampling rate. * @param rate */ public void setSamplingRate(final int rate) { sampling_rate = rate; } /** * Returns the sampling rate. * @return the sampling rate. */ public int getSamplingRate() { return sampling_rate; } /** * Return LookAhead. * @return LookAhead. */ public int getLookAhead() { return windowSize - frameSize; } /** * Returns the relative quality. * @return the relative quality. */ public float getRelativeQuality() { return relative_quality; } } jspeex/src/java/org/xiph/speex/NbLspQuant.java0000644000175000017500000001565210135761046021613 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: NbLU.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: NbLspQuant.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * LSP Quantisation and Unquantisation (narrowband) * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class NbLspQuant extends LspQuant { /** * Line Spectral Pair Quantification (narrowband). * @param lsp - Line Spectral Pairs table. * @param qlsp - Quantified Line Spectral Pairs table. * @param order * @param bits - Speex bits buffer. */ public final void quant(float[] lsp, float[] qlsp, int order, Bits bits) { int i; float tmp1, tmp2; int id; float[] quant_weight = new float[MAX_LSP_SIZE]; for (i=0;i tmp2 ? tmp1 : tmp2; } for (i=0;iOgg uses the same generator polynomial as ethernet, although with an * unreflected alg and an init/final of 0, not 0xffffffff. * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class OggCrc { // TODO - implement java.util.zip.Checksum /** * CRC checksum lookup table */ private static int[] crc_lookup; static { crc_lookup = new int[256]; for (int i=0; i>>24)&0xff)^(data[offset]&0xff)]; } return crc; } } jspeex/src/java/org/xiph/speex/OggSpeexWriter.java0000644000175000017500000002342210135761046022474 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: OggSpeexWriter.java * * * * Author: Marc GIMPEL * * * * Date: 9th April 2003 * * * ******************************************************************************/ /* $Id: OggSpeexWriter.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ package org.xiph.speex; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.FileOutputStream; import java.util.Random; /** * Ogg Speex Writer * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class OggSpeexWriter extends AudioFileWriter { /** Number of packets in an Ogg page (must be less than 255) */ public static final int PACKETS_PER_OGG_PAGE = 250; /** The OutputStream */ private OutputStream out; /** Defines the encoder mode (0=NB, 1=WB and 2-UWB). */ private int mode; /** Defines the sampling rate of the audio input. */ private int sampleRate; /** Defines the number of channels of the audio input (1=mono, 2=stereo). */ private int channels; /** Defines the number of frames per speex packet. */ private int nframes; /** Defines whether or not to use VBR (Variable Bit Rate). */ private boolean vbr; /** */ private int size; /** Ogg Stream Serial Number */ private int streamSerialNumber; /** Data buffer */ private byte[] dataBuffer; /** Pointer within the Data buffer */ private int dataBufferPtr; /** Header buffer */ private byte[] headerBuffer; /** Pointer within the Header buffer */ private int headerBufferPtr; /** Ogg Page count */ private int pageCount; /** Speex packet count within an Ogg Page */ private int packetCount; /** * Absolute granule position * (the number of audio samples from beginning of file to end of Ogg Packet). */ private long granulepos; /** * Builds an Ogg Speex Writer. */ public OggSpeexWriter() { if (streamSerialNumber == 0) streamSerialNumber = new Random().nextInt(); dataBuffer = new byte[65565]; dataBufferPtr = 0; headerBuffer = new byte[255]; headerBufferPtr = 0; pageCount = 0; packetCount = 0; granulepos = 0; } /** * Builds an Ogg Speex Writer. * @param mode the mode of the encoder (0=NB, 1=WB, 2=UWB). * @param sampleRate the number of samples per second. * @param channels the number of audio channels (1=mono, 2=stereo, ...). * @param nframes the number of frames per speex packet. * @param vbr */ public OggSpeexWriter(final int mode, final int sampleRate, final int channels, final int nframes, final boolean vbr) { this(); setFormat(mode, sampleRate, channels, nframes, vbr); } /** * Sets the output format. * Must be called before WriteHeader(). * @param mode the mode of the encoder (0=NB, 1=WB, 2=UWB). * @param sampleRate the number of samples per second. * @param channels the number of audio channels (1=mono, 2=stereo, ...). * @param nframes the number of frames per speex packet. * @param vbr */ private void setFormat(final int mode, final int sampleRate, final int channels, final int nframes, boolean vbr) { this.mode = mode; this.sampleRate = sampleRate; this.channels = channels; this.nframes = nframes; this.vbr = vbr; } /** * Sets the Stream Serial Number. * Must not be changed mid stream. * @param serialNumber */ public void setSerialNumber(final int serialNumber) { this.streamSerialNumber = serialNumber; } /** * Closes the output file. * @exception IOException if there was an exception closing the Audio Writer. */ public void close() throws IOException { flush(true); out.close(); } /** * Open the output file. * @param file - file to open. * @exception IOException if there was an exception opening the Audio Writer. */ public void open(final File file) throws IOException { file.delete(); out = new FileOutputStream(file); size = 0; } /** * Open the output file. * @param filename - file to open. * @exception IOException if there was an exception opening the Audio Writer. */ public void open(final String filename) throws IOException { open(new File(filename)); } /** * Writes the header pages that start the Ogg Speex file. * Prepares file for data to be written. * @param comment description to be included in the header. * @exception IOException */ public void writeHeader(final String comment) throws IOException { int chksum; byte[] header; byte[] data; /* writes the OGG header page */ header = buildOggPageHeader(2, 0, streamSerialNumber, pageCount++, 1, new byte[] {80}); data = buildSpeexHeader(sampleRate, mode, channels, vbr, nframes); chksum = OggCrc.checksum(0, header, 0, header.length); chksum = OggCrc.checksum(chksum, data, 0, data.length); writeInt(header, 22, chksum); out.write(header); out.write(data); /* writes the OGG comment page */ header = buildOggPageHeader(0, 0, streamSerialNumber, pageCount++, 1, new byte[] {(byte) (comment.length() + 8)}); data = buildSpeexComment(comment); chksum = OggCrc.checksum(0, header, 0, header.length); chksum = OggCrc.checksum(chksum, data, 0, data.length); writeInt(header, 22, chksum); out.write(header); out.write(data); } /** * Writes a packet of audio. * @param data - audio data. * @param offset - the offset from which to start reading the data. * @param len - the length of data to read. * @exception IOException */ public void writePacket(final byte[] data, final int offset, final int len) throws IOException { if (len <= 0) { // nothing to write return; } if (packetCount > PACKETS_PER_OGG_PAGE) { flush(false); } System.arraycopy(data, offset, dataBuffer, dataBufferPtr, len); dataBufferPtr += len; headerBuffer[headerBufferPtr++]=(byte)len; packetCount++; granulepos += nframes * (mode==2 ? 640 : (mode==1 ? 320 : 160)); } /** * Flush the Ogg page out of the buffers into the file. * @param eos - end of stream * @exception IOException */ private void flush(final boolean eos) throws IOException { int chksum; byte[] header; /* writes the OGG header page */ header = buildOggPageHeader((eos ? 4 : 0), granulepos, streamSerialNumber, pageCount++, packetCount, headerBuffer); chksum = OggCrc.checksum(0, header, 0, header.length); chksum = OggCrc.checksum(chksum, dataBuffer, 0, dataBufferPtr); writeInt(header, 22, chksum); out.write(header); out.write(dataBuffer, 0, dataBufferPtr); dataBufferPtr = 0; headerBufferPtr = 0; packetCount = 0; } } jspeex/src/java/org/xiph/speex/PcmWaveWriter.java0000644000175000017500000004036610135761046022323 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: PcmWaveWriter.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: PcmWaveWriter.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ package org.xiph.speex; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; /** * Writes basic PCM wave files from binary audio data. * *

Here's an example that writes 2 seconds of silence *

 * PcmWaveWriter s_wsw = new PcmWaveWriter(2, 44100);
 * byte[] silence = new byte[16*2*44100];
 * wsw.Open("C:\\out.wav");
 * wsw.WriteHeader(); 
 * wsw.WriteData(silence, 0, silence.length);
 * wsw.WriteData(silence, 0, silence.length);
 * wsw.Close(); 
 * 
* * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class PcmWaveWriter extends AudioFileWriter { /** Wave type code of PCM */ public static final short WAVE_FORMAT_PCM = (short) 0x01; /** Wave type code of Speex */ public static final short WAVE_FORMAT_SPEEX = (short) 0xa109; /** * Table describing the number of frames per packet in a Speex Wave file, * depending on its mode-1 (1=NB, 2=WB, 3=UWB), channels-1 (1=mono, 2=stereo) * and the quality setting (0 to 10). * See end of file for exerpt from SpeexACM code for more explanations. */ public static final int[][][] WAVE_FRAME_SIZES = new int[][][] {{{8, 8, 8, 1, 1, 2, 2, 2, 2, 2, 2}, // NB mono {2, 1, 1, 7, 7, 8, 8, 8, 8, 3, 3}}, // NB stereo {{8, 8, 8, 2, 1, 1, 2, 2, 2, 2, 2}, // WB mono {1, 2, 2, 8, 7, 6, 3, 3, 3, 3, 3}}, // WB stereo {{8, 8, 8, 1, 2, 2, 1, 1, 1, 1, 1}, // UWB mono {2, 1, 1, 7, 8, 3, 6, 6, 5, 5, 5}}}; // UWB stereo /** * Table describing the number of bit per Speex frame, depending on its * mode-1 (1=NB, 2=WB, 3=UWB), channels-1 (1=mono, 2=stereo) and the quality * setting (0 to 10). * See end of file for exerpt from SpeexACM code for more explanations. */ public static final int[][][] WAVE_BITS_PER_FRAME = new int[][][] {{{ 43, 79, 119, 160, 160, 220, 220, 300, 300, 364, 492}, // NB mono { 60, 96, 136, 177, 177, 237, 237, 317, 317, 381, 509}}, // NB stereo {{ 79, 115, 155, 196, 256, 336, 412, 476, 556, 684, 844}, // WB mono { 96, 132, 172, 213, 273, 353, 429, 493, 573, 701, 861}}, // WB stereo {{ 83, 151, 191, 232, 292, 372, 448, 512, 592, 720, 880}, // UWB mono {100, 168, 208, 249, 309, 389, 465, 529, 609, 737, 897}}}; // UWB stereo private RandomAccessFile raf; /** Defines the encoder mode (0=NB, 1=WB and 2-UWB). */ private int mode; /** */ private int quality; /** Defines the sampling rate of the audio input. */ private int sampleRate; /** Defines the number of channels of the audio input (1=mono, 2=stereo). */ private int channels; /** Defines the number of frames per speex packet. */ private int nframes; /** Defines whether or not to use VBR (Variable Bit Rate). */ private boolean vbr; /** */ private int size; /** */ private boolean isPCM; /** * Constructor. */ public PcmWaveWriter() { size = 0; } /** * Constructor. * @param sampleRate the number of samples per second. * @param channels the number of audio channels (1=mono, 2=stereo, ...). */ public PcmWaveWriter(final int sampleRate, final int channels) { this(); setPCMFormat(sampleRate, channels); } /** * Constructor. * @param mode the mode of the encoder (0=NB, 1=WB, 2=UWB). * @param quality * @param sampleRate the number of samples per second. * @param channels the number of audio channels (1=mono, 2=stereo, ...). * @param nframes the number of frames per speex packet. * @param vbr */ public PcmWaveWriter(final int mode, final int quality, final int sampleRate, final int channels, final int nframes, final boolean vbr) { this(); setSpeexFormat(mode, quality, sampleRate, channels, nframes, vbr); } /** * Sets the output format for a PCM Wave file. * Must be called before WriteHeader(). * @param sampleRate the number of samples per second. * @param channels the number of audio channels (1=mono, 2=stereo, ...). */ private void setPCMFormat(final int sampleRate, final int channels) { this.channels = channels; this.sampleRate = sampleRate; isPCM = true; } /** * Sets the output format for a Speex Wave file. * Must be called before WriteHeader(). * @param mode the mode of the encoder (0=NB, 1=WB, 2=UWB). * @param quality * @param sampleRate the number of samples per second. * @param channels the number of audio channels (1=mono, 2=stereo, ...). * @param nframes the number of frames per speex packet. * @param vbr */ private void setSpeexFormat(final int mode, final int quality, final int sampleRate, final int channels, final int nframes, final boolean vbr) { this.mode = mode; this.quality = quality; this.sampleRate = sampleRate; this.channels = channels; this.nframes = nframes; this.vbr = vbr; isPCM = false; } /** * Closes the output file. * MUST be called to have a correct stream. * @exception IOException if there was an exception closing the Audio Writer. */ public void close() throws IOException { /* update the total file length field from RIFF chunk */ raf.seek(4); int fileLength = (int) raf.length() - 8; writeInt(raf, fileLength); /* update the data chunk length size */ raf.seek(40); writeInt(raf, size); /* close the output file */ raf.close(); } /** * Open the output file. * @param file - file to open. * @exception IOException if there was an exception opening the Audio Writer. */ public void open(final File file) throws IOException { file.delete(); raf = new RandomAccessFile(file, "rw"); size = 0; } /** * Open the output file. * @param filename filename to open. * @exception IOException if there was an exception opening the Audio Writer. */ public void open(final String filename) throws IOException { open(new File(filename)); } /** * Writes the initial data chunks that start the wave file. * Prepares file for data samples to written. * @param comment ignored by the WAV header. * @exception IOException */ public void writeHeader(final String comment) throws IOException { /* writes the RIFF chunk indicating wave format */ byte[] chkid = "RIFF".getBytes(); raf.write(chkid, 0, chkid.length); writeInt(raf, 0); /* total length must be blank */ chkid = "WAVE".getBytes(); raf.write(chkid, 0, chkid.length); /* format subchunk: of size 16 */ chkid = "fmt ".getBytes(); raf.write(chkid, 0, chkid.length); if (isPCM) { writeInt(raf, 16); // Size of format chunk writeShort(raf, WAVE_FORMAT_PCM); // Format tag: PCM writeShort(raf, (short)channels); // Number of channels writeInt(raf, sampleRate); // Sampling frequency writeInt(raf, sampleRate*channels*2); // Average bytes per second writeShort(raf, (short) (channels*2)); // Blocksize of data writeShort(raf, (short) 16); // Bits per sample } else { int length = comment.length(); writeInt(raf, (short) (18+2+80+length)); // Size of format chunk writeShort(raf, WAVE_FORMAT_SPEEX); // Format tag: Speex writeShort(raf, (short)channels); // Number of channels writeInt(raf, sampleRate); // Sampling frequency writeInt(raf, (calculateEffectiveBitrate(mode, channels, quality) + 7) >> 3); // Average bytes per second writeShort(raf, (short) calculateBlockSize(mode, channels, quality)); // Blocksize of data writeShort(raf, (short) quality); // Bits per sample writeShort(raf, (short) (2+80+length)); // The count in bytes of the extra size raf.writeByte(0xff & 1); // ACM major version number raf.writeByte(0xff & 0); // ACM minor version number raf.write(buildSpeexHeader(sampleRate, mode, channels, vbr, nframes)); raf.writeBytes(comment); } /* write the start of data chunk */ chkid = "data".getBytes(); raf.write(chkid, 0, chkid.length); writeInt(raf, 0); } /** * Writes a packet of audio. * @param data audio data * @param offset the offset from which to start reading the data. * @param len the length of data to read. * @exception IOException */ public void writePacket(final byte[] data, final int offset, final int len) throws IOException { raf.write(data, offset, len); size+= len; } /** * Calculates effective bitrate (considering padding). * See end of file for exerpt from SpeexACM code for more explanations. * @param mode * @param channels * @param quality * @return effective bitrate (considering padding). */ private static final int calculateEffectiveBitrate(final int mode, final int channels, final int quality) { return ((((WAVE_FRAME_SIZES[mode-1][channels-1][quality] * WAVE_BITS_PER_FRAME[mode-1][channels-1][quality]) + 7) >> 3) * 50 * 8) / WAVE_BITS_PER_FRAME[mode-1][channels-1][quality]; } /** * Calculates block size (considering padding). * See end of file for exerpt from SpeexACM code for more explanations. * @param mode * @param channels * @param quality * @return block size (considering padding). */ private static final int calculateBlockSize(final int mode, final int channels, final int quality) { return (((WAVE_FRAME_SIZES[mode-1][channels-1][quality] * WAVE_BITS_PER_FRAME[mode-1][channels-1][quality]) + 7) >> 3); } } // The following is taken from the SpeexACM 1.0.1.1 Source code (codec.c file). // // This array describes how many bits are required by an encoded audio frame. // It also specifies the optimal framesperblock parameter to minimize // padding loss. It also lists the effective bitrate (considering padding). // // The array indices are rate, channels, quality (each as a 0 based index) // /* struct tagQualityInfo { UINT nBitsPerFrame; UINT nFrameSize; UINT nFramesPerBlock; UINT nEffectiveBitrate; } QualityInfo[3][2][11] = { 43, 160, 8, 2150, // 8000 1 0 79, 160, 8, 3950, // 8000 1 1 119, 160, 8, 5950, // 8000 1 2 160, 160, 1, 8000, // 8000 1 3 160, 160, 1, 8000, // 8000 1 4 220, 160, 2, 11000, // 8000 1 5 220, 160, 2, 11000, // 8000 1 6 300, 160, 2, 15000, // 8000 1 7 300, 160, 2, 15000, // 8000 1 8 364, 160, 2, 18200, // 8000 1 9 492, 160, 2, 24600, // 8000 1 10 60, 160, 2, 3000, // 8000 2 0 96, 160, 1, 4800, // 8000 2 1 136, 160, 1, 6800, // 8000 2 2 177, 160, 7, 8857, // 8000 2 3 177, 160, 7, 8857, // 8000 2 4 237, 160, 8, 11850, // 8000 2 5 237, 160, 8, 11850, // 8000 2 6 317, 160, 8, 15850, // 8000 2 7 317, 160, 8, 15850, // 8000 2 8 381, 160, 3, 19066, // 8000 2 9 509, 160, 3, 25466, // 8000 2 10 79, 320, 8, 3950, // 16000 1 0 115, 320, 8, 5750, // 16000 1 1 155, 320, 8, 7750, // 16000 1 2 196, 320, 2, 9800, // 16000 1 3 256, 320, 1, 12800, // 16000 1 4 336, 320, 1, 16800, // 16000 1 5 412, 320, 2, 20600, // 16000 1 6 476, 320, 2, 23800, // 16000 1 7 556, 320, 2, 27800, // 16000 1 8 684, 320, 2, 34200, // 16000 1 9 844, 320, 2, 42200, // 16000 1 10 96, 320, 1, 4800, // 16000 2 0 132, 320, 2, 6600, // 16000 2 1 172, 320, 2, 8600, // 16000 2 2 213, 320, 8, 10650, // 16000 2 3 273, 320, 7, 13657, // 16000 2 4 353, 320, 6, 17666, // 16000 2 5 429, 320, 3, 21466, // 16000 2 6 493, 320, 3, 24666, // 16000 2 7 573, 320, 3, 28666, // 16000 2 8 701, 320, 3, 35066, // 16000 2 9 861, 320, 3, 43066, // 16000 2 10 83, 640, 8, 4150, // 32000 1 0 151, 640, 8, 7550, // 32000 1 1 191, 640, 8, 9550, // 32000 1 2 232, 640, 1, 11600, // 32000 1 3 292, 640, 2, 14600, // 32000 1 4 372, 640, 2, 18600, // 32000 1 5 448, 640, 1, 22400, // 32000 1 6 512, 640, 1, 25600, // 32000 1 7 592, 640, 1, 29600, // 32000 1 8 720, 640, 1, 36000, // 32000 1 9 880, 640, 1, 44000, // 32000 1 10 100, 640, 2, 5000, // 32000 2 0 168, 640, 1, 8400, // 32000 2 1 208, 640, 1, 10400, // 32000 2 2 249, 640, 7, 12457, // 32000 2 3 309, 640, 8, 15450, // 32000 2 4 389, 640, 3, 19466, // 32000 2 5 465, 640, 6, 23266, // 32000 2 6 529, 640, 6, 26466, // 32000 2 7 609, 640, 5, 30480, // 32000 2 8 737, 640, 5, 36880, // 32000 2 9 897, 640, 5, 44880, // 32000 2 10 }; */ jspeex/src/java/org/xiph/speex/RawWriter.java0000644000175000017500000001104010135761046021475 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: RawWriter.java * * * * Author: Marc GIMPEL * * * * Date: 6th January 2004 * * * ******************************************************************************/ /* $Id: RawWriter.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ package org.xiph.speex; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.FileOutputStream; /** * Raw Audio File Writer. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class RawWriter extends AudioFileWriter { private OutputStream out; /** * Closes the output file. * @exception IOException if there was an exception closing the Audio Writer. */ public void close() throws IOException { out.close(); } /** * Open the output file. * @param file - file to open. * @exception IOException if there was an exception opening the Audio Writer. */ public void open(final File file) throws IOException { file.delete(); out = new FileOutputStream(file); } /** * Open the output file. * @param filename - file to open. * @exception IOException if there was an exception opening the Audio Writer. */ public void open(final String filename) throws IOException { open(new File(filename)); } /** * Writes the header pages that start the Ogg Speex file. * Prepares file for data to be written. * @param comment description to be included in the header. * @exception IOException */ public void writeHeader(final String comment) throws IOException { // a raw audio file has no header } /** * Writes a packet of audio. * @param data audio data * @param offset the offset from which to start reading the data. * @param len the length of data to read. * @exception IOException */ public void writePacket(final byte[] data, final int offset, final int len) throws IOException { out.write(data, offset, len); } } jspeex/src/java/org/xiph/speex/SbCodec.java0000644000175000017500000001775210135761046021071 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: SbCodec.java * * * * Author: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: 14th July 2003 * * * ******************************************************************************/ /* $Id: SbCodec.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ package org.xiph.speex; /** * Sideband Codec. * This class contains all the basic structures needed by the Sideband * encoder and decoder. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class SbCodec extends NbCodec { //--------------------------------------------------------------------------- // Constants //--------------------------------------------------------------------------- /** The Sideband Frame Size gives the size in bits of a Sideband frame for a given sideband submode. */ public static final int[] SB_FRAME_SIZE = {4, 36, 112, 192, 352, -1, -1, -1}; /** The Sideband Submodes gives the number of submodes possible for the Sideband codec. */ public static final int SB_SUBMODES = 8; /** The Sideband Submodes Bits gives the number bits used to encode the Sideband Submode*/ public static final int SB_SUBMODE_BITS = 3; /** Quadratic Mirror Filter Order */ public static final int QMF_ORDER = 64; //--------------------------------------------------------------------------- // Parameters //--------------------------------------------------------------------------- /** */ protected int fullFrameSize; /** */ protected float foldingGain; //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- /** */ protected float[] high; /** */ protected float[] y0, y1; /** */ protected float[] x0d; /** */ protected float[] g0_mem, g1_mem; /** * Wideband initialisation */ public void wbinit() { // Initialize SubModes submodes = buildWbSubModes(); submodeID = 3; // Initialize narrwoband parameters and variables //init(160, 40, 8, 640, .9f); } /** * Ultra-wideband initialisation */ public void uwbinit() { // Initialize SubModes submodes = buildUwbSubModes(); submodeID = 1; // Initialize narrwoband parameters and variables //init(320, 80, 8, 1280, .7f); } /** * Initialisation * @param frameSize * @param subframeSize * @param lpcSize * @param bufSize * @param foldingGain */ protected void init(final int frameSize, final int subframeSize, final int lpcSize, final int bufSize, final float foldingGain) { super.init(frameSize, subframeSize, lpcSize, bufSize); this.fullFrameSize = 2*frameSize; this.foldingGain = foldingGain; lag_factor = 0.002f; high = new float[fullFrameSize]; y0 = new float[fullFrameSize]; y1 = new float[fullFrameSize]; x0d = new float[frameSize]; g0_mem = new float[QMF_ORDER]; g1_mem = new float[QMF_ORDER]; } /** * Build wideband submodes. * @return the wideband submodes. */ protected static SubMode[] buildWbSubModes() { /* Initialize Long Term Predictions */ HighLspQuant highLU = new HighLspQuant(); /* Initialize Codebook Searches */ SplitShapeSearch ssCbHighLbrSearch = new SplitShapeSearch(40, 10, 4, hexc_10_32_table, 5, 0); SplitShapeSearch ssCbHighSearch = new SplitShapeSearch(40, 8, 5, hexc_table, 7, 1); /* Initialize wide-band modes */ SubMode[] wbSubModes = new SubMode[SB_SUBMODES]; wbSubModes[1] = new SubMode(0, 0, 1, 0, highLU, null, null, .75f, .75f, -1, 36); wbSubModes[2] = new SubMode(0, 0, 1, 0, highLU, null, ssCbHighLbrSearch, .85f, .6f, -1, 112); wbSubModes[3] = new SubMode(0, 0, 1, 0, highLU, null, ssCbHighSearch, .75f, .7f, -1, 192); wbSubModes[4] = new SubMode(0, 0, 1, 1, highLU, null, ssCbHighSearch, .75f, .75f, -1, 352); return wbSubModes; } /** * Build ultra-wideband submodes. * @return the ultra-wideband submodes. */ protected static SubMode[] buildUwbSubModes() { /* Initialize Long Term Predictions */ HighLspQuant highLU = new HighLspQuant(); SubMode[] uwbSubModes = new SubMode[SB_SUBMODES]; uwbSubModes[1] = new SubMode(0, 0, 1, 0, highLU, null, null, .75f, .75f, -1, 2); return uwbSubModes; } /** * Returns the size of a frame (ex: 160 samples for a narrowband frame, * 320 for wideband and 640 for ultra-wideband). * @return the size of a frame (number of audio samples in a frame). */ public int getFrameSize() { return fullFrameSize; } /** * Returns whether or not we are using Discontinuous Transmission encoding. * @return whether or not we are using Discontinuous Transmission encoding. */ public boolean getDtx() { // TODO - should return DTX for the NbCodec return dtx_enabled != 0; } /** * Returns the excitation array. * @return the excitation array. */ public float[] getExc() { int i; float[] excTmp = new float[fullFrameSize]; for (i=0;iexc, st->interp_qlpc, st->high, st->frame_size, st->lpcSize, st->mem_sp);*/ /* Reconstruct the original */ filters.fir_mem_up(x0d, h0, y0, fullFrameSize, QMF_ORDER, g0_mem); filters.fir_mem_up(high, h1, y1, fullFrameSize, QMF_ORDER, g1_mem); for (i=0;i 0) { /* Only adapt if long-term and short-term drift are the same sign */ qual_change = -.00001f*abr_drift/(1+abr_count); if (qual_change>.1f) qual_change=.1f; if (qual_change<-.1f) qual_change=-.1f; } vbr_quality += qual_change; if (vbr_quality>10) vbr_quality=10; if (vbr_quality<0) vbr_quality=0; } for (i=0;i2) ratio=2; /*if (ratio>-2)*/ if (vbr_enabled != 0) { int modeid; modeid = nb_modes-1; relative_quality+=1.0*(ratio+2); if (relative_quality<-1) { relative_quality=-1; } while (modeid != 0) { int v1; float thresh; v1=(int)Math.floor(vbr_quality); if (v1==10) thresh = Vbr.hb_thresh[modeid][v1]; else thresh = (vbr_quality-v1) * Vbr.hb_thresh[modeid][v1+1] + (1+v1-vbr_quality) * Vbr.hb_thresh[modeid][v1]; if (relative_quality >= thresh) break; modeid--; } setMode(modeid); if (abr_enabled != 0) { int bitrate; bitrate = getBitRate(); abr_drift+=(bitrate-abr_enabled); abr_drift2 = .95f*abr_drift2 + .05f*(bitrate-abr_enabled); abr_count += 1.0; } } else { /* VAD only */ int modeid; if (relative_quality<2.0) modeid=1; else modeid=submodeSelect; /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/ submodeID=modeid; } /*fprintf (stderr, "%f %f\n", ratio, low_qual);*/ } bits.pack(1, 1); if (dtx != 0) bits.pack(0, SB_SUBMODE_BITS); else bits.pack(submodeID, SB_SUBMODE_BITS); /* If null mode (no transmission), just set a couple things to zero*/ if (dtx != 0 || submodes[submodeID] == null) { for (i=0; i31) quant=31; bits.pack(quant, 5); g=(float)(.1*Math.exp(quant/9.4)); } /*printf ("folding gain: %f\n", g);*/ g /= filter_ratio; } else { float gc, scale, scale_1; for (i=0; i15) qgc=15; bits.pack(qgc, 4); gc = (float) Math.exp((1/3.7)*qgc-2); } scale = gc*(float)Math.sqrt(1+el)/filter_ratio; scale_1 = 1/scale; for (i=0; isubframeSize, "\ntarget");*/ submodes[submodeID].innovation.quant(target, interp_qlpc, bw_lpc1, bw_lpc2, lpcSize, subframeSize, innov, 0, syn_resp, bits, (complexity+1)>>1); /*print_vec(target, st->subframeSize, "after");*/ for (i=0; i>1); for (i=0; i 10) { quality = 10; } if (uwb) { lowenc.setQuality(quality); this.setMode(UWB_QUALITY_MAP[quality]); } else { lowenc.setMode(NB_QUALITY_MAP[quality]); this.setMode(WB_QUALITY_MAP[quality]); } } /** * Sets the Varible Bit Rate Quality. * @param quality */ public void setVbrQuality(float quality) { vbr_quality = quality; float qual = quality + 0.6f; if (qual>10) qual=10; lowenc.setVbrQuality(qual); int q = (int)Math.floor(.5+quality); if (q>10) q=10; setQuality(q); } /** * Sets whether or not to use Variable Bit Rate encoding. * @param vbr */ public void setVbr(final boolean vbr) { // super.setVbr(vbr); vbr_enabled = vbr ? 1 : 0; lowenc.setVbr(vbr); } /** * Sets the Average Bit Rate. * @param abr */ public void setAbr(final int abr) { lowenc.setVbr(true); // super.setAbr(abr); abr_enabled = (abr!=0) ? 1 : 0; vbr_enabled = 1; { int i=10, rate, target; float vbr_qual; target = abr; while (i>=0) { setQuality(i); rate = getBitRate(); if (rate <= target) break; i--; } vbr_qual=i; if (vbr_qual<0) vbr_qual=0; setVbrQuality(vbr_qual); abr_count=0; abr_drift=0; abr_drift2=0; } } /** * Returns the bitrate. * @return the bitrate. */ public int getBitRate() { if (submodes[submodeID] != null) return lowenc.getBitRate() + sampling_rate*submodes[submodeID].bits_per_frame/frameSize; else return lowenc.getBitRate() + sampling_rate*(SB_SUBMODE_BITS+1)/frameSize; } /** * Sets the sampling rate. * @param rate */ public void setSamplingRate(final int rate) { // super.setSamplingRate(rate); sampling_rate = rate; lowenc.setSamplingRate(rate); } /** * Return LookAhead. * @return LookAhead. */ public int getLookAhead() { return 2*lowenc.getLookAhead() + QMF_ORDER - 1; } /** * */ // public void resetState() // { // } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- /** * Sets the encoding submode. * @param mode */ public void setMode(int mode) { if (mode < 0) { mode = 0; } submodeID = submodeSelect = mode; } /** * Returns the encoding submode currently in use. * @return the encoding submode currently in use. */ public int getMode() { return submodeID; } /** * Sets the bitrate. * @param bitrate */ public void setBitRate(final int bitrate) { for (int i=10; i>=0; i--) { setQuality(i); if (getBitRate() <= bitrate) return; } } /** * Returns whether or not we are using Variable Bit Rate encoding. * @return whether or not we are using Variable Bit Rate encoding. */ public boolean getVbr() { return vbr_enabled != 0; } /** * Sets whether or not to use Voice Activity Detection encoding. * @param vad */ public void setVad(final boolean vad) { vad_enabled = vad ? 1 : 0; } /** * Returns whether or not we are using Voice Activity Detection encoding. * @return whether or not we are using Voice Activity Detection encoding. */ public boolean getVad() { return vad_enabled != 0; } /** * Sets whether or not to use Discontinuous Transmission encoding. * @param dtx */ public void setDtx(final boolean dtx) { dtx_enabled = dtx ? 1 : 0; } /** * Returns the Average Bit Rate used (0 if ABR is not turned on). * @return the Average Bit Rate used (0 if ABR is not turned on). */ public int getAbr() { return abr_enabled; } /** * Returns the Varible Bit Rate Quality. * @return the Varible Bit Rate Quality. */ public float getVbrQuality() { return vbr_quality; } /** * Sets the algorthmic complexity. * @param complexity */ public void setComplexity(int complexity) { if (complexity < 0) complexity = 0; if (complexity > 10) complexity = 10; this.complexity = complexity; } /** * Returns the algorthmic complexity. * @return the algorthmic complexity. */ public int getComplexity() { return complexity; } /** * Returns the sampling rate. * @return the sampling rate. */ public int getSamplingRate() { return sampling_rate; } /** * Returns the relative quality. * @return the relative quality. */ public float getRelativeQuality() { return relative_quality; } } jspeex/src/java/org/xiph/speex/SpeexDecoder.java0000644000175000017500000002452410245616612022134 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: SpeexDecoder.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: SpeexDecoder.java,v 1.4 2005/05/27 13:15:54 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; import java.io.StreamCorruptedException; /** * Main Speex Decoder class. * This class decodes the given Speex packets into PCM 16bit samples. * *

Here's an example that decodes and recovers one Speex packet. *

 * SpeexDecoder speexDecoder = new SpeexDecoder();
 * speexDecoder.processData(data, packetOffset, packetSize);
 * byte[] decoded = new byte[speexDecoder.getProcessedBataByteSize()];
 * speexDecoder.getProcessedData(decoded, 0);
 * 
* * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.4 $ */ public class SpeexDecoder { /** * Version of the Speex Decoder */ public static final String VERSION = "Java Speex Decoder v0.9.7 ($Revision: 1.4 $)"; private int sampleRate; private int channels; private float[] decodedData; private short[] outputData; private int outputSize; private Bits bits; private Decoder decoder; private int frameSize; /** * Constructor */ public SpeexDecoder() { bits = new Bits(); sampleRate = 0; channels = 0; } /** * Initialise the Speex Decoder. * @param mode the mode of the decoder (0=NB, 1=WB, 2=UWB). * @param sampleRate the number of samples per second. * @param channels the number of audio channels (1=mono, 2=stereo, ...). * @param enhanced whether to enable perceptual enhancement or not. * @return true if initialisation successful. */ public boolean init(final int mode, final int sampleRate, final int channels, final boolean enhanced) { switch (mode) { case 0: decoder = new NbDecoder(); ((NbDecoder)decoder).nbinit(); break; //Wideband case 1: decoder = new SbDecoder(); ((SbDecoder)decoder).wbinit(); break; case 2: decoder = new SbDecoder(); ((SbDecoder)decoder).uwbinit(); break; //*/ default: return false; } /* initialize the speex decoder */ decoder.setPerceptualEnhancement(enhanced); /* set decoder format and properties */ this.frameSize = decoder.getFrameSize(); this.sampleRate = sampleRate; this.channels = channels; int secondSize = sampleRate*channels; decodedData = new float[secondSize*2]; outputData = new short[secondSize*2]; outputSize = 0; bits.init(); return true; } /** * Returns the sample rate. * @return the sample rate. */ public int getSampleRate() { return sampleRate; } /** * Returns the number of channels. * @return the number of channels. */ public int getChannels() { return channels; } /** * Pull the decoded data out into a byte array at the given offset * and returns the number of bytes processed and just read. * @param data * @param offset * @return the number of bytes processed and just read. */ public int getProcessedData(final byte[] data, final int offset) { if (outputSize<=0) { return outputSize; } for (int i=0; i> 8) & 0xff ); } int size = outputSize*2; outputSize = 0; return size; } /** * Pull the decoded data out into a short array at the given offset * and returns tne number of shorts processed and just read * @param data * @param offset * @return the number of samples processed and just read. */ public int getProcessedData(final short[] data, final int offset) { if (outputSize<=0) { return outputSize; } System.arraycopy(outputData, 0, data, offset, outputSize); int size = outputSize; outputSize = 0; return size; } /** * Returns the number of bytes processed and ready to be read. * @return the number of bytes processed and ready to be read. */ public int getProcessedDataByteSize() { return (outputSize*2); } /** * This is where the actual decoding takes place * @param data - the Speex data (frame) to decode. * If it is null, the packet is supposed lost. * @param offset - the offset from which to start reading the data. * @param len - the length of data to read (Speex frame size). * @throws StreamCorruptedException If the input stream is invalid. */ public void processData(final byte[] data, final int offset, final int len) throws StreamCorruptedException { if (data == null) { processData(true); } else { /* read packet bytes into bitstream */ bits.read_from(data, offset, len); processData(false); } } /** * This is where the actual decoding takes place. * @param lost - true if the Speex packet has been lost. * @throws StreamCorruptedException If the input stream is invalid. */ public void processData(final boolean lost) throws StreamCorruptedException { int i; /* decode the bitstream */ if (lost) decoder.decode(null, decodedData); else decoder.decode(bits, decodedData); if (channels == 2) decoder.decodeStereo(decodedData, frameSize); /* PCM saturation */ for (i=0; i32767.0f) decodedData[i]=32767.0f; else if (decodedData[i]<-32768.0f) decodedData[i]=-32768.0f; } /* convert to short and save to buffer */ for (i=0; i0) ? (short) (decodedData[i]+.5) : (short) (decodedData[i]-.5); } } } jspeex/src/java/org/xiph/speex/SpeexEncoder.java0000644000175000017500000002564310245616612022151 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: SpeexEncoder.java * * * * Author: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: 9th April 2003 * * * ******************************************************************************/ /* $Id: SpeexEncoder.java,v 1.6 2005/05/27 13:15:54 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Main Speex Encoder class. * This class encodes the given PCM 16bit samples into Speex packets. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.6 $ */ public class SpeexEncoder { /** * Version of the Speex Encoder */ public static final String VERSION = "Java Speex Encoder v0.9.7 ($Revision: 1.6 $)"; private Encoder encoder; private Bits bits; private float[] rawData; private int sampleRate; private int channels; private int frameSize; /** * Constructor */ public SpeexEncoder() { bits = new Bits(); } /** * Initialisation * @param mode the mode of the encoder (0=NB, 1=WB, 2=UWB). * @param quality the quality setting of the encoder (between 0 and 10). * @param sampleRate the number of samples per second. * @param channels the number of audio channels (1=mono, 2=stereo, ...). * @return true if initialisation successful. */ public boolean init(final int mode, final int quality, final int sampleRate, final int channels) { switch (mode) { case 0: encoder = new NbEncoder(); ((NbEncoder)encoder).nbinit(); break; //Wideband case 1: encoder = new SbEncoder(); ((SbEncoder)encoder).wbinit(); break; case 2: encoder = new SbEncoder(); ((SbEncoder)encoder).uwbinit(); break; //*/ default: return false; } /* initialize the speex decoder */ encoder.setQuality(quality); /* set decoder format and properties */ this.frameSize = encoder.getFrameSize(); this.sampleRate = sampleRate; this.channels = channels; rawData = new float[channels*frameSize]; bits.init(); return true; } /** * Returns the Encoder being used (Narrowband, Wideband or Ultrawideband). * @return the Encoder being used (Narrowband, Wideband or Ultrawideband). */ public Encoder getEncoder() { return encoder; } /** * Returns the sample rate. * @return the sample rate. */ public int getSampleRate() { return sampleRate; } /** * Returns the number of channels. * @return the number of channels. */ public int getChannels() { return channels; } /** * Returns the size of a frame. * @return the size of a frame. */ public int getFrameSize() { return frameSize; } /** * Pull the decoded data out into a byte array at the given offset * and returns the number of bytes of encoded data just read. * @param data * @param offset * @return the number of bytes of encoded data just read. */ public int getProcessedData(final byte[] data, final int offset) { int size = bits.getBufferSize(); System.arraycopy(bits.getBuffer(), 0, data, offset, size); bits.init(); return size; } /** * Returns the number of bytes of encoded data ready to be read. * @return the number of bytes of encoded data ready to be read. */ public int getProcessedDataByteSize() { return bits.getBufferSize(); } /** * This is where the actual encoding takes place * @param data * @param offset * @param len * @return true if successful. */ public boolean processData(final byte[] data, final int offset, final int len) { // converty raw bytes into float samples mapPcm16bitLittleEndian2Float(data, offset, rawData, 0, len/2); // encode the bitstream return processData(rawData, len/2); } /** * Encode an array of shorts. * @param data * @param offset * @param numShorts * @return true if successful. */ public boolean processData(final short[] data, final int offset, final int numShorts) { int numSamplesRequired = channels * frameSize; if (numShorts != numSamplesRequired) { throw new IllegalArgumentException("SpeexEncoder requires " + numSamplesRequired + " samples to process a Frame, not " + numShorts); } // convert shorts into float samples, for (int i=0; i *
  • Java uses big endian for shorts and ints, and Windows uses little Endian. * Therefore, shorts and ints must be read as sequences of bytes and * combined with shifting operations. * * @param pcm16bitBytes - byte array of linear 16-bit PCM formated audio. * @param offsetInput * @param samples - float array to receive the 16-bit linear audio samples. * @param offsetOutput * @param length */ public static void mapPcm16bitLittleEndian2Float(final byte[] pcm16bitBytes, final int offsetInput, final float[] samples, final int offsetOutput, final int length) { if (pcm16bitBytes.length - offsetInput < 2 * length) { throw new IllegalArgumentException("Insufficient Samples to convert to floats"); } if (samples.length - offsetOutput < length) { throw new IllegalArgumentException("Insufficient float buffer to convert the samples"); } for (int i = 0; i < length; i++) { samples[offsetOutput+i] = (float)((pcm16bitBytes[offsetInput+2*i] & 0xff) | (pcm16bitBytes[offsetInput+2*i+1] << 8)); // no & 0xff at the end to keep the sign } } } jspeex/src/java/org/xiph/speex/SplitShapeSearch.java0000644000175000017500000003221110135761046022754 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: SplitShapeSearch.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: SplitShapeSearch.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Split shape codebook search * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class SplitShapeSearch extends CbSearch { /** */ public static final int MAX_COMPLEXITY = 10; private int subframesize; private int subvect_size; private int nb_subvect; private int[] shape_cb; private int shape_cb_size; private int shape_bits; private int have_sign; private int[] ind; private int[] signs; // Varibles used by the encoder private float[] t, e, E, r2; private float[][] ot, nt; private int[][] nind, oind; /** * Constructor * @param subframesize * @param subvect_size * @param nb_subvect * @param shape_cb * @param shape_bits * @param have_sign */ public SplitShapeSearch(final int subframesize, final int subvect_size, final int nb_subvect, final int[] shape_cb, final int shape_bits, final int have_sign) { this.subframesize = subframesize; this.subvect_size = subvect_size; this.nb_subvect = nb_subvect; this.shape_cb = shape_cb; this.shape_bits = shape_bits; this.have_sign = have_sign; this.ind = new int[nb_subvect]; this.signs = new int[nb_subvect]; shape_cb_size = 1<10) N=10; resp = new float[shape_cb_size*subvect_size]; best_index = new int[N]; best_dist = new float[N]; ndist = new float[N]; odist = new float[N]; for (i=0;i=shape_cb_size) { sign = -1; rind -= shape_cb_size; } res = rind*subvect_size; if (sign>0) for (m=0;m=shape_cb_size) { sign = -1; rind -= shape_cb_size; } g = sign*0.03125f*shape_cb[rind*subvect_size+m]; q = subvect_size-m; for (n=offset+subvect_size; nm; n--) { for (q=offset+subvect_size; q= shape_cb_size) { sign = -1; rind -= shape_cb_size; } for (j=0; j0) bits.pack(0, 1); else bits.pack(1, 1); balance=(float) Math.floor(.5f+Math.abs(balance)); if (balance>30) balance=31; bits.pack((int)balance, 5); /*Quantize energy ratio*/ tmp=VQ.index(e_ratio, e_ratio_quant, 4); bits.pack(tmp, 2); } /** * Transforms a mono frame into a stereo frame using intensity stereo info. * @param data - float array of size 2*frameSize, that contains the mono * audio samples in the first half. When the function has completed, the * array will contain the interlaced stereo audio samples. * @param frameSize - the size of a frame of mono audio samples. */ public void decode(final float[] data, final int frameSize) { int i; float e_tot=0, e_left, e_right, e_sum; for (i=frameSize-1; i>=0; i--) { e_tot += data[i]*data[i]; } e_sum=e_tot/e_ratio; e_left = e_sum*balance / (1+balance); e_right = e_sum-e_left; e_left = (float)Math.sqrt(e_left/(e_tot+.01f)); e_right = (float)Math.sqrt(e_right/(e_tot+.01f)); for (i=frameSize-1;i>=0;i--) { float ftmp=data[i]; smooth_left = .98f*smooth_left + .02f*e_left; smooth_right = .98f*smooth_right + .02f*e_right; data[2*i] = smooth_left*ftmp; data[2*i+1] = smooth_right*ftmp; } } /** * Callback handler for intensity stereo info * @param bits - Speex bits buffer. */ public void init(Bits bits) { float sign=1; int tmp; if (bits.unpack(1) != 0) sign=-1; tmp = bits.unpack(5); balance = (float) Math.exp(sign*.25*tmp); tmp = bits.unpack(2); e_ratio = e_ratio_quant[tmp]; } } jspeex/src/java/org/xiph/speex/SubMode.java0000644000175000017500000001514110135761046021113 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: SubMode.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: SubMode.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Speex SubMode * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class SubMode { /** Set to -1 for "normal" modes, otherwise encode pitch using a global pitch and allowing a +- lbr_pitch variation (for low not-rates)*/ public int lbr_pitch; /** Use the same (forced) pitch gain for all sub-frames */ public int forced_pitch_gain; /** Number of bits to use as sub-frame innovation gain */ public int have_subframe_gain; /** Apply innovation quantization twice for higher quality (and higher bit-rate)*/ public int double_codebook; /** LSP quantization/unquantization function */ public LspQuant lsqQuant; /** Long-term predictor (pitch) un-quantizer */ public Ltp ltp; /** Codebook Search un-quantizer*/ public CbSearch innovation; /** Enhancer constant */ public float lpc_enh_k1; /** Enhancer constant */ public float lpc_enh_k2; /** Gain of enhancer comb filter */ public float comb_gain; /** Number of bits per frame after encoding*/ public int bits_per_frame; /** * Constructor */ public SubMode(final int lbr_pitch, final int forced_pitch_gain, final int have_subframe_gain, final int double_codebook, final LspQuant lspQuant, final Ltp ltp, final CbSearch innovation, final float lpc_enh_k1, final float lpc_enh_k2, final float comb_gain, final int bits_per_frame) { this.lbr_pitch = lbr_pitch; this.forced_pitch_gain = forced_pitch_gain; this.have_subframe_gain = have_subframe_gain; this.double_codebook = double_codebook; this.lsqQuant = lspQuant; this.ltp = ltp; this.innovation = innovation; this.lpc_enh_k1 = lpc_enh_k1; this.lpc_enh_k2 = lpc_enh_k2; this.comb_gain = comb_gain; this.bits_per_frame = bits_per_frame; } } jspeex/src/java/org/xiph/speex/VQ.java0000644000175000017500000002143610135761046020107 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: VQ.java * * * * Author: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: 15th April 2003 * * * ******************************************************************************/ /* $Id: VQ.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin File: vq.c Vector quantization Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * Vector Quantization. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class VQ { /** * Finds the index of the entry in a codebook that best matches the input. * @param in - the value to compare. * @param codebook - the list of values to search through for the best match. * @param entries - the size of the codebook. * @return the index of the entry in a codebook that best matches the input. */ public static final int index(final float in, final float[] codebook, final int entries) { int i; float min_dist=0; int best_index=0; for (i=0;i= 1) && (k > used || dist < best_dist[k-1]); k--) { best_dist[k] = best_dist[k-1]; nbest[k] = nbest[k-1]; } best_dist[k]=dist; nbest[k]=i; used++; } } } /** * Finds the indices of the n-best entries in a codebook with sign * @param in * @param offset * @param codebook * @param len * @param entries * @param E * @param N * @param nbest * @param best_dist */ public static final void nbest_sign(final float[] in, final int offset, final float[] codebook, final int len, final int entries, final float[] E, final int N, final int[] nbest, final float[] best_dist) { int i, j, k, l=0, sign, used=0; for (i=0;i0) { sign=1; dist=-dist; } else { sign=0; } dist += .5*E[i]; if (i= 1) && (k > used || dist < best_dist[k-1]); k--) { best_dist[k]=best_dist[k-1]; nbest[k] = nbest[k-1]; } best_dist[k]=dist; nbest[k]=i; used++; if (sign != 0) nbest[k]+=entries; } } } } jspeex/src/java/org/xiph/speex/Vbr.java0000644000175000017500000003071610135761046020313 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: Vbr.java * * * * Author: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: 19th April 2003 * * * ******************************************************************************/ /* $Id: Vbr.java,v 1.2 2004/10/21 16:21:57 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin File: vbr.c VBR-related routines Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.xiph.speex; /** * This class analyses the signal to help determine what bitrate to use when * the Varible BitRate option has been selected. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.2 $ */ public class Vbr { /** */ public static final int VBR_MEMORY_SIZE = 5; /** */ public static final int MIN_ENERGY = 6000; /** */ public static final float NOISE_POW = 0.3f; /** * Narrowband threshhold table. */ public static final float[][] nb_thresh = { //[9][11] {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* CNG */ { 3.5f, 2.5f, 2.0f, 1.2f, 0.5f, 0.0f, -0.5f, -0.7f, -0.8f, -0.9f, -1.0f}, /* 2 kbps */ {10.0f, 6.5f, 5.2f, 4.5f, 3.9f, 3.5f, 3.0f, 2.5f, 2.3f, 1.8f, 1.0f}, /* 6 kbps */ {11.0f, 8.8f, 7.5f, 6.5f, 5.0f, 3.9f, 3.9f, 3.9f, 3.5f, 3.0f, 1.0f}, /* 8 kbps */ {11.0f, 11.0f, 9.9f, 9.0f, 8.0f, 7.0f, 6.5f, 6.0f, 5.0f, 4.0f, 2.0f}, /* 11 kbps */ {11.0f, 11.0f, 11.0f, 11.0f, 9.5f, 9.0f, 8.0f, 7.0f, 6.5f, 5.0f, 3.0f}, /* 15 kbps */ {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.5f, 8.5f, 8.0f, 6.5f, 4.0f}, /* 18 kbps */ {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.8f, 7.5f, 5.5f}, /* 24 kbps */ { 8.0f, 5.0f, 3.7f, 3.0f, 2.5f, 2.0f, 1.8f, 1.5f, 1.0f, 0.0f, 0.0f} /* 4 kbps */ }; /** * Wideband threshhold table. */ public static final float[][] hb_thresh = { //[5][11] {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* silence */ {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* 2 kbps */ {11.0f, 11.0f, 9.5f, 8.5f, 7.5f, 6.0f, 5.0f, 3.9f, 3.0f, 2.0f, 1.0f}, /* 6 kbps */ {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.5f, 8.7f, 7.8f, 7.0f, 6.5f, 4.0f}, /* 10 kbps */ {11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 11.0f, 9.8f, 7.5f, 5.5f} /* 18 kbps */ }; /** * Ultra-wideband threshhold table. */ public static final float[][] uhb_thresh = { // [2][11] {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f}, /* silence */ { 3.9f, 2.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f} /* 2 kbps */ }; private float energy_alpha; private float average_energy; private float last_energy; private float[] last_log_energy; private float accum_sum; private float last_pitch_coef; private float soft_pitch; private float last_quality; private float noise_level; private float noise_accum; private float noise_accum_count; private int consec_noise; /** * Constructor */ public Vbr() { average_energy = 0; last_energy = 1; accum_sum = 0; energy_alpha = .1f; soft_pitch = 0; last_pitch_coef = 0; last_quality = 0; noise_accum = (float) (.05*Math.pow(MIN_ENERGY, NOISE_POW)); noise_accum_count = .05f; noise_level = noise_accum/noise_accum_count; consec_noise = 0; last_log_energy = new float[VBR_MEMORY_SIZE]; for (int i=0; i *
  • Attacks (positive energy derivative) should be coded with more bits *
  • Stationary voiced segments should receive more bits *
  • Segments with (very) low absolute energy should receive less bits * (maybe only shaped noise?) *
  • DTX for near-zero energy? *
  • Stationary fricative segments should have less bits *
  • Temporal masking: when energy slope is decreasing, decrease the bit-rate *
  • Decrease bit-rate for males (low pitch)? *
  • (wideband only) less bits in the high-band when signal is very * non-stationary (harder to notice high-frequency noise)??? * * @param sig - signal. * @param len - signal length. * @param pitch - signal pitch. * @param pitch_coef - pitch coefficient. * @return quality */ public float analysis(final float[] sig, final int len, final int pitch, final float pitch_coef) { int i; float ener=0, ener1=0, ener2=0; float qual=7; int va; float log_energy; float non_st=0; float voicing; float pow_ener; for (i=0; i>1; i++) ener1 += sig[i]*sig[i]; for (i=len>>1; i1) non_st=1; voicing = 3*(pitch_coef-.4f)*Math.abs(pitch_coef-.4f); average_energy = (1-energy_alpha)*average_energy + energy_alpha*ener; noise_level=noise_accum/noise_accum_count; pow_ener = (float) Math.pow(ener,NOISE_POW); if (noise_accum_count<.06f && ener>MIN_ENERGY) noise_accum = .05f*pow_ener; if ((voicing<.3f && non_st < .2f && pow_ener < 1.2f*noise_level) || (voicing<.3f && non_st < .05f && pow_ener < 1.5f*noise_level) || (voicing<.4f && non_st < .05f && pow_ener < 1.2f*noise_level) || (voicing<0 && non_st < .05f)) { float tmp; va = 0; consec_noise++; if (pow_ener > 3*noise_level) tmp = 3*noise_level; else tmp = pow_ener; if (consec_noise>=4) { noise_accum = .95f*noise_accum + .05f*tmp; noise_accum_count = .95f*noise_accum_count + .05f; } } else { va = 1; consec_noise=0; } if (pow_ener < noise_level && ener>MIN_ENERGY) { noise_accum = .95f*noise_accum + .05f*pow_ener; noise_accum_count = .95f*noise_accum_count + .05f; } /* Checking for very low absolute energy */ if (ener < 30000) { qual -= .7f; if (ener < 10000) qual-=.7f; if (ener < 3000) qual-=.7f; } else { float short_diff, long_diff; short_diff = (float) Math.log((ener+1)/(1+last_energy)); long_diff = (float) Math.log((ener+1)/(1+average_energy)); /*fprintf (stderr, "%f %f\n", short_diff, long_diff);*/ if (long_diff<-5) long_diff=-5; if (long_diff>2) long_diff=2; if (long_diff>0) qual += .6f*long_diff; if (long_diff<0) qual += .5f*long_diff; if (short_diff>0) { if (short_diff>5) short_diff=5; qual += .5f*short_diff; } /* Checking for energy increases */ if (ener2 > 1.6f*ener1) qual += .5f; } last_energy = ener; soft_pitch = .6f*soft_pitch + .4f*pitch_coef; qual += 2.2f*((pitch_coef-.4) + (soft_pitch-.4)); if (qual < last_quality) qual = .5f*qual + .5f*last_quality; if (qual<4) qual=4; if (qual>10) qual=10; /* if (consec_noise>=2) qual-=1.3f; if (consec_noise>=5) qual-=1.3f; if (consec_noise>=12) qual-=1.3f; */ if (consec_noise>=3) qual=4; if (consec_noise != 0) qual -= (float)(1.0 * (Math.log(3.0 + consec_noise)-Math.log(3))); if (qual<0) qual=0; if (ener<60000) { if (consec_noise>2) qual-=(float)(0.5*(Math.log(3.0 + consec_noise)-Math.log(3))); if (ener<10000&&consec_noise>2) qual-=(float)(0.5*(Math.log(3.0 + consec_noise)-Math.log(3))); if (qual<0) qual=0; qual += (float)(.3*Math.log(ener/60000.0)); } if (qual<-1) qual=-1; last_pitch_coef = pitch_coef; last_quality = qual; for (i=VBR_MEMORY_SIZE-1; i>0; i--) last_log_energy[i] = last_log_energy[i-1]; last_log_energy[0] = log_energy; return qual; } } jspeex/src/java/org/xiph/speex/package.html0000644000175000017500000000043010135522576021171 0ustar twernertwerner JSpeex codec Package

    JSpeex codec package.

    It contains all the classes necessary for encoding and decoding Speex files.

    $Id: package.html,v 1.1 2004/10/20 17:50:53 mgimpel Exp $ jspeex/src/java/JSpeexDec.java0000644000175000017500000007075010245616476016523 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: JSpeexDec.java * * * * Author: James LAWRENCE * * Modified by: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: March 2003 * * * ******************************************************************************/ /* $Id: JSpeexDec.java,v 1.4 2005/05/27 13:14:38 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.File; import java.io.IOException; import java.io.EOFException; import java.io.DataInputStream; import java.io.FileInputStream; import java.util.Random; import org.xiph.speex.OggCrc; import org.xiph.speex.NbEncoder; import org.xiph.speex.SbEncoder; import org.xiph.speex.SpeexDecoder; import org.xiph.speex.AudioFileWriter; import org.xiph.speex.PcmWaveWriter; import org.xiph.speex.RawWriter; /** * Java Speex Command Line Decoder. * * Decodes SPX files created by Speex's speexenc utility to WAV entirely in pure java. * Currently this code has been updated to be compatible with release 1.0.3. * * NOTE!!! A number of advanced options are NOT supported. * * -- DTX implemented but untested. * -- Packet loss support implemented but untested. * -- SPX files with more than one comment. * -- Can't force decoder to run at another rate, mode, or channel count. * * @author Jim Lawrence, helloNetwork.com * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.4 $ */ public class JSpeexDec { /** Version of the Speex Encoder */ public static final String VERSION = "Java Speex Command Line Decoder v0.9.7 ($Revision: 1.4 $)"; /** Copyright display String */ public static final String COPYRIGHT = "Copyright (C) 2002-2004 Wimba S.A."; /** Print level for messages : Print debug information */ public static final int DEBUG = 0; /** Print level for messages : Print basic information */ public static final int INFO = 1; /** Print level for messages : Print only warnings and errors */ public static final int WARN = 2; /** Print level for messages : Print only errors */ public static final int ERROR = 3; /** Print level for messages */ protected int printlevel = INFO; /** File format for input or output audio file: Raw */ public static final int FILE_FORMAT_RAW = 0; /** File format for input or output audio file: Ogg */ public static final int FILE_FORMAT_OGG = 1; /** File format for input or output audio file: Wave */ public static final int FILE_FORMAT_WAVE = 2; /** Defines File format for input audio file (Raw, Ogg or Wave). */ protected int srcFormat = FILE_FORMAT_OGG; /** Defines File format for output audio file (Raw or Wave). */ protected int destFormat = FILE_FORMAT_WAVE; /** Random number generator for packet loss simulation. */ protected static Random random = new Random(); /** Speex Decoder */ protected SpeexDecoder speexDecoder; /** Defines whether or not the perceptual enhancement is used. */ protected boolean enhanced = true; /** If input is raw, defines the decoder mode (0=NB, 1=WB and 2-UWB). */ private int mode = 0; /** If input is raw, defines the quality setting used by the encoder. */ private int quality = 8; /** If input is raw, defines the number of frmaes per packet. */ private int nframes = 1; /** If input is raw, defines the sample rate of the audio. */ private int sampleRate = -1; /** */ private float vbr_quality = -1; /** */ private boolean vbr = false; /** If input is raw, defines th number of channels (1=mono, 2=stereo). */ private int channels = 1; /** The percentage of packets to lose in the packet loss simulation. */ private int loss = 0; /** The audio input file */ protected String srcFile; /** The audio output file */ protected String destFile; /** * Builds a plain JSpeex Decoder with default values. */ public JSpeexDec() { } /** * Command line entrance: *

       * Usage: JSpeexDec [options] input_file output_file
       * 
    * @param args Command line parameters. * @exception IOException */ public static void main(final String[] args) throws IOException { JSpeexDec decoder = new JSpeexDec(); if (decoder.parseArgs(args)) { decoder.decode(); } } /** * Parse the command line arguments. * @param args Command line parameters. * @return true if the parsed arguments are sufficient to run the decoder. */ public boolean parseArgs(final String[] args) { // make sure we have command args if (args.length < 2) { if (args.length==1 && (args[0].equals("-v") || args[0].equals("--version"))) { version(); return false; } usage(); return false; } // Determine input, output and file formats srcFile = args[args.length-2]; destFile = args[args.length-1]; if (srcFile.toLowerCase().endsWith(".spx")) { srcFormat = FILE_FORMAT_OGG; } else if (srcFile.toLowerCase().endsWith(".wav")) { srcFormat = FILE_FORMAT_WAVE; } else { srcFormat = FILE_FORMAT_RAW; } if (destFile.toLowerCase().endsWith(".wav")) { destFormat = FILE_FORMAT_WAVE; } else { destFormat = FILE_FORMAT_RAW; } // Determine encoder options for (int i=0; i0 && random.nextInt(100) 0) { writer.writePacket(decdat, 0, decsize); } packetNo++; } } if (chksum != origchksum) throw new IOException("Ogg CheckSums do not match"); } else { // Wave or Raw Speex /* if first packet, initialise everything */ if (packetNo == 0) { if (srcFormat == FILE_FORMAT_WAVE) { // read the WAVE header dis.readFully(header, 0, WAV_HEADERSIZE+4); // make sure its a WAVE header if (!RIFF.equals(new String(header, 0, 4)) && !WAVE.equals(new String(header, 8, 4))) { System.err.println("Not a WAVE file"); return; } // Read other header chunks dis.readFully(header, 0, WAV_HEADERSIZE); String chunk = new String(header, 0, 4); int size = readInt(header, 4); while (!chunk.equals(DATA)) { dis.readFully(header, 0, size); if (chunk.equals(FORMAT)) { /* typedef struct waveformat_extended_tag { WORD wFormatTag; // format type WORD nChannels; // number of channels (i.e. mono, stereo...) DWORD nSamplesPerSec; // sample rate DWORD nAvgBytesPerSec; // for buffer estimation WORD nBlockAlign; // block size of data WORD wBitsPerSample; // Number of bits per sample of mono data WORD cbSize; // The count in bytes of the extra size } WAVEFORMATEX; */ if (readShort(header, 0) != WAVE_FORMAT_SPEEX) { System.err.println("Not a Wave Speex file"); return; } channels = readShort(header, 2); sampleRate = readInt(header, 4); bodybytes = readShort(header, 12); /* The extra data in the wave format are 18 : ACM major version number 19 : ACM minor version number 20-100 : Speex header 100-... : Comment ? */ if (readShort(header, 16) < 82) { System.err.println("Possibly corrupt Speex Wave file."); return; } readSpeexHeader(header, 20, 80); // Display audio info if (printlevel <= DEBUG) { System.out.println("File Format: Wave Speex"); System.out.println("Sample Rate: " + sampleRate); System.out.println("Channels: " + channels); System.out.println("Encoder mode: " + (mode==0 ? "Narrowband" : (mode==1 ? "Wideband" : "UltraWideband"))); System.out.println("Frames per packet: " + nframes); } } dis.readFully(header, 0, WAV_HEADERSIZE); chunk = new String(header, 0, 4); size = readInt(header, 4); } if (printlevel <= DEBUG) System.out.println("Data size: " + size); } else { if (printlevel <= DEBUG) { System.out.println("File Format: Raw Speex"); System.out.println("Sample Rate: " + sampleRate); System.out.println("Channels: " + channels); System.out.println("Encoder mode: " + (mode==0 ? "Narrowband" : (mode==1 ? "Wideband" : "UltraWideband"))); System.out.println("Frames per packet: " + nframes); } /* initialize the Speex decoder */ speexDecoder.init(mode, sampleRate, channels, enhanced); if (!vbr) { switch (mode) { case 0: bodybytes = NbEncoder.NB_FRAME_SIZE[NbEncoder.NB_QUALITY_MAP[quality]]; break; //Wideband case 1: bodybytes = SbEncoder.NB_FRAME_SIZE[SbEncoder.NB_QUALITY_MAP[quality]]; bodybytes += SbEncoder.SB_FRAME_SIZE[SbEncoder.WB_QUALITY_MAP[quality]]; break; case 2: bodybytes = SbEncoder.NB_FRAME_SIZE[SbEncoder.NB_QUALITY_MAP[quality]]; bodybytes += SbEncoder.SB_FRAME_SIZE[SbEncoder.WB_QUALITY_MAP[quality]]; bodybytes += SbEncoder.SB_FRAME_SIZE[SbEncoder.UWB_QUALITY_MAP[quality]]; break; //*/ default: throw new IOException("Illegal mode encoundered."); } bodybytes = (bodybytes + 7) >> 3; } else { // We have read the stream to find out more bodybytes = 0; } } /* initialize the wave writer with output format */ if (destFormat == FILE_FORMAT_WAVE) { writer = new PcmWaveWriter(sampleRate, channels); if (printlevel <= DEBUG) { System.out.println(""); System.out.println("Output File: " + destPath); System.out.println("File Format: PCM Wave"); System.out.println("Perceptual Enhancement: " + enhanced); } } else { writer = new RawWriter(); if (printlevel <= DEBUG) { System.out.println(""); System.out.println("Output File: " + destPath); System.out.println("File Format: Raw Audio"); System.out.println("Perceptual Enhancement: " + enhanced); } } writer.open(destPath); writer.writeHeader(null); packetNo++; } else { dis.readFully(payload, 0, bodybytes); if (loss>0 && random.nextInt(100) 0) { writer.writePacket(decdat, 0, decsize); } packetNo++; } } } } catch (EOFException eof) {} /* close the output file */ writer.close(); } /** * Reads the header packet. *
       *  0 -  7: speex_string: "Speex   "
       *  8 - 27: speex_version: "speex-1.0"
       * 28 - 31: speex_version_id: 1
       * 32 - 35: header_size: 80
       * 36 - 39: rate
       * 40 - 43: mode: 0=narrowband, 1=wb, 2=uwb
       * 44 - 47: mode_bitstream_version: 4
       * 48 - 51: nb_channels
       * 52 - 55: bitrate: -1
       * 56 - 59: frame_size: 160
       * 60 - 63: vbr
       * 64 - 67: frames_per_packet
       * 68 - 71: extra_headers: 0
       * 72 - 75: reserved1
       * 76 - 79: reserved2
       * 
    * @param packet * @param offset * @param bytes * @return */ private boolean readSpeexHeader(final byte[] packet, final int offset, final int bytes) { if (bytes!=80) { System.out.println("Oooops"); return false; } if (!"Speex ".equals(new String(packet, offset, 8))) { return false; } mode = packet[40+offset] & 0xFF; sampleRate = readInt(packet, offset+36); channels = readInt(packet, offset+48); nframes = readInt(packet, offset+64); return speexDecoder.init(mode, sampleRate, channels, enhanced); } /** * Converts Little Endian (Windows) bytes to an int (Java uses Big Endian). * @param data the data to read. * @param offset the offset from which to start reading. * @return the integer value of the reassembled bytes. */ protected static int readInt(final byte[] data, final int offset) { return (data[offset] & 0xff) | ((data[offset+1] & 0xff) << 8) | ((data[offset+2] & 0xff) << 16) | (data[offset+3] << 24); // no 0xff on the last one to keep the sign } /** * Converts Little Endian (Windows) bytes to an short (Java uses Big Endian). * @param data the data to read. * @param offset the offset from which to start reading. * @return the integer value of the reassembled bytes. */ protected static int readShort(final byte[] data, final int offset) { return (data[offset] & 0xff) | (data[offset+1] << 8); // no 0xff on the last one to keep the sign } } jspeex/src/java/JSpeexEnc.java0000644000175000017500000005202110245616500016510 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: JSpeexEnc.java * * * * Author: Marc GIMPEL * * Based on code by: Jean-Marc VALIN * * * * Date: 9th April 2003 * * * ******************************************************************************/ /* $Id: JSpeexEnc.java,v 1.5 2005/05/27 13:14:39 mgimpel Exp $ */ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.File; import java.io.IOException; import java.io.EOFException; import java.io.DataInputStream; import java.io.FileInputStream; import org.xiph.speex.SpeexEncoder; import org.xiph.speex.AudioFileWriter; import org.xiph.speex.OggSpeexWriter; import org.xiph.speex.PcmWaveWriter; import org.xiph.speex.RawWriter; /** * Java Speex Command Line Encoder. * * Currently this code has been updated to be compatible with release 1.0.3. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.5 $ */ public class JSpeexEnc { /** Version of the Speex Encoder */ public static final String VERSION = "Java Speex Command Line Encoder v0.9.7 ($Revision: 1.5 $)"; /** Copyright display String */ public static final String COPYRIGHT = "Copyright (C) 2002-2004 Wimba S.A."; /** Print level for messages : Print debug information */ public static final int DEBUG = 0; /** Print level for messages : Print basic information */ public static final int INFO = 1; /** Print level for messages : Print only warnings and errors */ public static final int WARN = 2; /** Print level for messages : Print only errors */ public static final int ERROR = 3; /** Print level for messages */ protected int printlevel = INFO; /** File format for input or output audio file: Raw */ public static final int FILE_FORMAT_RAW = 0; /** File format for input or output audio file: Ogg */ public static final int FILE_FORMAT_OGG = 1; /** File format for input or output audio file: Wave */ public static final int FILE_FORMAT_WAVE = 2; /** Defines File format for input audio file (Raw, Ogg or Wave). */ protected int srcFormat = FILE_FORMAT_OGG; /** Defines File format for output audio file (Raw or Wave). */ protected int destFormat = FILE_FORMAT_WAVE; /** Defines the encoder mode (0=NB, 1=WB and 2=UWB). */ protected int mode = -1; /** Defines the encoder quality setting (integer from 0 to 10). */ protected int quality = 8; /** Defines the encoders algorithmic complexity. */ protected int complexity = 3; /** Defines the number of frames per speex packet. */ protected int nframes = 1; /** Defines the desired bitrate for the encoded audio. */ protected int bitrate = -1; /** Defines the sampling rate of the audio input. */ protected int sampleRate = -1; /** Defines the number of channels of the audio input (1=mono, 2=stereo). */ protected int channels = 1; /** Defines the encoder VBR quality setting (float from 0 to 10). */ protected float vbr_quality = -1; /** Defines whether or not to use VBR (Variable Bit Rate). */ protected boolean vbr = false; /** Defines whether or not to use VAD (Voice Activity Detection). */ protected boolean vad = false; /** Defines whether or not to use DTX (Discontinuous Transmission). */ protected boolean dtx = false; /** The audio input file */ protected String srcFile; /** The audio output file */ protected String destFile; /** * Builds a plain JSpeex Encoder with default values. */ public JSpeexEnc() { } /** * Command line entrance: *
       * Usage: JSpeexEnc [options] input_file output_file
       * 
    * @param args Command line parameters. * @exception IOException */ public static void main(final String[] args) throws IOException { JSpeexEnc encoder = new JSpeexEnc(); if (encoder.parseArgs(args)) { encoder.encode(); } } /** * Parse the command line arguments. * @param args Command line parameters. * @return true if the parsed arguments are sufficient to run the encoder. */ public boolean parseArgs(final String[] args) { // make sure we have command args if (args.length < 2) { if (args.length==1 && (args[0].equalsIgnoreCase("-v") || args[0].equalsIgnoreCase("--version"))) { version(); return false; } usage(); return false; } // Determine input, output and file formats srcFile = args[args.length-2]; destFile = args[args.length-1]; if (srcFile.toLowerCase().endsWith(".wav")) { srcFormat = FILE_FORMAT_WAVE; } else { srcFormat = FILE_FORMAT_RAW; } if (destFile.toLowerCase().endsWith(".spx")) { destFormat = FILE_FORMAT_OGG; } else if (destFile.toLowerCase().endsWith(".wav")) { destFormat = FILE_FORMAT_WAVE; } else { destFormat = FILE_FORMAT_RAW; } // Determine encoder options for (int i=0; i 0) { speexEncoder.getEncoder().setComplexity(complexity); } if (bitrate > 0) { speexEncoder.getEncoder().setBitRate(bitrate); } if (vbr) { speexEncoder.getEncoder().setVbr(vbr); if (vbr_quality > 0) { speexEncoder.getEncoder().setVbrQuality(vbr_quality); } } if (vad) { speexEncoder.getEncoder().setVad(vad); } if (dtx) { speexEncoder.getEncoder().setDtx(dtx); } // Display info if (printlevel <= DEBUG) { System.out.println(""); System.out.println("Output File: " + destPath); System.out.println("File format: Ogg Speex"); System.out.println("Encoder mode: " + (mode==0 ? "Narrowband" : (mode==1 ? "Wideband" : "UltraWideband"))); System.out.println("Quality: " + (vbr ? vbr_quality : quality)); System.out.println("Complexity: " + complexity); System.out.println("Frames per packet: " + nframes); System.out.println("Varible bitrate: " + vbr); System.out.println("Voice activity detection: " + vad); System.out.println("Discontinouous Transmission: " + dtx); } // Open the file writer AudioFileWriter writer; if (destFormat == FILE_FORMAT_OGG) { writer = new OggSpeexWriter(mode, sampleRate, channels, nframes, vbr); } else if (destFormat == FILE_FORMAT_WAVE) { nframes = PcmWaveWriter.WAVE_FRAME_SIZES[mode-1][channels-1][quality]; writer = new PcmWaveWriter(mode, quality, sampleRate, channels, nframes, vbr); } else { writer = new RawWriter(); } writer.open(destPath); writer.writeHeader("Encoded with: " + VERSION); int pcmPacketSize = 2 * channels * speexEncoder.getFrameSize(); try { // read until we get to EOF while (true) { dis.readFully(temp, 0, nframes*pcmPacketSize); for (int i=0; i 0) { writer.writePacket(temp, 0, encsize); } } } catch (EOFException e) {} writer.close(); dis.close(); } /** * Converts Little Endian (Windows) bytes to an int (Java uses Big Endian). * @param data the data to read. * @param offset the offset from which to start reading. * @return the integer value of the reassembled bytes. */ protected static int readInt(final byte[] data, final int offset) { return (data[offset] & 0xff) | ((data[offset+1] & 0xff) << 8) | ((data[offset+2] & 0xff) << 16) | (data[offset+3] << 24); // no 0xff on the last one to keep the sign } /** * Converts Little Endian (Windows) bytes to an short (Java uses Big Endian). * @param data the data to read. * @param offset the offset from which to start reading. * @return the integer value of the reassembled bytes. */ protected static int readShort(final byte[] data, final int offset) { return (data[offset] & 0xff) | (data[offset+1] << 8); // no 0xff on the last one to keep the sign } } jspeex/src/java/Overview.html0000644000175000017500000000125610135522576016530 0ustar twernertwerner JSpeex Overview

    JSpeex is a Java port of the Speex speech codec (Open Source/Free Software patent-free audio compression format designed for speech).

    It provides both the decoder and the encoder in pure Java, as well as a JavaSound SPI to enable complete and easy integration into Java applications.

    Additional tools include Ant tasks for encoding and decoding Speex files and an example swing player and recorder application and applet.

    $Id: Overview.html,v 1.1 2004/10/20 17:50:53 mgimpel Exp $ jspeex/src/test/0000755000175000017500000000000010245633324014062 5ustar twernertwernerjspeex/src/test/org/0000755000175000017500000000000010245633324014651 5ustar twernertwernerjspeex/src/test/org/xiph/0000755000175000017500000000000010245633324015621 5ustar twernertwernerjspeex/src/test/org/xiph/speex/0000755000175000017500000000000010245633324016745 5ustar twernertwernerjspeex/src/test/org/xiph/speex/spi/0000755000175000017500000000000010245633324017540 5ustar twernertwernerjspeex/src/test/org/xiph/speex/spi/TestInputStreams.java0000644000175000017500000001017310222222252023670 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: TestJSpeexSPI.java * * * * Author: Marc GIMPEL * * * * Date: 25th March 2005 * * * ******************************************************************************/ /* $Id: TestInputStreams.java,v 1.1 2005/03/29 09:49:30 mgimpel Exp $ */ package org.xiph.speex.spi; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * JUnit Tests for JSpeex SPI InputStreams * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.1 $ */ public class TestInputStreams extends TestCase { /** * Constructor * @param arg0 */ public TestInputStreams(String arg0) { super(arg0); } /** * Command line entrance. * @param args */ public static void main(String[] args) { junit.textui.TestRunner.run(TestInputStreams.suite()); } /////////////////////////////////////////////////////////////////////////// // TestCase classes to override /////////////////////////////////////////////////////////////////////////// /** * */ protected void setUp() { } /** * */ protected void tearDown() { } /** * */ // protected void runTest() // { // } /** * Builds the Test Suite. * @return the Test Suite. */ public static Test suite() { return new TestSuite(TestInputStreams.class); } /////////////////////////////////////////////////////////////////////////// // Tests /////////////////////////////////////////////////////////////////////////// /** * Test */ public void testSuccess() { assertTrue("It failed", true); } } jspeex/src/test/org/xiph/speex/spi/TestJSpeexSPI.java0000644000175000017500000001651710222220700023010 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: TestJSpeexSPI.java * * * * Author: Marc GIMPEL * * * * Date: 25th March 2005 * * * ******************************************************************************/ /* $Id: TestJSpeexSPI.java,v 1.1 2005/03/29 09:37:04 mgimpel Exp $ */ package org.xiph.speex.spi; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.xiph.speex.spi.SpeexFileFormatType; /** * JUnit Tests for JSpeex SPI * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.1 $ */ public class TestJSpeexSPI extends TestCase { /** * Constructor * @param arg0 */ public TestJSpeexSPI(String arg0) { super(arg0); } /** * Command line entrance. * @param args */ public static void main(String[] args) { junit.textui.TestRunner.run(TestJSpeexSPI.suite()); } /////////////////////////////////////////////////////////////////////////// // TestCase classes to override /////////////////////////////////////////////////////////////////////////// /** * */ protected void setUp() { } /** * */ protected void tearDown() { } /** * */ // protected void runTest() // { // } /** * Builds the Test Suite. * @return the Test Suite. */ public static Test suite() { return new TestSuite(TestJSpeexSPI.class); } /////////////////////////////////////////////////////////////////////////// // Tests /////////////////////////////////////////////////////////////////////////// /** * Test */ public void testSuccess() { assertTrue("It failed", true); } /** * Test */ public void testFileSupport() { assertTrue("Speex File Format not supported by JavaSound", AudioSystem.isFileTypeSupported(SpeexFileFormatType.SPEEX)); } /** * Test */ public void testConversionSupport() { assertTrue("Conversion to Speex Q0 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q0, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion to Speex Q1 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q1, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion to Speex Q2 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q2, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion to Speex Q3 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q3, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion to Speex Q4 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q4, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion to Speex Q5 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q5, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion to Speex Q6 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q6, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion to Speex Q7 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q7, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion to Speex Q8 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q8, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion to Speex Q9 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q9, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion to Speex Q10 not supported by JavaSound", AudioSystem.isConversionSupported(SpeexEncoding.SPEEX_Q10, new AudioFormat(8000, 16, 1, true, false))); assertTrue("Conversion from Speex not supported by JavaSound", AudioSystem.isConversionSupported(AudioFormat.Encoding.PCM_SIGNED, new AudioFormat(SpeexEncoding.SPEEX, 8000, -1, 1, -1, -1, false))); } } jspeex/src/test/org/xiph/speex/TestJSpeex.java0000644000175000017500000012072410222220422021636 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: TestJSpeex.java * * * * Author: Marc GIMPEL * * * * Date: 6th January 2004 * * * ******************************************************************************/ /* $Id: TestJSpeex.java,v 1.4 2005/03/29 09:34:09 mgimpel Exp $ */ package org.xiph.speex; import java.util.Arrays; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * JUnit Tests for JSpeex * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.4 $ */ public class TestJSpeex extends TestCase { public final static byte[] ENCODED_SILENCE_NB_Q01_MONO = {70, -99, 102, 0, 1, -100, -25, 57, -50, 114}; public final static byte[] ENCODED_SILENCE_NB_Q02_MONO = {22, -99, 102, 0, 0, -18, -18, 7, 119, 112, 59, -69, -127, -35, -36}; public final static byte[] ENCODED_SILENCE_NB_Q03_MONO = {30, -99, 102, 0, 0, 103, 57, -56, 16, 51, -100, -28, 8, 25, -50, 114, 4, 12, -25, 57}; public final static byte[] ENCODED_SILENCE_NB_Q04_MONO = ENCODED_SILENCE_NB_Q03_MONO; public final static byte[] ENCODED_SILENCE_NB_Q05_MONO = {38, -99, 102, 0, 0, 27, 54, 108, -39, -80, 0, 27, 54, 108, -39, -80, 0, 27, 54, 108, -39, -80, 0, 27, 54, 108, -39, -80}; public final static byte[] ENCODED_SILENCE_NB_Q06_MONO = ENCODED_SILENCE_NB_Q05_MONO; public final static byte[] ENCODED_SILENCE_NB_Q07_MONO = {46, -99, 27, -102, 32, 0, 1, 127, -1, -1, -1, -1, -1, -128, 0, -65, -1, -1, -1, -1, -1, -64, 0, 95, -1, -1, -1, -1, -1, -32, 0, 47, -1, -1, -1, -1, -1, -16}; public final static byte[] ENCODED_SILENCE_NB_Q08_MONO = ENCODED_SILENCE_NB_Q07_MONO; public final static byte[] ENCODED_SILENCE_NB_Q09_MONO = {54, -99, 27, -102, 32, 0, 1, 104, -24, -24, -24, -24, -24, -24, -24, -128, 0, -76, 116, 116, 116, 116, 116, 116, 116, 64, 0, 90, 58, 58, 58, 58, 58, 58, 58, 32, 0, 45, 29, 29, 29, 29, 29, 29, 29, 16}; public final static byte[] ENCODED_SILENCE_NB_Q10_MONO = {62, -99, 27, -102, 32, 0, 1, 127, -1, -1, -1, -1, -1, -37, 109, -74, -37, 109, -74, -128, 0, -65, -1, -1, -1, -1, -1, -19, -74, -37, 109, -74, -37, 64, 0, 95, -1, -1, -1, -1, -1, -10, -37, 109, -74, -37, 109, -96, 0, 47, -1, -1, -1, -1, -1, -5, 109, -74, -37, 109, -74, -48}; public final static byte[] ENCODED_SILENCE_WB_Q01_MONO = {70, -99, 102, 0, 1, -100, -25, 57, -50, 115, 39, 108, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_WB_Q02_MONO = {22, -99, 102, 0, 0, -18, -18, 7, 119, 112, 59, -69, -127, -35, -35, 39, 108, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_WB_Q03_MONO = {30, -99, 102, 0, 0, 103, 57, -56, 16, 51, -100, -28, 8, 25, -50, 114, 4, 12, -25, 57, -109, -74, 0, 0, 0,}; public final static byte[] ENCODED_SILENCE_WB_Q04_MONO = {38, -99, 102, 0, 0, 27, 54, 108, -39, -80, 0, 27, 54, 108, -39, -80, 0, 27, 54, 108, -39, -80, 0, 27, 54, 108, -39, -71, 59, 96, 0, 0}; public final static byte[] ENCODED_SILENCE_WB_Q05_MONO = {46, -99, 27, -102, 32, 0, 1, 127, -1, -1, -1, -1, -1, -128, 0, -65, -1, -1, -1, -1, -1, -64, 0, 95, -1, -1, -1, -1, -1, -32, 0, 47, -1, -1, -1, -1, -1, -7, 59, 96, 0, 0}; public final static byte[] ENCODED_SILENCE_WB_Q06_MONO = {46, -99, 27, -102, 32, 0, 1, 127, -1, -1, -1, -1, -1, -128, 0, -65, -1, -1, -1, -1, -1, -64, 0, 95, -1, -1, -1, -1, -1, -32, 0, 47, -1, -1, -1, -1, -1, -6, 59, 96, -75, -83, 96, -75, -83, 96, -75, -83, 96, -75, -83, 96}; public final static byte[] ENCODED_SILENCE_WB_Q07_MONO = {54, -99, 27, -102, 32, 0, 1, 104, -24, -24, -24, -24, -24, -24, -24, -128, 0, -76, 116, 116, 116, 116, 116, 116, 116, 64, 0, 90, 58, 58, 58, 58, 58, 58, 58, 32, 0, 45, 29, 29, 29, 29, 29, 29, 29, 26, 59, 96, -75, -83, 96, -75, -83, 96, -75, -83, 96, -75, -83, 96}; public final static byte[] ENCODED_SILENCE_WB_Q08_MONO = {54, -99, 27, -102, 32, 0, 1, 104, -24, -24, -24, -24, -24, -24, -24, -128, 0, -76, 116, 116, 116, 116, 116, 116, 116, 64, 0, 90, 58, 58, 58, 58, 58, 58, 58, 32, 0, 45, 29, 29, 29, 29, 29, 29, 29, 27 , 59, 96, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -80, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -80,}; public final static byte[] ENCODED_SILENCE_WB_Q09_MONO = {62, -99, 27, -102, 32, 0, 1, 127, -1, -1, -1, -1, -1, -37, 109, -74, -37, 109, -74, -128, 0, -65, -1, -1, -1, -1, -1, -19, -74, -37, 109, -74, -37, 64, 0, 95, -1, -1, -1, -1, -1, -10, -37, 109, -74, -37, 109, -96, 0, 47, -1, -1, -1, -1, -1, -5, 109, -74, -37, 109, -74, -37, 59, 96, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -80, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -80}; public final static byte[] ENCODED_SILENCE_WB_Q10_MONO = {62, -99, 27, -102, 32, 0, 1, 127, -1, -1, -1, -1, -1, -37, 109, -74, -37, 109, -74, -128, 0, -65, -1, -1, -1, -1, -1, -19, -74, -37, 109, -74, -37, 64, 0, 95, -1, -1, -1, -1, -1, -10, -37, 109, -74, -37, 109, -96, 0, 47, -1, -1, -1, -1, -1, -5, 109, -74, -37, 109, -74, -36, 59, 96, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -78, -78, -78, -78, -78, -80, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -78, -78, -78, -78, -78, -80}; public final static byte[] ENCODED_SILENCE_UWB_Q01_MONO = {70, -99, 102, 0, 1, -100, -25, 57, -50, 115, 39, 108, 0, 0, 18, 118, -64, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q02_MONO = {22, -99, 102, 0, 0, -18, -18, 7, 119, 112, 59, -69, -127, -35, -35, 39, 108, 0, 0, 18, 118, -64, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q03_MONO = {30, -99, 102, 0, 0, 103, 57, -56, 16, 51, -100, -28, 8, 25, -50, 114, 4, 12, -25, 57, -109, -74, 0, 0, 9, 59, 96, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q04_MONO = {38, -99, 102, 0, 0, 27, 54, 108, -39, -80, 0, 27, 54, 108, -39, -80, 0, 27, 54, 108, -39, -80, 0, 27, 54, 108, -39, -71, 59, 96, 0, 0, -109, -74, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q05_MONO = {46, -99, 27, -102, 32, 0, 1, 127, -1, -1, -1, -1, -1, -128, 0, -65, -1, -1, -1, -1, -1, -64, 0, 95, -1, -1, -1, -1, -1, -32, 0, 47, -1, -1, -1, -1, -1, -7, 59, 96, 0, 0, -109, -74, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q06_MONO = {46, -99, 27, -102, 32, 0, 1, 127, -1, -1, -1, -1, -1, -128, 0, -65, -1, -1, -1, -1, -1, -64, 0, 95, -1, -1, -1, -1, -1, -32, 0, 47, -1, -1, -1, -1, -1, -6, 59, 96, -75, -83, 96, -75, -83, 96, -75, -83, 96, -75, -83, 105, 59, 96, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q07_MONO = {54, -99, 27, -102, 32, 0, 1, 104, -24, -24, -24, -24, -24, -24, -24, -128, 0, -76, 116, 116, 116, 116, 116, 116, 116, 64, 0, 90, 58, 58, 58, 58, 58, 58, 58, 32, 0, 45, 29, 29, 29, 29, 29, 29, 29, 26, 59, 96, -75, -83, 96, -75, -83, 96, -75, -83, 96, -75, -83, 105, 59, 96, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q08_MONO = {54, -99, 27, -102, 32, 0, 1, 104, -24, -24, -24, -24, -24, -24, -24, -128, 0, -76, 116, 116, 116, 116, 116, 116, 116, 64, 0, 90, 58, 58, 58, 58, 58, 58, 58, 32, 0, 45, 29, 29, 29, 29, 29, 29, 29, 27, 59, 96, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -80, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -71, 59, 96, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q09_MONO = {62, -99, 27, -102, 32, 0, 1, 127, -1, -1, -1, -1, -1, -37, 109, -74, -37, 109, -74, -128, 0, -65, -1, -1, -1, -1, -1, -19, -74, -37, 109, -74, -37, 64, 0, 95, -1, -1, -1, -1, -1, -10, -37, 109, -74, -37, 109, -96, 0, 47, -1, -1, -1, -1, -1, -5, 109, -74, -37, 109, -74, -37, 59, 96, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -80, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -71, 59, 96, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q10_MONO = {62, -99, 27, -102, 32, 0, 1, 127, -1, -1, -1, -1, -1, -37, 109, -74, -37, 109, -74, -128, 0, -65, -1, -1, -1, -1, -1, -19, -74, -37, 109, -74, -37, 64, 0, 95, -1, -1, -1, -1, -1, -10, -37, 109, -74, -37, 109, -96, 0, 47, -1, -1, -1, -1, -1, -5, 109, -74, -37, 109, -74, -36, 59, 96, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -78, -78, -78, -78, -78, -80, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, -78, -78, -78, -78, -78, -78, -78, -78, -78, -71, 59, 96, 0, 0}; public final static byte[] ENCODED_SILENCE_NB_Q01_STEREO = {116, -64, 35, 78, -77, 0, 0, -50, 115, -100, -25, 57}; public final static byte[] ENCODED_SILENCE_NB_Q02_STEREO = {116, -64, 11, 78, -77, 0, 0, 119, 119, 3, -69, -72, 29, -35, -64, -18, -18}; public final static byte[] ENCODED_SILENCE_NB_Q03_STEREO = {116, -64, 15, 78, -77, 0, 0, 51, -100, -28, 8, 25, -50, 114, 4, 12, -25, 57, 2, 6, 115, -100, -128}; public final static byte[] ENCODED_SILENCE_NB_Q04_STEREO = ENCODED_SILENCE_NB_Q03_STEREO; public final static byte[] ENCODED_SILENCE_NB_Q05_STEREO = {116, -64, 19, 78, -77, 0, 0, 13, -101, 54, 108, -40, 0, 13, -101, 54, 108, -40, 0, 13, -101, 54, 108, -40, 0, 13, -101, 54, 108, -40}; public final static byte[] ENCODED_SILENCE_NB_Q06_STEREO = ENCODED_SILENCE_NB_Q05_STEREO; public final static byte[] ENCODED_SILENCE_NB_Q07_STEREO = {116, -64, 23, 78, -115, -51, 16, 0, 0, -65, -1, -1, -1, -1, -1, -64, 0, 95, -1, -1, -1, -1, -1, -32, 0, 47, -1, -1, -1, -1, -1, -16, 0, 23, -1, -1, -1, -1, -1, -8}; public final static byte[] ENCODED_SILENCE_NB_Q08_STEREO = ENCODED_SILENCE_NB_Q07_STEREO; public final static byte[] ENCODED_SILENCE_NB_Q09_STEREO = {116, -64, 27, 78, -115, -51, 16, 0, 0, -76, 116, 116, 116, 116, 116, 116, 116, 64, 0, 90, 58, 58, 58, 58, 58, 58, 58, 32, 0, 45, 29, 29, 29, 29, 29, 29, 29, 16, 0, 22, -114, -114, -114, -114, -114, -114, -114, -120}; public final static byte[] ENCODED_SILENCE_NB_Q10_STEREO = {116, -64, 31, 78, -115, -51, 16, 0, 0, -65, -1, -1, -1, -1, -1, -19, -74, -37, 109, -74, -37, 64, 0, 95, -1, -1, -1, -1, -1, -10, -37, 109, -74, -37, 109, -96, 0, 47, -1, -1, -1, -1, -1, -5, 109, -74, -37, 109, -74, -48, 0, 23, -1, -1, -1, -1, -1, -3, -74, -37, 109, -74, -37, 104}; public final static byte[] ENCODED_SILENCE_WB_Q01_STEREO = {116, -64, 35, 78, -77, 0, 0, -50, 115, -100, -25, 57, -109, -74, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_WB_Q02_STEREO = {116, -64, 11, 78, -77, 0, 0, 119, 119, 3, -69, -72, 29, -35, -64, -18, -18, -109, -74, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_WB_Q03_STEREO = {116, -64, 15, 78, -77, 0, 0, 51, -100, -28, 8, 25, -50, 114, 4, 12, -25, 57, 2, 6, 115, -100, -55, -37, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_WB_Q04_STEREO = {116, -64, 19, 78, -77, 0, 0, 13, -101, 54, 108, -40, 0, 13, -101, 54, 108, -40, 0, 13, -101, 54, 108, -40, 0, 13, -101, 54, 108, -36, -99, -80, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_WB_Q05_STEREO = {116, -64, 23, 78, -115, -51, 16, 0, 0, -65, -1, -1, -1, -1, -1, -64, 0, 95, -1, -1, -1, -1, -1, -32, 0, 47, -1, -1, -1, -1, -1, -16, 0, 23, -1, -1, -1, -1, -1, -4, -99, -80, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_WB_Q06_STEREO = {116, -64, 23, 78, -115, -51, 16, 0, 0, -65, -1, -1, -1, -1, -1, -64, 0, 95, -1, -1, -1, -1, -1, -32, 0, 47, -1, -1, -1, -1, -1, -16, 0, 23, -1, -1, -1, -1, -1, -3, 29, -80, 90, -42, -80, 90, -42, -80, 90, -42, -80, 90, -42, -80}; public final static byte[] ENCODED_SILENCE_WB_Q07_STEREO = {116, -64, 27, 78, -115, -51, 16, 0, 0, -76, 116, 116, 116, 116, 116, 116, 116, 64, 0, 90, 58, 58, 58, 58, 58, 58, 58, 32, 0, 45, 29, 29, 29, 29, 29, 29, 29, 16, 0, 22, -114, -114, -114, -114, -114, -114, -114, -115, 29, -80, 90, -42, -80, 90, -42, -80, 90, -42, -80, 90, -42, -80}; public final static byte[] ENCODED_SILENCE_WB_Q08_STEREO = {116, -64, 27, 78, -115, -51, 16, 0, 0, -76, 116, 116, 116, 116, 116, 116, 116, 64, 0, 90, 58, 58, 58, 58, 58, 58, 58, 32, 0, 45, 29, 29, 29, 29, 29, 29, 29, 16, 0, 22, -114, -114, -114, -114, -114, -114, -114, -115, -99, -80, 21, -107, -107, -107, -107, -127, 89, 89, 89, 89, 88, 21, -107, -107, -107, -107, -127, 89, 89, 89, 89, 88}; public final static byte[] ENCODED_SILENCE_WB_Q09_STEREO = {116, -64, 31, 78, -115, -51, 16, 0, 0, -65, -1, -1, -1, -1, -1, -19, -74, -37, 109, -74, -37, 64, 0, 95, -1, -1, -1, -1, -1, -10, -37, 109, -74, -37, 109, -96, 0, 47, -1, -1, -1, -1, -1, -5, 109, -74, -37, 109, -74, -48, 0, 23, -1, -1, -1, -1, -1, -3, -74, -37, 109, -74, -37, 109, -99, -80, 21, -107, -107, -107, -107, -127, 89, 89, 89, 89, 88, 21, -107, -107, -107, -107, -127, 89, 89, 89, 89, 88}; public final static byte[] ENCODED_SILENCE_WB_Q10_STEREO = {116, -64, 31, 78, -115, -51, 16, 0, 0, -65, -1, -1, -1, -1, -1, -19, -74, -37, 109, -74, -37, 64, 0, 95, -1, -1, -1, -1, -1, -10, -37, 109, -74, -37, 109, -96, 0, 47, -1, -1, -1, -1, -1, -5, 109, -74, -37, 109, -74, -48, 0, 23, -1, -1, -1, -1, -1, -3, -74, -37, 109, -74, -37, 110, 29, -80, 21, -107, -107, -107, -107, -107, -107, -107, -107, -107, -127, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 21, -107, -107, -107, -107, -107, -107, -107, -107, -107, -127, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88}; public final static byte[] ENCODED_SILENCE_UWB_Q01_STEREO = {116, -64, 35, 78, -77, 0, 0, -50, 115, -100, -25, 57, -109, -74, 0, 0, 9, 59, 96, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q02_STEREO = {116, -64, 11, 78, -77, 0, 0, 119, 119, 3, -69, -72, 29, -35, -64, -18, -18, -109, -74, 0, 0, 9, 59, 96, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q03_STEREO = {116, -64, 15, 78, -77, 0, 0, 51, -100, -28, 8, 25, -50, 114, 4, 12, -25, 57, 2, 6, 115, -100, -55, -37, 0, 0, 4, -99, -80, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q04_STEREO = {116, -64, 19, 78, -77, 0, 0, 13, -101, 54, 108, -40, 0, 13, -101, 54, 108, -40, 0, 13, -101, 54, 108, -40, 0, 13, -101, 54, 108, -36, -99, -80, 0, 0, 73, -37, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q05_STEREO = {116, -64, 23, 78, -115, -51, 16, 0, 0, -65, -1, -1, -1, -1, -1, -64, 0, 95, -1, -1, -1, -1, -1, -32, 0, 47, -1, -1, -1, -1, -1, -16, 0, 23, -1, -1, -1, -1, -1, -4, -99, -80, 0, 0, 73, -37, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q06_STEREO = {116, -64, 23, 78, -115, -51, 16, 0, 0, -65, -1, -1, -1, -1, -1, -64, 0, 95, -1, -1, -1, -1, -1, -32, 0, 47, -1, -1, -1, -1, -1, -16, 0, 23, -1, -1, -1, -1, -1, -3, 29, -80, 90, -42, -80, 90, -42, -80, 90, -42, -80, 90, -42, -76, -99, -80, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q07_STEREO = {116, -64, 27, 78, -115, -51, 16, 0, 0, -76, 116, 116, 116, 116, 116, 116, 116, 64, 0, 90, 58, 58, 58, 58, 58, 58, 58, 32, 0, 45, 29, 29, 29, 29, 29, 29, 29, 16, 0, 22, -114, -114, -114, -114, -114, -114, -114, -115, 29, -80, 90, -42, -80, 90, -42, -80, 90, -42, -80, 90, -42, -76, -99, -80, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q08_STEREO = {116, -64, 27, 78, -115, -51, 16, 0, 0, -76, 116, 116, 116, 116, 116, 116, 116, 64, 0, 90, 58, 58, 58, 58, 58, 58, 58, 32, 0, 45, 29, 29, 29, 29, 29, 29, 29, 16, 0, 22, -114, -114, -114, -114, -114, -114, -114, -115, -99, -80, 21, -107, -107, -107, -107, -127, 89, 89, 89, 89, 88, 21, -107, -107, -107, -107, -127, 89, 89, 89, 89, 92, -99, -80, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q09_STEREO = {116, -64, 31, 78, -115, -51, 16, 0, 0, -65, -1, -1, -1, -1, -1, -19, -74, -37, 109, -74, -37, 64, 0, 95, -1, -1, -1, -1, -1, -10, -37, 109, -74, -37, 109, -96, 0, 47, -1, -1, -1, -1, -1, -5, 109, -74, -37, 109, -74, -48, 0, 23, -1, -1, -1, -1, -1, -3, -74, -37, 109, -74, -37, 109, -99, -80, 21, -107, -107, -107, -107, -127, 89, 89, 89, 89, 88, 21, -107, -107, -107, -107, -127, 89, 89, 89, 89, 92, -99, -80, 0, 0, 0}; public final static byte[] ENCODED_SILENCE_UWB_Q10_STEREO = {116, -64, 31, 78, -115, -51, 16, 0, 0, -65, -1, -1, -1, -1, -1, -19, -74, -37, 109, -74, -37, 64, 0, 95, -1, -1, -1, -1, -1, -10, -37, 109, -74, -37, 109, -96, 0, 47, -1, -1, -1, -1, -1, -5, 109, -74, -37, 109, -74, -48, 0, 23, -1, -1, -1, -1, -1, -3, -74, -37, 109, -74, -37, 110, 29, -80, 21, -107, -107, -107, -107, -107, -107, -107, -107, -107, -127, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 21, -107, -107, -107, -107, -107, -107, -107, -107, -107, -127, 89, 89, 89, 89, 89, 89, 89, 89, 89, 92, -99, -80, 0, 0, 0}; /** * Constructor * @param arg0 */ public TestJSpeex(String arg0) { super(arg0); } /** * Command line entrance. * @param args */ public static void main(String[] args) { junit.textui.TestRunner.run(TestJSpeex.suite()); } /////////////////////////////////////////////////////////////////////////// // TestCase classes to override /////////////////////////////////////////////////////////////////////////// /** * */ protected void setUp() { } /** * */ protected void tearDown() { } /** * */ // protected void runTest() // { // } /** * Builds the Test Suite. * @return the Test Suite. */ public static Test suite() { return new TestSuite(TestJSpeex.class); } /////////////////////////////////////////////////////////////////////////// // Tests /////////////////////////////////////////////////////////////////////////// /** * Test */ public void testSuccess() { assertTrue("It failed", true); } /** * * @param source * @param bitoffset * @param size * @return */ protected byte[] shiftArray(byte[] source, int bitoffset, int size) { int byteoffset = bitoffset / 8; int bitshift = bitoffset % 8; byte[] dest = new byte[size]; for (int i=0; i<=size-1; i++) { dest[i] = (byte) ((source[byteoffset++]&0xFF) << bitshift); if (byteoffset < source.length) { dest[i] |= (byte) ((source[byteoffset]&0xFF) >>> (8-bitshift)); } } return dest; } /** * * @param source * @param offset * @param size * @return */ protected byte[] subArray(byte[] source, int offset, int size) { byte[] dest = new byte[size]; System.arraycopy(source, offset, dest, 0, size); return dest; } /** * Stereo Encoding encodes the balance on the first 17 bits, then encodes * normally the average signal. In the case of identical signals on each * channel, this is the same thing. Lets test for Silence. */ public void testSilenceStereoConstants() { assertTrue("NB Q=1 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_NB_Q01_STEREO, 17, ENCODED_SILENCE_NB_Q01_MONO.length), ENCODED_SILENCE_NB_Q01_MONO)); assertTrue("NB Q=2 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_NB_Q02_STEREO, 17, ENCODED_SILENCE_NB_Q02_MONO.length), ENCODED_SILENCE_NB_Q02_MONO)); assertTrue("NB Q=3 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_NB_Q03_STEREO, 17, ENCODED_SILENCE_NB_Q03_MONO.length), ENCODED_SILENCE_NB_Q03_MONO)); assertTrue("NB Q=4 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_NB_Q04_STEREO, 17, ENCODED_SILENCE_NB_Q04_MONO.length), ENCODED_SILENCE_NB_Q04_MONO)); assertTrue("NB Q=5 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_NB_Q05_STEREO, 17, ENCODED_SILENCE_NB_Q05_MONO.length), ENCODED_SILENCE_NB_Q05_MONO)); assertTrue("NB Q=6 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_NB_Q06_STEREO, 17, ENCODED_SILENCE_NB_Q06_MONO.length), ENCODED_SILENCE_NB_Q06_MONO)); assertTrue("NB Q=7 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_NB_Q07_STEREO, 17, ENCODED_SILENCE_NB_Q07_MONO.length), ENCODED_SILENCE_NB_Q07_MONO)); assertTrue("NB Q=8 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_NB_Q08_STEREO, 17, ENCODED_SILENCE_NB_Q08_MONO.length), ENCODED_SILENCE_NB_Q08_MONO)); assertTrue("NB Q=9 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_NB_Q09_STEREO, 17, ENCODED_SILENCE_NB_Q09_MONO.length), ENCODED_SILENCE_NB_Q09_MONO)); assertTrue("NB Q=10 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_NB_Q10_STEREO, 17, ENCODED_SILENCE_NB_Q10_MONO.length), ENCODED_SILENCE_NB_Q10_MONO)); assertTrue("WB Q=1 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_WB_Q01_STEREO, 17, ENCODED_SILENCE_WB_Q01_MONO.length), ENCODED_SILENCE_WB_Q01_MONO)); assertTrue("WB Q=2 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_WB_Q02_STEREO, 17, ENCODED_SILENCE_WB_Q02_MONO.length), ENCODED_SILENCE_WB_Q02_MONO)); assertTrue("WB Q=3 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_WB_Q03_STEREO, 17, ENCODED_SILENCE_WB_Q03_MONO.length), ENCODED_SILENCE_WB_Q03_MONO)); assertTrue("WB Q=4 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_WB_Q04_STEREO, 17, ENCODED_SILENCE_WB_Q04_MONO.length), ENCODED_SILENCE_WB_Q04_MONO)); assertTrue("WB Q=5 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_WB_Q05_STEREO, 17, ENCODED_SILENCE_WB_Q05_MONO.length), ENCODED_SILENCE_WB_Q05_MONO)); assertTrue("WB Q=6 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_WB_Q06_STEREO, 17, ENCODED_SILENCE_WB_Q06_MONO.length), ENCODED_SILENCE_WB_Q06_MONO)); assertTrue("WB Q=7 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_WB_Q07_STEREO, 17, ENCODED_SILENCE_WB_Q07_MONO.length), ENCODED_SILENCE_WB_Q07_MONO)); assertTrue("WB Q=8 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_WB_Q08_STEREO, 17, ENCODED_SILENCE_WB_Q08_MONO.length), ENCODED_SILENCE_WB_Q08_MONO)); assertTrue("WB Q=9 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_WB_Q09_STEREO, 17, ENCODED_SILENCE_WB_Q09_MONO.length), ENCODED_SILENCE_WB_Q09_MONO)); assertTrue("WB Q=10 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_WB_Q10_STEREO, 17, ENCODED_SILENCE_WB_Q10_MONO.length), ENCODED_SILENCE_WB_Q10_MONO)); assertTrue("UWB Q=1 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_UWB_Q01_STEREO, 17, ENCODED_SILENCE_UWB_Q01_MONO.length), ENCODED_SILENCE_UWB_Q01_MONO)); assertTrue("UWB Q=2 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_UWB_Q02_STEREO, 17, ENCODED_SILENCE_UWB_Q02_MONO.length), ENCODED_SILENCE_UWB_Q02_MONO)); assertTrue("UWB Q=3 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_UWB_Q03_STEREO, 17, ENCODED_SILENCE_UWB_Q03_MONO.length), ENCODED_SILENCE_UWB_Q03_MONO)); assertTrue("UWB Q=4 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_UWB_Q04_STEREO, 17, ENCODED_SILENCE_UWB_Q04_MONO.length), ENCODED_SILENCE_UWB_Q04_MONO)); assertTrue("UWB Q=5 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_UWB_Q05_STEREO, 17, ENCODED_SILENCE_UWB_Q05_MONO.length), ENCODED_SILENCE_UWB_Q05_MONO)); assertTrue("UWB Q=6 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_UWB_Q06_STEREO, 17, ENCODED_SILENCE_UWB_Q06_MONO.length), ENCODED_SILENCE_UWB_Q06_MONO)); assertTrue("UWB Q=7 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_UWB_Q07_STEREO, 17, ENCODED_SILENCE_UWB_Q07_MONO.length), ENCODED_SILENCE_UWB_Q07_MONO)); assertTrue("UWB Q=8 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_UWB_Q08_STEREO, 17, ENCODED_SILENCE_UWB_Q08_MONO.length), ENCODED_SILENCE_UWB_Q08_MONO)); assertTrue("UWB Q=9 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_UWB_Q09_STEREO, 17, ENCODED_SILENCE_UWB_Q09_MONO.length), ENCODED_SILENCE_UWB_Q09_MONO)); assertTrue("UWB Q=10 Stereo file is wrong", Arrays.equals(shiftArray(ENCODED_SILENCE_UWB_Q10_STEREO, 17, ENCODED_SILENCE_UWB_Q10_MONO.length), ENCODED_SILENCE_UWB_Q10_MONO)); } /** * Speex encodes UWB audio by spliting the signal into 2, and encoding the * lower frequencies as WB, then adding some data for the higher frequencies. * As such, in the case of silence WB and UWB should have the same beginning. */ public void testSilenceModesConstants() { assertTrue("UWB mode inconsistent with WB mode for Q=1", Arrays.equals(subArray(ENCODED_SILENCE_UWB_Q01_MONO, 0, ENCODED_SILENCE_WB_Q01_MONO.length-1), subArray(ENCODED_SILENCE_WB_Q01_MONO, 0, ENCODED_SILENCE_WB_Q01_MONO.length-1))); assertTrue("UWB mode inconsistent with WB mode for Q=2", Arrays.equals(subArray(ENCODED_SILENCE_UWB_Q02_MONO, 0, ENCODED_SILENCE_WB_Q02_MONO.length-1), subArray(ENCODED_SILENCE_WB_Q02_MONO, 0, ENCODED_SILENCE_WB_Q02_MONO.length-1))); assertTrue("UWB mode inconsistent with WB mode for Q=3", Arrays.equals(subArray(ENCODED_SILENCE_UWB_Q03_MONO, 0, ENCODED_SILENCE_WB_Q03_MONO.length-1), subArray(ENCODED_SILENCE_WB_Q03_MONO, 0, ENCODED_SILENCE_WB_Q03_MONO.length-1))); assertTrue("UWB mode inconsistent with WB mode for Q=4", Arrays.equals(subArray(ENCODED_SILENCE_UWB_Q04_MONO, 0, ENCODED_SILENCE_WB_Q04_MONO.length-1), subArray(ENCODED_SILENCE_WB_Q04_MONO, 0, ENCODED_SILENCE_WB_Q04_MONO.length-1))); assertTrue("UWB mode inconsistent with WB mode for Q=5", Arrays.equals(subArray(ENCODED_SILENCE_UWB_Q05_MONO, 0, ENCODED_SILENCE_WB_Q05_MONO.length-1), subArray(ENCODED_SILENCE_WB_Q05_MONO, 0, ENCODED_SILENCE_WB_Q05_MONO.length-1))); assertTrue("UWB mode inconsistent with WB mode for Q=6", Arrays.equals(subArray(ENCODED_SILENCE_UWB_Q06_MONO, 0, ENCODED_SILENCE_WB_Q06_MONO.length-1), subArray(ENCODED_SILENCE_WB_Q06_MONO, 0, ENCODED_SILENCE_WB_Q06_MONO.length-1))); assertTrue("UWB mode inconsistent with WB mode for Q=7", Arrays.equals(subArray(ENCODED_SILENCE_UWB_Q07_MONO, 0, ENCODED_SILENCE_WB_Q07_MONO.length-1), subArray(ENCODED_SILENCE_WB_Q07_MONO, 0, ENCODED_SILENCE_WB_Q07_MONO.length-1))); assertTrue("UWB mode inconsistent with WB mode for Q=8", Arrays.equals(subArray(ENCODED_SILENCE_UWB_Q08_MONO, 0, ENCODED_SILENCE_WB_Q08_MONO.length-1), subArray(ENCODED_SILENCE_WB_Q08_MONO, 0, ENCODED_SILENCE_WB_Q08_MONO.length-1))); assertTrue("UWB mode inconsistent with WB mode for Q=9", Arrays.equals(subArray(ENCODED_SILENCE_UWB_Q09_MONO, 0, ENCODED_SILENCE_WB_Q09_MONO.length-1), subArray(ENCODED_SILENCE_WB_Q09_MONO, 0, ENCODED_SILENCE_WB_Q09_MONO.length-1))); assertTrue("UWB mode inconsistent with WB mode for Q=10", Arrays.equals(subArray(ENCODED_SILENCE_UWB_Q10_MONO, 0, ENCODED_SILENCE_WB_Q10_MONO.length-1), subArray(ENCODED_SILENCE_WB_Q10_MONO, 0, ENCODED_SILENCE_WB_Q10_MONO.length-1))); } /** * Encodes the given Source with the given settings and compares the result * to the expected result. * @param mode * @param quality * @param sampleRate * @param channels * @param source * @param expected */ protected void testEncode(int mode, int quality, int sampleRate, int channels, float[] source, byte[] expected) { SpeexEncoder speexEncoder = new SpeexEncoder(); speexEncoder.init(mode, quality, sampleRate, channels); //speexEncoder.getEncoder().setComplexity(3); //speexEncoder.getEncoder().setBitRate(bitrate); //speexEncoder.getEncoder().setVbr(vbr); //speexEncoder.getEncoder().setVbrQuality(vbr_quality); //speexEncoder.getEncoder().setVad(vad); //speexEncoder.getEncoder().setDtx(dtx); speexEncoder.processData(source, source.length); int actualsize = speexEncoder.getProcessedDataByteSize(); assertEquals("Encoded data is not of the expected size", checkSize(mode, quality, channels, speexEncoder), actualsize); byte[] speex = new byte[actualsize]; speexEncoder.getProcessedData(speex, 0); assertTrue("Encoded data appears wrong", Arrays.equals(expected, speex)); } /** * Calculates the expected size of the returned encoded Speex packet. * @param mode * @param quality * @param channels * @param speexEncoder * @return */ protected int checkSize(int mode, int quality, int channels, SpeexEncoder speexEncoder) { assertEquals("Number of channels don't match", channels, speexEncoder.getChannels()); int bitsize = 0; if (mode == 0) { // Narrowband bitsize = NbCodec.NB_FRAME_SIZE[NbEncoder.NB_QUALITY_MAP[quality]]; assertEquals("SubModes don't match", NbEncoder.NB_QUALITY_MAP[quality], speexEncoder.getEncoder().getMode()); } else if (mode == 1) { // Wideband bitsize = NbCodec.NB_FRAME_SIZE[SbEncoder.NB_QUALITY_MAP[quality]]; bitsize += SbCodec.SB_FRAME_SIZE[SbEncoder.WB_QUALITY_MAP[quality]]; } else if (mode == 2) { // UltraWideband bitsize = NbCodec.NB_FRAME_SIZE[SbEncoder.NB_QUALITY_MAP[quality]]; bitsize += SbCodec.SB_FRAME_SIZE[SbEncoder.WB_QUALITY_MAP[quality]]; bitsize += SbCodec.SB_FRAME_SIZE[SbEncoder.UWB_QUALITY_MAP[quality]]; } assertEquals("Number of encoded bits don't match", bitsize, speexEncoder.getEncoder().getEncodedFrameSize()); if (channels > 1) { bitsize += 17; // 1+4(14=inband)+4(9=stereo)+8(stereo data) } return (bitsize + 7) / 8; } /** * Tests encoding one packet of silence at different quality settings. * * 1 packet NB = 160 samples = 20 ms */ public void testEncodeSilenceNBmono() { testEncode(0, 1, 8000, 1, new float[160], ENCODED_SILENCE_NB_Q01_MONO); testEncode(0, 2, 8000, 1, new float[160], ENCODED_SILENCE_NB_Q02_MONO); testEncode(0, 3, 8000, 1, new float[160], ENCODED_SILENCE_NB_Q03_MONO); testEncode(0, 4, 8000, 1, new float[160], ENCODED_SILENCE_NB_Q04_MONO); testEncode(0, 5, 8000, 1, new float[160], ENCODED_SILENCE_NB_Q05_MONO); testEncode(0, 6, 8000, 1, new float[160], ENCODED_SILENCE_NB_Q06_MONO); testEncode(0, 7, 8000, 1, new float[160], ENCODED_SILENCE_NB_Q07_MONO); testEncode(0, 8, 8000, 1, new float[160], ENCODED_SILENCE_NB_Q08_MONO); testEncode(0, 9, 8000, 1, new float[160], ENCODED_SILENCE_NB_Q09_MONO); testEncode(0, 10, 8000, 1, new float[160], ENCODED_SILENCE_NB_Q10_MONO); } /** * Tests encoding one packet of silence at different quality settings. * * 1 packet WB = 320 samples = 20 ms */ public void testEncodeSilenceWBmono() { testEncode(1, 1, 16000, 1, new float[320], ENCODED_SILENCE_WB_Q01_MONO); testEncode(1, 2, 16000, 1, new float[320], ENCODED_SILENCE_WB_Q02_MONO); testEncode(1, 3, 16000, 1, new float[320], ENCODED_SILENCE_WB_Q03_MONO); testEncode(1, 4, 16000, 1, new float[320], ENCODED_SILENCE_WB_Q04_MONO); testEncode(1, 5, 16000, 1, new float[320], ENCODED_SILENCE_WB_Q05_MONO); testEncode(1, 6, 16000, 1, new float[320], ENCODED_SILENCE_WB_Q06_MONO); testEncode(1, 7, 16000, 1, new float[320], ENCODED_SILENCE_WB_Q07_MONO); testEncode(1, 8, 16000, 1, new float[320], ENCODED_SILENCE_WB_Q08_MONO); testEncode(1, 9, 16000, 1, new float[320], ENCODED_SILENCE_WB_Q09_MONO); testEncode(1, 10, 16000, 1, new float[320], ENCODED_SILENCE_WB_Q10_MONO); } /** * Tests encoding one packet of silence at different quality settings. * * 1 packet UWB = 640 samples = 20 ms */ public void testEncodeSilenceUWBmono() { testEncode(2, 1, 32000, 1, new float[640], ENCODED_SILENCE_UWB_Q01_MONO); testEncode(2, 2, 32000, 1, new float[640], ENCODED_SILENCE_UWB_Q02_MONO); testEncode(2, 3, 32000, 1, new float[640], ENCODED_SILENCE_UWB_Q03_MONO); testEncode(2, 4, 32000, 1, new float[640], ENCODED_SILENCE_UWB_Q04_MONO); testEncode(2, 5, 32000, 1, new float[640], ENCODED_SILENCE_UWB_Q05_MONO); testEncode(2, 6, 32000, 1, new float[640], ENCODED_SILENCE_UWB_Q06_MONO); testEncode(2, 7, 32000, 1, new float[640], ENCODED_SILENCE_UWB_Q07_MONO); testEncode(2, 8, 32000, 1, new float[640], ENCODED_SILENCE_UWB_Q08_MONO); testEncode(2, 9, 32000, 1, new float[640], ENCODED_SILENCE_UWB_Q09_MONO); testEncode(2, 10, 32000, 1, new float[640], ENCODED_SILENCE_UWB_Q10_MONO); } /** * Tests encoding one packet of silence at different quality settings. * * 1 packet NB = 160 samples = 20 ms */ public void testEncodeSilenceNBstereo() { testEncode(0, 1, 8000, 2, new float[320], ENCODED_SILENCE_NB_Q01_STEREO); testEncode(0, 2, 8000, 2, new float[320], ENCODED_SILENCE_NB_Q02_STEREO); testEncode(0, 3, 8000, 2, new float[320], ENCODED_SILENCE_NB_Q03_STEREO); testEncode(0, 4, 8000, 2, new float[320], ENCODED_SILENCE_NB_Q04_STEREO); testEncode(0, 5, 8000, 2, new float[320], ENCODED_SILENCE_NB_Q05_STEREO); testEncode(0, 6, 8000, 2, new float[320], ENCODED_SILENCE_NB_Q06_STEREO); testEncode(0, 7, 8000, 2, new float[320], ENCODED_SILENCE_NB_Q07_STEREO); testEncode(0, 8, 8000, 2, new float[320], ENCODED_SILENCE_NB_Q08_STEREO); testEncode(0, 9, 8000, 2, new float[320], ENCODED_SILENCE_NB_Q09_STEREO); testEncode(0, 10, 8000, 2, new float[320], ENCODED_SILENCE_NB_Q10_STEREO); } /** * Tests encoding one packet of silence at different quality settings. * * 1 packet WB = 320 samples = 20 ms */ public void testEncodeSilenceWBstereo() { testEncode(1, 1, 16000, 2, new float[640], ENCODED_SILENCE_WB_Q01_STEREO); testEncode(1, 2, 16000, 2, new float[640], ENCODED_SILENCE_WB_Q02_STEREO); testEncode(1, 3, 16000, 2, new float[640], ENCODED_SILENCE_WB_Q03_STEREO); testEncode(1, 4, 16000, 2, new float[640], ENCODED_SILENCE_WB_Q04_STEREO); testEncode(1, 5, 16000, 2, new float[640], ENCODED_SILENCE_WB_Q05_STEREO); testEncode(1, 6, 16000, 2, new float[640], ENCODED_SILENCE_WB_Q06_STEREO); testEncode(1, 7, 16000, 2, new float[640], ENCODED_SILENCE_WB_Q07_STEREO); testEncode(1, 8, 16000, 2, new float[640], ENCODED_SILENCE_WB_Q08_STEREO); testEncode(1, 9, 16000, 2, new float[640], ENCODED_SILENCE_WB_Q09_STEREO); testEncode(1, 10, 16000, 2, new float[640], ENCODED_SILENCE_WB_Q10_STEREO); } /** * Tests encoding one packet of silence at different quality settings. * * 1 packet UWB = 640 samples = 20 ms */ public void testEncodeSilenceUWBstereo() { testEncode(2, 1, 32000, 2, new float[1280], ENCODED_SILENCE_UWB_Q01_STEREO); testEncode(2, 2, 32000, 2, new float[1280], ENCODED_SILENCE_UWB_Q02_STEREO); testEncode(2, 3, 32000, 2, new float[1280], ENCODED_SILENCE_UWB_Q03_STEREO); testEncode(2, 4, 32000, 2, new float[1280], ENCODED_SILENCE_UWB_Q04_STEREO); testEncode(2, 5, 32000, 2, new float[1280], ENCODED_SILENCE_UWB_Q05_STEREO); testEncode(2, 6, 32000, 2, new float[1280], ENCODED_SILENCE_UWB_Q06_STEREO); testEncode(2, 7, 32000, 2, new float[1280], ENCODED_SILENCE_UWB_Q07_STEREO); testEncode(2, 8, 32000, 2, new float[1280], ENCODED_SILENCE_UWB_Q08_STEREO); testEncode(2, 9, 32000, 2, new float[1280], ENCODED_SILENCE_UWB_Q09_STEREO); testEncode(2, 10, 32000, 2, new float[1280], ENCODED_SILENCE_UWB_Q10_STEREO); } } jspeex/src/test/org/xiph/speex/WaveToolbox.java0000644000175000017500000004075510135761046022075 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: WaveToolbox.java * * * * Author: Marc GIMPEL * * * * Date: Oct 21, 2004 * * * ******************************************************************************/ /* $Id: WaveToolbox.java,v 1.1 2004/10/21 16:21:58 mgimpel Exp $ */ package org.xiph.speex; import java.io.FileOutputStream; import java.io.IOException; import java.util.Random; /** * Toolbox for dealing with wave files * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.1 $ */ public class WaveToolbox { /** * Generates a wav header based on the given parameters. * Wave file structure is as follows: * * * * * * * * * * * * * * * * * * * * * * *
    Byte Size Value
    0- 3 4 "RIFF"
    4- 7 4 Wave File Size (-8)
    8-11 4 "WAVE"
    12-15 4 "fmt " = Format Chunk Header
    16-19 4 Size Format Chunk = 16 usually
    20-21 2 Format Tag = 0x01 for PCM
    22-23 2 Number of Channels = 1 for mono
    24-27 4 Sampling Frequency : ex. 8000
    28-31 4 Average bytes per second
    32-33 2 Data Block Size (in bytes)
    34-35 2 Bits per sample : 16 for PCM
    ... 4+ Extended Format Chunk
    ~36-39 4 "data" = Data Chunk Header
    ~40-43 4 Size Data Chunk
    ~44-... 4 Audio data
    * * @param channels the number of audio channels (1=mono, 2=stereo, ...). * @param sampleRate the sampling frequency of the audio. * @param sampleCount the number of audio samples. * @return a wav header based on the given parameters. */ public static byte[] generateWaveHeader(final int channels, final int sampleRate, final int sampleCount) { int headerSize = 44; byte[] header = new byte[headerSize]; writeString(header, 0, "RIFF"); writeInt (header, 4, 2*channels*sampleCount+headerSize-8); writeString(header, 8, "WAVE"); writeString(header, 12, "fmt "); writeInt (header, 16, 16); // Size of format chunk writeShort (header, 20, (short) 0x01); // Format tag: PCM writeShort (header, 22, (short) channels); // Number of channels writeInt (header, 24, sampleRate); // Sampling frequency writeInt (header, 28, 2*sampleRate*channels); // Average bytes per second writeShort (header, 32, (short) 2*channels); // Blocksize of data writeShort (header, 34, (short) 16); // Bits per sample writeString(header, 36, "data"); writeInt (header, 40, 2*sampleCount*channels); // Data Size return header; } /** * Generate Gaussian White Noise. * @param sampleCount the number of audio samples. * @param stddev standard deviation of the gaussian white noise. * @return */ public static int[] generateWhiteNoise(final int sampleCount, final int stddev) { if (sampleCount < 0) { return new int[0]; } Random random = new Random(); // Generate White Noise. int[] signal = new int[sampleCount]; for (int i=0; i 32767) signal[i] = 32767; if (signal[i] < -32768) signal[i] = -32768; } return signal; } /** * Generates a sine wave using the given parameters. * @param sampleCount the number of audio samples. * @param amplitude the amplitude of the sine wave. * @param periode the periode (in samples) of the sine wave. * @return an integer array representing a sine wave. */ private static int[] generateSine(final int sampleCount, final int amplitude, final int periode) { if (sampleCount < 0) { return new int[0]; } double phase = 0; double frequency; if (periode == 0) { frequency = 1.0; } else { frequency = 1.0 / ((double) periode); } double phaseIncrement = 2.0 * Math.PI * frequency; int[] signal = new int[sampleCount]; for (int i=0; i 32767) signal[i] = 32767; if (signal[i] < -32768) signal[i] = -32768; phase += phaseIncrement; } return signal; } /** * Generate a Wave File of White Noise with the given parameters. * @param filename * @param channels the number of audio channels (1=mono, 2=stereo, ...). * @param sampleRate the sampling frequency of the audio. * @param sampleCount the number of audio samples. * @param stddev standard deviation of the gaussian white noise. * @throws IOException */ public static void generateWhiteNoiseWaveFile(final String filename, final int channels, final int sampleRate, final int sampleCount, final int stddev) throws IOException { FileOutputStream fos = new FileOutputStream(filename); fos.write(generateWaveHeader(channels, sampleRate, sampleCount)); int[] signal = generateWhiteNoise(channels*sampleCount, stddev); byte[] data = new byte[2*channels*sampleCount]; mapInt2Pcm16bit(signal, 0, data, 0, channels*sampleCount); fos.write(data); fos.flush(); fos.close(); } /** * Generate a Wave File of a Sine Signal with the given parameters. * @param filename * @param channels the number of audio channels (1=mono, 2=stereo, ...). * @param sampleRate the sampling frequency of the audio. * @param sampleCount the number of audio samples. * @param amplitude the amplitude of the sine wave. * @param periode the periode (in samples) of the sine wave. * @throws IOException */ public static void generateSineWaveFile(final String filename, final int channels, final int sampleRate, final int sampleCount, final int amplitude, final int periode) throws IOException { FileOutputStream fos = new FileOutputStream(filename); fos.write(generateWaveHeader(channels, sampleRate, sampleCount)); int[] signal = generateSine(channels*sampleCount, amplitude, periode); byte[] data = new byte[2*channels*sampleCount]; mapInt2Pcm16bit(signal, 0, data, 0, channels*sampleCount); fos.write(data); fos.flush(); fos.close(); } /** * Generate a Wave File of Silence of a given length. * @param filename * @param channels the number of audio channels (1=mono, 2=stereo, ...). * @param sampleRate the sampling frequency of the audio. * @param sampleCount the number of audio samples. * @throws IOException */ public static void generateSilenceWaveFile(final String filename, final int channels, final int sampleRate, final int sampleCount) throws IOException { FileOutputStream fos = new FileOutputStream(filename); fos.write(generateWaveHeader(channels, sampleRate, sampleCount)); byte[] data = new byte[2*channels*sampleCount]; fos.write(data); fos.flush(); fos.close(); } //------------------------------------------------------------------------- // General Array Static methods //------------------------------------------------------------------------- /** * Writes a Little-endian short. * @param data the array into which the data should be written. * @param offset the offset from which to start writing in the array. * @param val the value to write. */ public static void writeShort(final byte[] data, final int offset, final int val) { data[offset] = (byte) (0xff & val); data[offset+1] = (byte) (0xff & (val >>> 8)); } /** * Writes a Little-endian int. * @param data the array into which the data should be written. * @param offset the offset from which to start writing in the array. * @param val the value to write. */ public static void writeInt(final byte[] data, final int offset, final int val) { data[offset] = (byte) (0xff & val); data[offset+1] = (byte) (0xff & (val >>> 8)); data[offset+2] = (byte) (0xff & (val >>> 16)); data[offset+3] = (byte) (0xff & (val >>> 24)); } /** * Writes a Little-endian long. * @param data the array into which the data should be written. * @param offset the offset from which to start writing in the array. * @param val the value to write. */ public static void writeLong(final byte[] data, final int offset, final long val) { data[offset] = (byte) (0xff & val); data[offset+1] = (byte) (0xff & (val >>> 8)); data[offset+2] = (byte) (0xff & (val >>> 16)); data[offset+3] = (byte) (0xff & (val >>> 24)); data[offset+4] = (byte) (0xff & (val >>> 32)); data[offset+5] = (byte) (0xff & (val >>> 40)); data[offset+6] = (byte) (0xff & (val >>> 48)); data[offset+7] = (byte) (0xff & (val >>> 56)); } /** * Writes a String. * @param data the array into which the data should be written. * @param offset the offset from which to start writing in the array. * @param val the value to write. */ public static void writeString(final byte[] data, final int offset, final String val) { byte[] str = val.getBytes(); System.arraycopy(str, 0, data, offset, str.length); } /** * Converts an integer PCM stream (in the form of an int array) into a * 16 bit linear PCM Little Endian stream (in the form of a byte array). * @param samples int array of 16-bit linear audio samples. * @param offsetInput offset in samples from which to start reading the input. * @param pcmBytes byte array to receive the linear 16-bit PCM formated audio. * @param offsetOutput offset in bytes from which to start writing the output. * @param length number of samples to convert. */ public static void mapInt2Pcm16bit(final int[] samples, final int offsetInput, final byte[] pcmBytes, int offsetOutput, final int length) { if (samples.length - offsetInput < length) { throw new IllegalArgumentException( "Insufficient Samples to convert to bytes"); } if (pcmBytes.length - offsetOutput < 2*length) { throw new IllegalArgumentException( "Insufficient byte buffer to convert the samples"); } for (int i = 0; i < length; i++) { pcmBytes[offsetOutput++] = (byte) (samples[offsetInput+i] & 0xff); pcmBytes[offsetOutput++] = (byte) ((samples[offsetInput+i]>>8) & 0xff); } } /** * Converts a 16 bit linear PCM Little Endian stream (in the form of a byte array) * into an integer PCM stream (in the form of an int array). * Here are some important details about the encoding: *

      *
    • Java uses big endian for shorts and ints, and Windows uses little Endian. * Therefore, shorts and ints must be read as sequences of bytes and * combined with shifting operations. *
    * @param pcmBytes byte array of linear 16-bit PCM formated audio. * @param offsetInput offset in bytes from which to start reading the input. * @param samples int array to receive the 16-bit linear audio samples. * @param offsetOutput offset in samples from which to start writing the output. * @param length number of samples to convert. */ public static void mapPcm16bit2Int(final byte[] pcmBytes, final int offsetInput, final int[] samples, final int offsetOutput, final int length) { if (pcmBytes.length - offsetInput < 2 * length) { throw new IllegalArgumentException( "Insufficient Samples to convert to integers"); } if (samples.length - offsetOutput < length) { throw new IllegalArgumentException( "Insufficient integer buffer to convert the samples"); } for (int i = 0; i < length; i++) { samples[offsetOutput+i] = (pcmBytes[offsetInput+2*i] & 0xff) | (pcmBytes[offsetInput+2*i+1] << 8); // no & 0xff at the end to keep the sign } } } jspeex/src/test/TestJSpeexCodec.java0000644000175000017500000003733510135761046017735 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2004 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Class: TestJSpeexCodec.java * * * * Author: Marc GIMPEL * * * * Date: 21st October 2004 * * * ******************************************************************************/ /* $Id: TestJSpeexCodec.java,v 1.1 2004/10/21 16:21:58 mgimpel Exp $ */ import java.io.File; import java.io.IOException; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.xiph.speex.WaveToolbox; /** * JUnit Tests for JSpeex. * * Tests Encoding and decoding of various Wave files (silence, 440 Hz Sine wave * and Gaussian White Noise) using the command line encoder. * * @author Marc Gimpel, Wimba S.A. (mgimpel@horizonwimba.com) * @version $Revision: 1.1 $ */ public class TestJSpeexCodec extends TestCase { /** Directory where audio generated by the tests are outputed. */ public static final String AUDIO_OUTPUT_DIRECTORY = "temp" + File.separator; /** * Constructor * @param arg0 */ public TestJSpeexCodec(String arg0) { super(arg0); } /** * Command line entrance. * @param args */ public static void main(String[] args) { junit.textui.TestRunner.run(TestJSpeexCodec.suite()); } /////////////////////////////////////////////////////////////////////////// // TestCase classes to override /////////////////////////////////////////////////////////////////////////// /** * */ protected void setUp() { } /** * */ protected void tearDown() { } /** * */ // protected void runTest() // { // } /** * Builds the Test Suite. * @return the Test Suite. */ public static Test suite() { return new TestSuite(TestJSpeexCodec.class); } /////////////////////////////////////////////////////////////////////////// // Tests /////////////////////////////////////////////////////////////////////////// /** * Tests encoding and decoding of 8kHz Mono Audio Signals. */ public void test8kHzMono() { encodeDecodeSine("sin8m", 0, 8000, 1, false); encodeDecodeSine("sin8mv", 0, 8000, 1, true); encodeDecodeNoise("gwn8m", 0, 8000, 1, false); encodeDecodeNoise("gwn8mv", 0, 8000, 1, true); encodeDecodeSilence("blank8m", 0, 8000, 1, false); encodeDecodeSilence("blank8mv", 0, 8000, 1, true); } /** * Tests encoding and decoding of 11kHz Mono Audio Signals. */ public void test11kHzMono() { encodeDecodeSine("sin11m", 0, 11025, 1, false); encodeDecodeSine("sin11mv", 0, 11025, 1, true); encodeDecodeNoise("gwn11m", 0, 11025, 1, false); encodeDecodeNoise("gwn11mv", 0, 11025, 1, true); encodeDecodeSilence("blank11m", 0, 11025, 1, false); encodeDecodeSilence("blank11mv", 0, 11025, 1, true); } /** * Tests encoding and decoding of an 16kHz Mono Sine Audio Signal (440 Hz). */ public void test16kHzMono() { encodeDecodeSine("sin16m", 1, 16000, 1, false); encodeDecodeSine("sin16mv", 1, 16000, 1, true); encodeDecodeNoise("gwn16m", 1, 16000, 1, false); encodeDecodeNoise("gwn16mv", 1, 16000, 1, true); encodeDecodeSilence("blank16m", 1, 16000, 1, false); encodeDecodeSilence("blank16mv", 1, 16000, 1, true); } /** * Tests encoding and decoding of an 22kHz Mono Sine Audio Signal (440 Hz). */ public void test22kHzMono() { encodeDecodeSine("sin22m", 1, 22050, 1, false); encodeDecodeSine("sin22mv", 1, 22050, 1, true); encodeDecodeNoise("gwn22m", 1, 22050, 1, false); encodeDecodeNoise("gwn22mv", 1, 22050, 1, true); encodeDecodeSilence("blank22m", 1, 22050, 1, false); encodeDecodeSilence("blank22mv", 1, 22050, 1, true); } /** * Tests encoding and decoding of an 32kHz Mono Sine Audio Signal (440 Hz). */ public void test32kHzMono() { encodeDecodeSine("sin32m", 2, 32000, 1, false); encodeDecodeSine("sin32mv", 2, 32000, 1, true); encodeDecodeNoise("gwn32m", 2, 32000, 1, false); encodeDecodeNoise("gwn32mv", 2, 32000, 1, true); encodeDecodeSilence("blank32m", 2, 32000, 1, false); encodeDecodeSilence("blank32mv", 2, 32000, 1, true); } /** * Tests encoding and decoding of an 44kHz Mono Sine Audio Signal (440 Hz). */ public void test44kHzMono() { encodeDecodeSine("sin44m", 2, 44100, 1, false); encodeDecodeSine("sin44mv", 2, 44100, 1, true); encodeDecodeNoise("gwn44m", 2, 44100, 1, false); encodeDecodeNoise("gwn44mv", 2, 44100, 1, true); encodeDecodeSilence("blank44m", 2, 44100, 1, false); encodeDecodeSilence("blank44mv", 2, 44100, 1, true); } /** * Tests encoding and decoding of an 8kHz Stereo Sine Audio Signal (440 Hz). */ public void test8kHzStereo() { encodeDecodeSine("sin8s", 0, 8000, 2, false); encodeDecodeSine("sin8sv", 0, 8000, 2, true); encodeDecodeNoise("gwn8s", 0, 8000, 2, false); encodeDecodeNoise("gwn8sv", 0, 8000, 2, true); encodeDecodeSilence("blank8s", 0, 8000, 2, false); encodeDecodeSilence("blank8sv", 0, 8000, 2, true); } /** * Tests encoding and decoding of an 11kHz Stereo Sine Audio Signal (440 Hz). */ public void test11kHzStereo() { encodeDecodeSine("sin11s", 0, 11025, 2, false); encodeDecodeSine("sin11sv", 0, 11025, 2, true); encodeDecodeNoise("gwn11s", 0, 11025, 2, false); encodeDecodeNoise("gwn11sv", 0, 11025, 2, true); encodeDecodeSilence("blank11s", 0, 11025, 2, false); encodeDecodeSilence("blank11sv", 0, 11025, 2, true); } /** * Tests encoding and decoding of an 16kHz Stereo Sine Audio Signal (440 Hz). */ public void test16kHzStereo() { encodeDecodeSine("sin16s", 1, 16000, 2, false); encodeDecodeSine("sin16sv", 1, 16000, 2, true); encodeDecodeNoise("gwn16s", 1, 16000, 2, false); encodeDecodeNoise("gwn16sv", 1, 16000, 2, true); encodeDecodeSilence("blank16s", 1, 16000, 2, false); encodeDecodeSilence("blank16sv", 1, 16000, 2, true); } /** * Tests encoding and decoding of an 22kHz Stereo Sine Audio Signal (440 Hz). */ public void test22kHzStereo() { encodeDecodeSine("sin22s", 1, 22050, 2, false); encodeDecodeSine("sin22sv", 1, 22050, 2, true); encodeDecodeNoise("gwn22s", 1, 22050, 2, false); encodeDecodeNoise("gwn22sv", 1, 22050, 2, true); encodeDecodeSilence("blank22s", 1, 22050, 2, false); encodeDecodeSilence("blank22sv", 1, 22050, 2, true); } /** * Tests encoding and decoding of an 32kHz Stereo Sine Audio Signal (440 Hz). */ public void test32kHzStereo() { encodeDecodeSine("sin32s", 2, 32000, 2, false); encodeDecodeSine("sin32sv", 2, 32000, 2, true); encodeDecodeNoise("gwn32s", 2, 32000, 2, false); encodeDecodeNoise("gwn32sv", 2, 32000, 2, true); encodeDecodeSilence("blank32s", 2, 32000, 2, false); encodeDecodeSilence("blank32sv", 2, 32000, 2, true); } /** * Tests encoding and decoding of an 44kHz Stereo Sine Audio Signal (440 Hz). */ public void test44kHzStereo() { encodeDecodeSine("sin44s", 2, 44100, 2, false); encodeDecodeSine("sin44sv", 2, 44100, 2, true); encodeDecodeNoise("gwn44s", 2, 44100, 2, false); encodeDecodeNoise("gwn44sv", 2, 44100, 2, true); encodeDecodeSilence("blank44s", 2, 44100, 2, false); encodeDecodeSilence("blank44sv", 2, 44100, 2, true); } /////////////////////////////////////////////////////////////////////////// // Build and Test Encoders and Decoders /////////////////////////////////////////////////////////////////////////// /** * Tests encoding and decoding of Silence. * @param filename * @param mode * @param sampleRate * @param channels * @param vbr */ protected static void encodeDecodeSilence(String filename, final int mode, final int sampleRate, final int channels, final boolean vbr) { filename = AUDIO_OUTPUT_DIRECTORY + filename; // Setup Source try { WaveToolbox.generateSilenceWaveFile(filename+".wav", channels, sampleRate, 5 * sampleRate); } catch (IOException e) { fail("Unable to generate input audio file"); } // Encode Audio JSpeexEnc enc = buildEncoder(filename, mode, sampleRate, channels, vbr); try { enc.encode(); } catch (IOException e) { fail("Unable to encode audio file"); } // Decode Audio JSpeexDec dec = buildDecoder(filename); try { dec.decode(); } catch (IOException e) { fail("Unable to decode audio file"); } } /** * Tests encoding and decoding of Gaussian White Noise. * @param filename * @param mode * @param sampleRate * @param channels * @param vbr */ protected static void encodeDecodeNoise(String filename, final int mode, final int sampleRate, final int channels, final boolean vbr) { filename = AUDIO_OUTPUT_DIRECTORY + filename; // Setup Source File try { WaveToolbox.generateWhiteNoiseWaveFile(filename+".wav", channels, sampleRate, 5 * sampleRate, 22000); } catch (IOException e) { fail("Unable to generate input audio file"); } // Encode Audio JSpeexEnc enc = buildEncoder(filename, mode, sampleRate, channels, vbr); try { enc.encode(); } catch (IOException e) { fail("Unable to encode audio file"); } // Decode Audio JSpeexDec dec = buildDecoder(filename); try { dec.decode(); } catch (IOException e) { fail("Unable to decode audio file"); } } /** * Tests encoding and decoding of a Sine Audio Signal (440 Hz). * @param filename * @param mode * @param sampleRate * @param channels * @param vbr */ protected static void encodeDecodeSine(String filename, final int mode, final int sampleRate, final int channels, final boolean vbr) { filename = AUDIO_OUTPUT_DIRECTORY + filename; // Setup Source File 5s 440Hz (la) try { WaveToolbox.generateSineWaveFile(filename+".wav", channels, sampleRate, 5 * sampleRate, 30000, channels * sampleRate / 440); } catch (IOException e) { fail("Unable to generate input audio file"); } // Encode Audio JSpeexEnc enc = buildEncoder(filename, mode, sampleRate, channels, vbr); try { enc.encode(); } catch (IOException e) { fail("Unable to encode audio file"); } // Decode Audio JSpeexDec dec = buildDecoder(filename); try { dec.decode(); } catch (IOException e) { fail("Unable to decode audio file"); } } /** * Build JSpeex Encoder for the given filename. * @param filename * @param mode * @param sampleRate * @param channels * @return JSpeex Encoder for the given filename. */ protected static JSpeexEnc buildEncoder(final String filename, final int mode, final int sampleRate, final int channels, final boolean vbr) { JSpeexEnc enc = new JSpeexEnc(); enc.srcFile = filename+".wav"; enc.destFile = filename+".spx"; enc.srcFormat = JSpeexEnc.FILE_FORMAT_WAVE; enc.destFormat = JSpeexEnc.FILE_FORMAT_OGG; enc.printlevel = JSpeexEnc.ERROR; enc.mode = mode; // Narrowband //enc.vbr_quality = 8f; // default 8 //enc.quality = 8; // default 8 //enc.complexity = 3; // default 3 //enc.nframes = 1; // default 1 enc.vbr = vbr; // default false //enc.vad = false; // default false //enc.dtx = false; // default false enc.sampleRate = sampleRate; enc.channels = channels; return enc; } /** * Build JSpeex Decoder for the given filename. * @param filename filename without extention of file to decode. * @return JSpeex Decoder for the given filename. */ protected static JSpeexDec buildDecoder(final String filename) { JSpeexDec dec = new JSpeexDec(); dec.srcFile = filename+".spx"; dec.destFile = filename+"-encdec.wav"; dec.srcFormat = JSpeexDec.FILE_FORMAT_OGG; dec.destFormat = JSpeexDec.FILE_FORMAT_WAVE; dec.printlevel = JSpeexDec.ERROR; dec.enhanced = true; return dec; } } jspeex/src/jspeex.spec0000644000175000017500000000723510135761046015265 0ustar twernertwerner#-------------------------------------------------------------------- # RPM Spec file for JSpeex # $Id: jspeex.spec,v 1.8 2004/10/21 16:21:58 mgimpel Exp $ #-------------------------------------------------------------------- %define name jspeex %define version @VERSION@ %define release 1 Name: %{name} Version: %{version} Release: %{release} Epoch: 0 Summary: 100% Java Speex encoder/decoder/converter library License: BSD Url: http://jspeex.sourceforge.net/ Group: Development/Libraries/Java Vendor: JSpeex Source0: http://switch.dl.sourceforge.net/sourceforge/jspeex/%{name}-%{version}.zip BuildRequires: ant BuildRequires: jpackage-utils >= 0:1.5 BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot %package javadoc Summary: Javadoc for %{name} Group: Development/Documentation #-------------------------------------------------------------------- # Description #-------------------------------------------------------------------- %description JSpeex is a Java port of the Speex speech codec (Open Source/Free Software patent-free audio compression format designed for speech). It provides both the decoder and the encoder in pure Java, as well as a JavaSound SPI. %description javadoc Javadoc for %{name}. #-------------------------------------------------------------------- # Build Preparations #-------------------------------------------------------------------- %prep rm -rf $RPM_BUILD_ROOT %setup -q -c find . -name "jspeex*.jar" -exec rm -f {} \; find . -name "*.class" -exec rm -f {} \; #-------------------------------------------------------------------- # Source Build #-------------------------------------------------------------------- %build cd jspeex ant package ant javadoc cd .. #-------------------------------------------------------------------- # Source Install #-------------------------------------------------------------------- %install # jar install -d -m 755 $RPM_BUILD_ROOT%{_javadir} install -m 644 %{name}/dist/%{name}.jar \ $RPM_BUILD_ROOT%{_javadir}/%{name}-%{version}.jar (cd $RPM_BUILD_ROOT%{_javadir} && for jar in *-%{version}*; do \ ln -sf ${jar} ${jar/-%{version}/}; done) # javadoc install -d -m 755 $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version} cp -pr jspeex/doc/* $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version} #-------------------------------------------------------------------- # Post Build Cleaning #-------------------------------------------------------------------- %clean rm -rf $RPM_BUILD_ROOT #-------------------------------------------------------------------- # Post-install Scripts #-------------------------------------------------------------------- %post javadoc rm -f %{_javadocdir}/%{name} ln -s %{name}-%{version} %{_javadocdir}/%{name} #-------------------------------------------------------------------- # Post-un-install Scripts #-------------------------------------------------------------------- %postun javadoc if [ "$1" = "0" ]; then rm -f %{_javadocdir}/%{name} fi #-------------------------------------------------------------------- # Package File List #-------------------------------------------------------------------- %files %defattr(0644,root,root,0755) %doc jspeex/TODO jspeex/License.txt jspeex/README %{_javadir}/* %files javadoc %defattr(0644,root,root,0755) %{_javadocdir}/%{name}-%{version} #-------------------------------------------------------------------- # Changelogs #-------------------------------------------------------------------- %changelog * Tue Aug 5 2003 Marc Gimpel 0.9.5-1 - bug fixes * Tue Aug 5 2003 Marc Gimpel 0.8.1-1 - release jspeex/License.txt0000644000175000017500000000753107700054144014444 0ustar twernertwerner/****************************************************************************** * * * Copyright (c) 1999-2003 Wimba S.A., All Rights Reserved. * * * * COPYRIGHT: * * This software is the property of Wimba S.A. * * This software is redistributed under the Xiph.org variant of * * the BSD license. * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * - Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * - Neither the name of Wimba, the Xiph.org Foundation nor the names of * * its contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * WARRANTIES: * * This software is made available by the authors in the hope * * that it will be useful, but without any warranty. * * Wimba S.A. is not liable for any consequence related to the * * use of the provided software. * * * * Date: 22nd April 2003 * * * ******************************************************************************/ /* Copyright (C) 2002 Jean-Marc Valin Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ jspeex/README0000644000175000017500000000334510222221076013171 0ustar twernertwernerBuilding -------- If you have apache ant installed, there is a build.xml file in the root directory. For those of you who are interested in getting the smallest footprint possible out of this code, there are several build targets which remove the wideband code to reduce the footprint, and obfuscate the code using another open source tool, Proguard, which also further reduces the footprint. With this I have manager to build a Jar file with just the narrowband decoder that is only 47.7k Using with JavaSound ---------------------- place the dist/jspeex.jar in your classpath and JavaSound will automatically have access to the codecs, to read, write and convert the Speex (.spx) files. It has been tested and works with the jlGui Java Music Player. Running on the Command line --------------------------- encoder help: java -cp dist/jspeex.jar JSpeexEnc -h or: java -jar dist/jspeex.jar -h decoder help: java -cp dist/jspeex.jar JSpeexDec -h ex: encoding a wav file: java -cp dist/jspeex.jar JSpeexEnc input.wav output.spx decoding any speex file: java -cp dist/jspeex.jar JSpeexDec input.spx output.wav Credits ------- First of all I'd like to thank Jean-Marc Valin for giving us all this fantastic codec. This code is really just a porting of Jean-Marc's code from C to Java. I'd also like to thank James Lawrence, who wrote the original Java Speex Decoder, from which this encoder was build. Finally I'd like to thank all the people who have submitted patches since the project has started: Dan Rollo William Shubert George Arnhold Mark Brown Marc Gimpel Director of Research Horizon Wimba jspeex/TODO0000644000175000017500000000100710135761044013001 0ustar twernertwernerDECODER ======= - DTX implemented but untested. - Can't force decoder to run at another rate, mode, or channel count. - Packet loss simulation implemented but untested ENCODER ======= - DTX, VAD and ABR implemented but untested. MISCELLANEOUS ============= - Test capacity to read and write Speex Wav files (compatible with Speex ACM) - Write a Simple JavaSound Player/Recorder to demonstrate the SPI working. - Improve the JUnit test suit to test and validate the code and SPI when changes are made. jspeex/build.xml0000644000175000017500000003057210245617604014147 0ustar twernertwerner JSpeex build file
    -libraryjars ${java.home}/lib/rt.jar -injars ${dist}/jspeex.jar -outjar ${dist}/jspeex-obf.jar -renamesourcefileattribute SourceFile -keepattributes InnerClasses,SourceFile -printmapping ${log}/jspeex-obf.map -overloadaggressively -keep public class * { public protected *; } -libraryjars ${java.home}/lib/rt.jar -injars ${dist}/jspeex-dec-nb.jar -outjar ${dist}/jspeex-dec-nb-obf.jar -printmapping ${log}/jspeex-dec-nb-obf.map -overloadaggressively -defaultpackage '' -keep public class JSpeexDec { public static void main(java.lang.String[]); } Copyright © 1999-2004 Wimba S.A. All Rights Reserved.]]> !!! You must be root to run this target !!! ant [options] target Principal Targets of interest: compile Compile classes package Package classes into library (94k) compress Obfuscate library to reduce size (92k) javadoc Generate javadoc documentation Other Targets of interest: compile-nb Compile classes for narrowband use only compress-dec-nb Package and compress only the decoder for narrowband (48k) Other Targets: release Builds a zip file containing the JSpeex release usage Display this message clean Clean the build directories