Java 纠正JSpeex编码中的异常
我得到一个空指针异常。我看过以前关于空指针异常的文章,但我无法解决我的问题。我还提供了异常的快照 下面是我的JSpeexCode和speexincoder代码 JSpeex代码Java 纠正JSpeex编码中的异常,java,Java,我得到一个空指针异常。我看过以前关于空指针异常的文章,但我无法解决我的问题。我还提供了异常的快照 下面是我的JSpeexCode和speexincoder代码 JSpeex代码 import java.io.BufferedReader; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; i
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.xiph.speex.AudioFileWriter;
import org.xiph.speex.OggSpeexWriter;
import org.xiph.speex.PcmWaveWriter;
import org.xiph.speex.RawWriter;
import org.xiph.speex.SpeexEncoder;
/**
* 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.
*/
/**
* Command line entrance:
* <pre>
* Usage: JSpeexEnc [options] input_file output_file
* </pre>
* @param args Command line parameters.
*/
public static void main(final String[] args) throws IOException
{
JSpeexEnc encoder = new JSpeexEnc();
if (encoder.parseArgs(args)) {
encoder.encode("frf1.wav", "frf1_encoded.raw");
try (BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\Administrator\\workspace\\JSpeex.java\\src\\frf1.wav")))
{
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
System.out.println(sCurrentLine);
}
} catch (FileNotFoundException e) {
}
}
}
/**
* Parse the command line arguments.
* @param args Command line parameters.
* @param FILE_FORMAT_WAVE1
* @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<args.length-2; i++) {
if (args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("--help")) {
usage();
return false;
}
else if (args[i].equalsIgnoreCase("-v") || args[i].equalsIgnoreCase("--version")) {
version();
return false;
}
else if (args[i].equalsIgnoreCase("--verbose")) {
printlevel = DEBUG;
}
else if (args[i].equalsIgnoreCase("--quiet")) {
printlevel = WARN;
}
else if (args[i].equalsIgnoreCase("-n") ||
args[i].equalsIgnoreCase("-nb") ||
args[i].equalsIgnoreCase("--narrowband")) {
mode = 0;
}
else if (args[i].equalsIgnoreCase("-w") ||
args[i].equalsIgnoreCase("-wb") ||
args[i].equalsIgnoreCase("--wideband")) {
mode = 1;
}
else if (args[i].equalsIgnoreCase("-u") ||
args[i].equalsIgnoreCase("-uwb") ||
args[i].equalsIgnoreCase("--ultra-wideband")) {
mode = 2;
}
else if (args[i].equalsIgnoreCase("-q") || args[i].equalsIgnoreCase("--quality")) {
try {
vbr_quality = Float.parseFloat(args[++i]);
quality = (int) vbr_quality;
}
catch (NumberFormatException e) {
usage();
return false;
}
}
else if (args[i].equalsIgnoreCase("--complexity")) {
try {
complexity = Integer.parseInt(args[++i]);
}
catch (NumberFormatException e) {
usage();
return false;
}
}
else if (args[i].equalsIgnoreCase("--nframes")) {
try {
nframes = Integer.parseInt(args[++i]);
}
catch (NumberFormatException e) {
usage();
return false;
}
}
else if (args[i].equalsIgnoreCase("--vbr")) {
vbr = true;
}
else if (args[i].equalsIgnoreCase("--vad")) {
vad = true;
}
else if (args[i].equalsIgnoreCase("--dtx")) {
dtx = true;
}
else if (args[i].equalsIgnoreCase("--rate")) {
try {
sampleRate = Integer.parseInt(args[++i]);
}
catch (NumberFormatException e) {
usage();
return false;
}
}
else if (args[i].equalsIgnoreCase("--stereo")) {
channels = 2;
}
else {
usage();
return false;
}
}
return true;
}
/**
* Prints the usage guidelines.
*/
public static void usage()
{
version();
System.out.println("");
System.out.println("Usage: JSpeexEnc [options] input_file output_file");
System.out.println("Where:");
System.out.println(" input_file can be:" );
System.out.println(" filename.wav a PCM wav file");
System.out.println(" filename.* a raw PCM file (any extension other than .wav)");
System.out.println(" output_file can be:");
System.out.println(" filename.spx an Ogg Speex file");
System.out.println(" filename.wav a Wave Speex file (beta!!!)");
System.out.println(" filename.* a raw Speex file");
System.out.println("Options: -h, --help This help");
System.out.println(" -v, --version Version information");
System.out.println(" --verbose Print detailed information");
System.out.println(" --quiet Print minimal information");
System.out.println(" -n, -nb Consider input as Narrowband (8kHz)");
System.out.println(" -w, -wb Consider input as Wideband (16kHz)");
System.out.println(" -u, -uwb Consider input as Ultra-Wideband (32kHz)");
System.out.println(" --quality n Encoding quality (0-10) default 8");
System.out.println(" --complexity n Encoding complexity (0-10) default 3");
System.out.println(" --nframes n Number of frames per Ogg packet, default 1");
System.out.println(" --vbr Enable varible bit-rate (VBR)");
System.out.println(" --vad Enable voice activity detection (VAD)");
System.out.println(" --dtx Enable file based discontinuous transmission (DTX)");
System.out.println(" if the input file is raw PCM (not a Wave file)");
System.out.println(" --rate n Sampling rate for raw input");
System.out.println(" --stereo Consider input as stereo");
System.out.println("More information is available from: http://jspeex.sourceforge.net/");
System.out.println("This code is a Java port of the Speex codec: http://www.speex.org/");
}
/**
* Prints the version.
*/
public static void version()
{
System.out.println(VERSION);
System.out.println("using " + SpeexEncoder.VERSION);
System.out.println(COPYRIGHT);
}
/**
* Encodes a PCM file to Speex.
*/
public void encode()
{
System.out.println("Value of Destination File is:= "+destFile);
encode();
System.out.println("Value of Destination File is:= " +srcFile +destFile);
}
/**
* Encodes a PCM file to Speex.
* @param string
* @param string2
* @exception IOException */
public void encode(final String string, final String string2)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: " );
}
try
(DataInputStream dis = new DataInputStream(new FileInputStream(string)))
{
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: " + string.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 speexEncoder1 = speexEncoder;
if (complexity > 0) {
speexEncoder1.setComplexity(complexity);
}
if (bitrate > 0) {
speexEncoder1.setBitRate(bitrate);
// speexEncoder1.getEncoder().setBitRate(bitrate);
}
if (vbr) {
// speexEncoder1.getEncoder().setVbr(vbr);
if (vbr_quality > 0) {
speexEncoder1.setVbrQuality(vbr_quality);
}
}
if (vad) {
( speexEncoder1).setVad(vad);
}
if (dtx) {
( speexEncoder1).setDtx(dtx);
}
// Display info
if (printlevel <= DEBUG) {
System.out.println("");
System.out.println("Output File: " + string2);
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("Variable 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(string2);
writer.writeHeader("Encoded with: " + VERSION);
int pcmPacketSize = 2 * channels * speexEncoder.getFrameSize();
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);
}
}
}
}
/**
* 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
}
}
检查要传递到
MapPCM16BittleEndian2Float
的数组的大小,以及循环执行的迭代次数,记住在Java中,数组从零开始。我建议运行代码并在MapPCM16BittleEndian2Float
方法的开始处放置断点,根据您的IDE,您应该能够看到阵列的大小。如果不使用,可以将值打印到控制台。@Yann4在MAPPCM16BITLETLEENDIAN2FLOAT方法中,我已检查了所有参数的值。。样本的值显示为空。如何进一步纠正。请提示您正在传递一个空数组并试图遍历它?offsetOutput和length的值是多少?@Yann4 offsetOutput和length的值都是0。。。如何避免传递空数组并尝试遍历它。我以为你已经得到了答案,抱歉。我认为您正试图在mappcm16bittleendian2float
中打印空浮点数组。在System.out.println行中(“值为:”+samples)
,您需要在数组中选择一个特定项,如在samples[i]
中,对于i
需要的任何内容
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, len, len);
// 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<numShorts; i++) {
rawData[i] = (float) data[offset + i ];
}
// encode the bitstream
return processData(rawData, numShorts);
}
/**
* Encode an array of floats.
* @param data
* @param numSamples
* @return true if successful.
*/
public boolean processData(final float[] data, final int numSamples)
{
int numSamplesRequired = channels * frameSize;
if (numSamples != numSamplesRequired) {
throw new IllegalArgumentException("SpeexEncoder requires " + numSamplesRequired + " samples to process a Frame, not " + numSamples );
}
// encode the bitstream
if (channels==2) {
Stereo.encode(bits, data, frameSize);
}
encoder.encode(bits, data);
//System.out.println("THA VALUE OF BITS IS:" + bits);
return true;
}
/**
* Converts a 16 bit linear PCM stream (in the form of a byte array)
* into a floating point PCM stream (in the form of an float array).
* Here are some important details about the encoding:
* <ul>
* <li> 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.
* </ul>
* @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
*/
void mapPcm16bitLittleEndian2Float(final byte[] pcm16bitBytes,
final int offsetInput,
float[] samples,
final int offsetOutput,
final int length)
{
if (pcm16bitBytes.length - offsetInput < 2 * length) {
throw new IllegalArgumentException("Insufficient Samples to convert to floats");
}
System.out.println("the value is:" +samples);
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
}
}
public void setComplexity(int complexity) {
// TODO Auto-generated method stub
}
public void setVbrQuality(float vbr_quality) {
// TODO Auto-generated method stub
}
public void setDtx(boolean dtx) {
// TODO Auto-generated method stub
}
public void setBitRate(int bitrate) {
// TODO Auto-generated method stub
}
public void setVad(boolean vad) {
// TODO Auto-generated method stub
}
}
Exception in thread "main" java.lang.NullPointerException
at org.xiph.speex.SpeexEncoder.mapPcm16bitLittleEndian2Float(SpeexEncoder.java:290)
at org.xiph.speex.SpeexEncoder.processData(SpeexEncoder.java:216)
at JSpeexEnc.encode(JSpeexEnc.java:541)
at JSpeexEnc.main(JSpeexEnc.java:170)