/// <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 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(); }