/// <summary>Decodes a Speex file to PCM.</summary> /// <remarks>Decodes a Speex file to PCM.</remarks> /// <param name="srcPath"></param> /// <param name="destPath"></param> /// <exception>IOException</exception> /// <exception cref="System.IO.IOException"></exception> public virtual void decode(java.io.RandomInputStream srcPath, java.io.RandomOutputStream destPath) { byte[] header = new byte[2048]; byte[] payload = new byte[65536]; byte[] decdat = new byte[44100 * 2 * 2]; int WAV_HEADERSIZE = 8; short WAVE_FORMAT_SPEEX = (short)unchecked((short)(0xa109)); string RIFF = "RIFF"; string WAVE = "WAVE"; string FORMAT = "fmt "; string DATA = "data"; int OGG_HEADERSIZE = 27; int OGG_SEGOFFSET = 26; 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) { System.Console.WriteLine(string.Empty); } if (printlevel <= DEBUG) { System.Console.WriteLine("Input File: " + srcPath); } // construct a new decoder speexDecoder = new org.xiph.speex.SpeexDecoder(); // open the input stream java.io.DataInputStream dis = new java.io.DataInputStream((srcPath)); org.xiph.speex.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 = org.xiph.speex.OggCrc.checksum(0, header, 0, OGG_HEADERSIZE); // make sure its a OGG header if (!OGGID.Equals(cspeex.StringUtil.getStringForBytes(header, 0, 4))) { System.Console.Error.WriteLine("missing ogg id!"); return; } segments = header[OGG_SEGOFFSET] & unchecked((int)(0xFF)); dis.readFully(header, OGG_HEADERSIZE, segments); chksum = org.xiph.speex.OggCrc.checksum(chksum, header, OGG_HEADERSIZE, segments); for (curseg = 0; curseg < segments; curseg++) { bodybytes = header[OGG_HEADERSIZE + curseg] & unchecked((int)(0xFF)); if (bodybytes == 255) { System.Console.Error.WriteLine("sorry, don't handle 255 sizes!"); return; } dis.readFully(payload, 0, bodybytes); chksum = org.xiph.speex.OggCrc.checksum(chksum, payload, 0, bodybytes); if (packetNo == 0) { if (readSpeexHeader(payload, 0, bodybytes)) { if (printlevel <= DEBUG) { System.Console.WriteLine("File Format: Ogg Speex"); System.Console.WriteLine("Sample Rate: " + sampleRate); System.Console.WriteLine("Channels: " + channels); System.Console.WriteLine("Encoder mode: " + (mode == 0 ? "Narrowband" : (mode == 1 ? "Wideband" : "UltraWideband"))); System.Console.WriteLine("Frames per packet: " + nframes); } if (destFormat == FILE_FORMAT_WAVE) { writer = new org.xiph.speex.PcmWaveWriter(speexDecoder.getSampleRate(), speexDecoder .getChannels()); if (printlevel <= DEBUG) { System.Console.WriteLine(string.Empty); System.Console.WriteLine("Output File: " + destPath); System.Console.WriteLine("File Format: PCM Wave"); System.Console.WriteLine("Perceptual Enhancement: " + enhanced); } } else { writer = new org.xiph.speex.RawWriter(); if (printlevel <= DEBUG) { System.Console.WriteLine(string.Empty); System.Console.WriteLine("Output File: " + destPath); System.Console.WriteLine("File Format: Raw Audio"); System.Console.WriteLine("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) < loss) { speexDecoder.processData(null, 0, bodybytes); for (int i = 1; i < nframes; i++) { speexDecoder.processData(true); } } else { speexDecoder.processData(payload, 0, bodybytes); for (int i = 1; i < nframes; i++) { speexDecoder.processData(false); } } if ((decsize = speexDecoder.getProcessedData(decdat, 0)) > 0) { writer.writePacket(decdat, 0, decsize); } packetNo++; } } } if (chksum != origchksum) { throw new System.IO.IOException("Ogg CheckSums do not match"); } } else { // Wave or Raw Speex 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(cspeex.StringUtil.getStringForBytes(header, 0, 4)) && !WAVE.Equals (cspeex.StringUtil.getStringForBytes(header, 8, 4))) { System.Console.Error.WriteLine("Not a WAVE file"); return; } // Read other header chunks dis.readFully(header, 0, WAV_HEADERSIZE); string chunk = cspeex.StringUtil.getStringForBytes(header, 0, 4); int size = readInt(header, 4); while (!chunk.Equals(DATA)) { dis.readFully(header, 0, size); if (chunk.Equals(FORMAT)) { if (readShort(header, 0) != WAVE_FORMAT_SPEEX) { System.Console.Error.WriteLine("Not a Wave Speex file"); return; } channels = readShort(header, 2); sampleRate = readInt(header, 4); bodybytes = readShort(header, 12); if (readShort(header, 16) < 82) { System.Console.Error.WriteLine("Possibly corrupt Speex Wave file."); return; } readSpeexHeader(header, 20, 80); // Display audio info if (printlevel <= DEBUG) { System.Console.WriteLine("File Format: Wave Speex"); System.Console.WriteLine("Sample Rate: " + sampleRate); System.Console.WriteLine("Channels: " + channels); System.Console.WriteLine("Encoder mode: " + (mode == 0 ? "Narrowband" : (mode == 1 ? "Wideband" : "UltraWideband"))); System.Console.WriteLine("Frames per packet: " + nframes); } } dis.readFully(header, 0, WAV_HEADERSIZE); chunk = cspeex.StringUtil.getStringForBytes(header, 0, 4); size = readInt(header, 4); } if (printlevel <= DEBUG) { System.Console.WriteLine("Data size: " + size); } } else { if (printlevel <= DEBUG) { System.Console.WriteLine("File Format: Raw Speex"); System.Console.WriteLine("Sample Rate: " + sampleRate); System.Console.WriteLine("Channels: " + channels); System.Console.WriteLine("Encoder mode: " + (mode == 0 ? "Narrowband" : (mode == 1 ? "Wideband" : "UltraWideband"))); System.Console.WriteLine("Frames per packet: " + nframes); } speexDecoder.init(mode, sampleRate, channels, enhanced); if (!vbr) { switch (mode) { case 0: { bodybytes = org.xiph.speex.NbEncoder.NB_FRAME_SIZE[org.xiph.speex.NbEncoder.NB_QUALITY_MAP [quality]]; break; } case 1: { //Wideband bodybytes = org.xiph.speex.SbEncoder.NB_FRAME_SIZE[org.xiph.speex.SbEncoder.NB_QUALITY_MAP [quality]]; bodybytes += org.xiph.speex.SbEncoder.SB_FRAME_SIZE[org.xiph.speex.SbEncoder.WB_QUALITY_MAP [quality]]; break; } case 2: { bodybytes = org.xiph.speex.SbEncoder.NB_FRAME_SIZE[org.xiph.speex.SbEncoder.NB_QUALITY_MAP [quality]]; bodybytes += org.xiph.speex.SbEncoder.SB_FRAME_SIZE[org.xiph.speex.SbEncoder.WB_QUALITY_MAP [quality]]; bodybytes += org.xiph.speex.SbEncoder.SB_FRAME_SIZE[org.xiph.speex.SbEncoder.UWB_QUALITY_MAP [quality]]; break; } default: { //*/ throw new System.IO.IOException("Illegal mode encoundered."); break; } } bodybytes = (bodybytes + 7) >> 3; } else { // We have read the stream to find out more bodybytes = 0; } } if (destFormat == FILE_FORMAT_WAVE) { writer = new org.xiph.speex.PcmWaveWriter(sampleRate, channels); if (printlevel <= DEBUG) { System.Console.WriteLine(string.Empty); System.Console.WriteLine("Output File: " + destPath); System.Console.WriteLine("File Format: PCM Wave"); System.Console.WriteLine("Perceptual Enhancement: " + enhanced); } } else { writer = new org.xiph.speex.RawWriter(); if (printlevel <= DEBUG) { System.Console.WriteLine(string.Empty); System.Console.WriteLine("Output File: " + destPath); System.Console.WriteLine("File Format: Raw Audio"); System.Console.WriteLine("Perceptual Enhancement: " + enhanced); } } writer.open(destPath); writer.writeHeader(null); packetNo++; } else { dis.readFully(payload, 0, bodybytes); if (loss > 0 && random.nextInt(100) < loss) { speexDecoder.processData(null, 0, bodybytes); for (int i = 1; i < nframes; i++) { speexDecoder.processData(true); } } else { speexDecoder.processData(payload, 0, bodybytes); for (int i = 1; i < nframes; i++) { speexDecoder.processData(false); } } if ((decsize = speexDecoder.getProcessedData(decdat, 0)) > 0) { writer.writePacket(decdat, 0, decsize); } packetNo++; } } } } catch (java.io.EOFException) { } writer.close(); }
public virtual void EncodeToSpeex(java.io.RandomInputStream srcStream, java.io.RandomOutputStream destStream) { java.io.DataInputStream dis = new java.io.DataInputStream(srcStream); org.xiph.speex.OggSpeexWriter writer = new org.xiph.speex.OggSpeexWriter(mode, sampleRate, channels, nframes, vbr); writer.open(destStream); writer.writeHeader("Encoded with: " + VERSION); try { int len = int.Parse(srcStream.InnerStream.Length.ToString()); while (len > 0) { len -= (PacketSize); dis.readFully(TempBuffer, 0, PacketSize); Speex_Encoder.processData(TempBuffer, 0, PacketSize); int encsize = Speex_Encoder.getProcessedData(TempBuffer, 0); if (encsize > 0) { writer.writePacket(TempBuffer, 0, encsize); } } } catch (java.io.EOFException){} finally { writer.close(); dis.close(); } }
/// <summary>Return the AudioFileFormat from the given InputStream.</summary> /// <remarks>Return the AudioFileFormat from the given InputStream. Implementation.</remarks> /// <param name="bitStream"></param> /// <param name="baos"></param> /// <param name="mediaLength"></param> /// <returns> /// an AudioInputStream object based on the audio file data contained /// in the input stream. /// </returns> /// <exception> /// UnsupportedAudioFileException /// if the File does not point to /// a valid audio file data recognized by the system. /// </exception> /// <exception> /// IOException /// if an I/O exception occurs. /// </exception> /// <exception cref="javax.sound.sampled.UnsupportedAudioFileException"></exception> /// <exception cref="System.IO.IOException"></exception> protected virtual javax.sound.sampled.AudioFileFormat getAudioFileFormat(java.io.InputStream bitStream, java.io.ByteArrayOutputStream baos, int mediaLength) { javax.sound.sampled.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 = javax.sound.sampled.AudioSystem.NOT_SPECIFIED; float frameRate = javax.sound.sampled.AudioSystem.NOT_SPECIFIED; byte[] header = new byte[128]; int segments = 0; int bodybytes = 0; java.io.DataInputStream dis = new java.io.DataInputStream(bitStream); if (baos == null) { baos = new java.io.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 = org.xiph.speex.OggCrc.checksum(0, header, 0, OGG_HEADERSIZE); // make sure its a OGG header if (!OGGID.Equals(cspeex.StringUtil.getStringForBytes(header, 0, 4))) { throw new javax.sound.sampled.UnsupportedAudioFileException("missing ogg id!"); } // how many segments are there? segments = header[SEGOFFSET] & unchecked((int)(0xFF)); if (segments > 1) { throw new javax.sound.sampled.UnsupportedAudioFileException("Corrupt Speex Header: more than 1 segments" ); } dis.readFully(header, OGG_HEADERSIZE, segments); baos.write(header, OGG_HEADERSIZE, segments); chksum = org.xiph.speex.OggCrc.checksum(chksum, header, OGG_HEADERSIZE, segments); // get the number of bytes in the segment bodybytes = header[OGG_HEADERSIZE] & unchecked((int)(0xFF)); if (bodybytes != SPEEX_HEADERSIZE) { throw new javax.sound.sampled.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 = org.xiph.speex.OggCrc.checksum(chksum, header, OGG_HEADERSIZE + 1, bodybytes ); // make sure its a Speex header if (!SPEEXID.Equals(cspeex.StringUtil.getStringForBytes(header, OGG_HEADERSIZE + 1, 8))) { throw new javax.sound.sampled.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); bool vbr = readInt(header, OGG_HEADERSIZE + 1 + 60) == 1; // Checksum if (chksum != origchksum) { throw new System.IO.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 javax.sound.sampled.AudioFormat(org.xiph.speex.spi.SpeexEncoding.SPEEX , (float)sampleRate, javax.sound.sampled.AudioSystem.NOT_SPECIFIED, channels, frameSize , frameRate, false); } catch (javax.sound.sampled.UnsupportedAudioFileException e) { // reset the stream for other providers if (bitStream.markSupported()) { bitStream.reset(); } // just rethrow this exception throw; } catch (System.IO.IOException ioe) { // reset the stream for other providers if (bitStream.markSupported()) { bitStream.reset(); } throw new javax.sound.sampled.UnsupportedAudioFileException(ioe.Message); } return new javax.sound.sampled.AudioFileFormat(org.xiph.speex.spi.SpeexFileFormatType .SPEEX, format, javax.sound.sampled.AudioSystem.NOT_SPECIFIED); }
// ---| public virtual void encode(java.io.File srcPath, java.io.File destPath) { byte[] temp = new byte[2560]; // stereo UWB requires one to read 2560b int HEADERSIZE = 8; string RIFF = "RIFF"; string WAVE = "WAVE"; string FORMAT = "fmt "; string DATA = "data"; int WAVE_FORMAT_PCM = unchecked((int)(0x0001)); // Display info if (printlevel <= INFO) { version(); } if (printlevel <= DEBUG) { System.Console.WriteLine(string.Empty); } if (printlevel <= DEBUG) { System.Console.WriteLine("Input File: " + srcPath); } // Open the input stream java.io.DataInputStream dis = new java.io.DataInputStream(new java.io.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(cspeex.StringUtil.getStringForBytes(temp, 0, 4)) && !WAVE.Equals(cspeex.StringUtil.getStringForBytes (temp, 8, 4))) { System.Console.Error.WriteLine("Not a WAVE file"); return; } // Read other header chunks dis.readFully(temp, 0, HEADERSIZE); string chunk = cspeex.StringUtil.getStringForBytes(temp, 0, 4); int size = readInt(temp, 4); while (!chunk.Equals(DATA)) { dis.readFully(temp, 0, size); if (chunk.Equals(FORMAT)) { if (readShort(temp, 0) != WAVE_FORMAT_PCM) { System.Console.Error.WriteLine("Not a PCM file"); return; } channels = readShort(temp, 2); sampleRate = readInt(temp, 4); if (readShort(temp, 14) != 16) { System.Console.Error.WriteLine("Not a 16 bit file " + readShort(temp, 18)); return; } // Display audio info if (printlevel <= DEBUG) { System.Console.WriteLine("File Format: PCM wave"); System.Console.WriteLine("Sample Rate: " + sampleRate); System.Console.WriteLine("Channels: " + channels); } } dis.readFully(temp, 0, HEADERSIZE); chunk = cspeex.StringUtil.getStringForBytes(temp, 0, 4); size = readInt(temp, 4); } if (printlevel <= DEBUG) { System.Console.WriteLine("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.Console.WriteLine("File format: Raw audio"); System.Console.WriteLine("Sample rate: " + sampleRate); System.Console.WriteLine("Channels: " + channels); System.Console.WriteLine("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; } else { // Narrowband if (sampleRate < 24000) { mode = 1; } else { // Wideband mode = 2; } } } // Ultra-wideband // Construct a new encoder org.xiph.speex.SpeexEncoder speexEncoder = new org.xiph.speex.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.Console.WriteLine(string.Empty); System.Console.WriteLine("Output File: " + destPath); System.Console.WriteLine("File format: Ogg Speex"); System.Console.WriteLine("Encoder mode: " + (mode == 0 ? "Narrowband" : (mode== 1 ? "Wideband" : "UltraWideband"))); System.Console.WriteLine("Quality: " + (vbr ? vbr_quality : quality)); System.Console.WriteLine("Complexity: " + complexity); System.Console.WriteLine("Frames per packet: " + nframes); System.Console.WriteLine("Varible bitrate: " + vbr); System.Console.WriteLine("Voice activity detection: " + vad); System.Console.WriteLine("Discontinouous Transmission: " + dtx); } // Open the file writer org.xiph.speex.AudioFileWriter writer; if (destFormat == FILE_FORMAT_OGG) { writer = new org.xiph.speex.OggSpeexWriter(mode, sampleRate, channels, nframes, vbr ); } else { if (destFormat == FILE_FORMAT_WAVE) { nframes = org.xiph.speex.PcmWaveWriter.WAVE_FRAME_SIZES[mode - 1][channels - 1][quality ]; writer = new org.xiph.speex.PcmWaveWriter(mode, quality, sampleRate, channels, nframes , vbr); } else { writer = new org.xiph.speex.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 < nframes; i++) { speexEncoder.processData(temp, i * pcmPacketSize, pcmPacketSize); } int encsize = speexEncoder.getProcessedData(temp, 0); if (encsize > 0) { writer.writePacket(temp, 0, encsize); } } } catch (java.io.EOFException) { } writer.close(); dis.close(); }