1

我正在尝试为 android 使用 java 声音调制库,即sonic。我正在尝试运行其示例 android 应用程序,但它给了我异常说“初始化错误中的异常”我无法找出原因。以下是代码,请检查。

public class SonicTest extends Activity
{
static Sonic sonic;
@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);                      
    setContentView(R.layout.main);
}

public void play(View view)
{
    new Thread(new Runnable() 
    {
        public void run()
        {
            final EditText speedEdit = (EditText) findViewById(R.id.speed);
            final EditText pitchEdit = (EditText) findViewById(R.id.pitch);
            final EditText rateEdit = (EditText) findViewById(R.id.rate);
            float speed = Float.parseFloat(speedEdit.getText().toString());
            float pitch = Float.parseFloat(pitchEdit.getText().toString());
            float rate = Float.parseFloat(rateEdit.getText().toString());
            AndroidAudioDevice device = new AndroidAudioDevice(22050, 1);
            byte samples[] = new byte[4096];
            byte modifiedSamples[] = new byte[2048];
            InputStream soundFile = getResources().openRawResource(R.raw.talking);
            int bytesRead;
            Log.i("Hello", "HI");
             sonic = new Sonic(22050, 1);

            if(soundFile != null) {
                sonic.setSpeed(speed);
                sonic.setPitch(pitch);
                sonic.setRate(rate);
                do {
                    try {
                        bytesRead = soundFile.read(samples, 0, samples.length);
                    } catch (IOException e) {
                        e.printStackTrace();
                        return;
                    }
                    if(bytesRead > 0) {
                        sonic.putBytes(samples, bytesRead);
                    } else {
                        sonic.flush();
                    }
                    int available = sonic.availableBytes(); 
                    if(available > 0) {
                        if(modifiedSamples.length < available) {
                            modifiedSamples = new byte[available*2];
                        }
                        sonic.receiveBytes(modifiedSamples, available);
                        device.writeSamples(modifiedSamples, available);
                    }
                } while(bytesRead > 0);
                device.flush();
            }
        }
    } ).start();
}}

声波类:

public class Sonic
{
// Sonic is thread-safe, but to have multiple instances of it, we have to
// store a pointer to it's data. We store that here as a long, just in case
// someone wants to port this JNI wapper to a 64-bit JVM.
long sonicID = 0;

// Create a sonic stream.  Return false only if we are out of memory and cannot
// allocate the stream. Set numChannels to 1 for mono, and 2 for stereo.
public Sonic(int sampleRate, int numChannels)
{
    close();
    sonicID = initNative(sampleRate, numChannels);
}

// Call this to clean up memory after you're done processing sound.
public void close()
{
    if(sonicID != 0) {
        closeNative(sonicID);
        sonicID = 0;
    }
}

// Just insure that close gets called, in case the user forgot.
protected void finalize()
{
    // It is safe to call this twice, in case the user already did.
    close();
}

// Force the sonic stream to generate output using whatever data it currently
// has.  No extra delay will be added to the output, but flushing in the middle of
// words could introduce distortion.
public void flush()
{
    flushNative(sonicID);
}

// Set the sample rate of the stream.  This will drop any samples that have not been read.
public void setSampleRate(int newSampleRate)
{
    setSampleRateNative(sonicID, newSampleRate);
}

// Get the sample rate of the stream.
public int getSampleRate()
{
    return getSampleRateNative(sonicID);
}

// Set the number of channels.  This will drop any samples that have not been read.
public void setNumChannels(int newNumChannels)
{
    setNumChannelsNative(sonicID, newNumChannels);
}

// Get the number of channels.
public int getNumChannels()
{
    return getNumChannelsNative(sonicID);
}

// Set the pitch of the stream.
public void setPitch(float newPitch)
{
    setPitchNative(sonicID, newPitch);
}

// Get the pitch of the stream.
public float getPitch()
{
    return getPitchNative(sonicID);
}

//Set the speed of the stream.
public void setSpeed(float newSpeed)
{
    setSpeedNative(sonicID, newSpeed);
}

// Get the speed of the stream.
public float getSpeed()
{
    return getSpeedNative(sonicID);
}

// Set the rate of the stream.  Rate means how fast we play, without pitch correction
// You probably just want to use setSpeed and setPitch instead.
public void setRate(float newRate)
{
    setRateNative(sonicID, newRate);
}

// Get the rate of the stream.
public float getRate()
{
    return getRateNative(sonicID);
}

// Set chord pitch mode on or off.  Default is off.  See the documentation
// page for a description of this feature.
public void setChordPitch(boolean useChordPitch)
{
    setChordPitchNative(sonicID, useChordPitch);
}

// Get the chord pitch setting.
public boolean getChordPitch()
{
    return getChordPitchNative(sonicID);
}

// Use this to write 16-bit data to be speed up or down into the stream.
// Return false if memory realloc failed, otherwise true.
public boolean putBytes(byte[] buffer, int lenBytes)
{
    return putBytesNative(sonicID, buffer, lenBytes);
}

// Use this to read 16-bit data out of the stream.  Sometimes no data will
// be available, and zero is returned, which is not an error condition.
public int receiveBytes(byte[] ret, int lenBytes)
{
    return receiveBytesNative(sonicID, ret, lenBytes);
}

// Return the number of samples in the output buffer
public int availableBytes()
{
    return availableBytesNative(sonicID);
}

// Set the scaling factor of the stream.
public void setVolume(float newVolume)
{
    setVolumeNative(sonicID, newVolume);
}

// Get the scaling factor of the stream.
public float getVolume()
{
    return getVolumeNative(sonicID);
}

private native long initNative(int sampleRate, int channels);
// When done with sound processing, it's best to call this method to clean up memory.
private native void closeNative(long sonicID);
private native void flushNative(long sonicID);
// Note that changing the sample rate or num channels will cause a flush.
private native void setSampleRateNative(long sonicID, int newSampleRate);
private native int getSampleRateNative(long sonicID);
private native void setNumChannelsNative(long sonicID, int newNumChannels);
private native int getNumChannelsNative(long sonicID);
private native void setPitchNative(long sonicID, float newPitch);
private native float getPitchNative(long sonicID);
private native void setSpeedNative(long sonicID, float newSpeed);
private native float getSpeedNative(long sonicID);
private native void setRateNative(long sonicID, float newRate);
private native float getRateNative(long sonicID);
private native void setChordPitchNative(long sonicID, boolean useChordPitch);
private native boolean getChordPitchNative(long sonicID);
private native boolean putBytesNative(long sonicID, byte[] buffer, int lenBytes);
private native int receiveBytesNative(long sonicID, byte[] ret, int lenBytes);
private native int availableBytesNative(long sonicID);
private native void setVolumeNative(long sonicID, float newVolume);
private native float getVolumeNative(long sonicID);

static {
    System.loadLibrary("sonic");
}}

以下是我的日志文件。

FATAL EXCEPTION: Thread-10
java.lang.ExceptionInInitializerError
at org.vinuxproject.sonic.SonicTest$1.run(SonicTest.java:50)
at java.lang.Thread.run(Thread.java:1019)
Caused by: java.lang.UnsatisfiedLinkError: Couldn't load sonic: findLibrary returned    null
4

2 回答 2

3

您必须放在项目libsonic.so的文件夹中libs/armeabi

于 2013-03-26T08:20:41.510 回答
1

您必须将 jar 添加到构建路径(您可能已经拥有,因为它可以编译)并且还必须在项目设置中的 Android 下的“Order and Export”选项卡上检查库。

于 2013-03-26T08:20:57.493 回答