如何使用Android应用程序中编码的opus编码和解码音频?

时间:2016-04-26 07:46:37

标签: android java-native-interface opus

我正在尝试编写一个记录和播放语音的应用程序。我为此使用了AudioRecord / AudioTrack API。要求是我需要对从AudioRecord对象读取的音频数据进行编码,并在将其写入要播放的AudioTrack对象之前使用opus编解码器对其进行解码。我能够实现录制和编码。但录制的音频在解码后无法播放。

以下是我使用的文件:

Playback.java

public class Playback {

private static String TAG = "Playback";

public boolean isPlaying = false;
public boolean isStopped = false;
private boolean shouldStopPlaying = false;

private int frequency = 48000;
private int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int numberOfChannels = 1;
private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
private int frameSize = 120;

private final int audioRecBufferSize = AudioRecord.getMinBufferSize(frequency,
        channelConfiguration, audioEncoding);

public void playFile (File file)
{
    this.shouldStopPlaying = false;
    this.isPlaying = true;

    FileInputStream inputStream = this.initInputStreamForFile(file);

    AudioTrack atrack = new AudioTrack(AudioManager.STREAM_MUSIC,frequency,
            channelConfiguration, audioEncoding, audioRecBufferSize,
            AudioTrack.MODE_STREAM);
    atrack.play();

    int bytesRead = 0;

    short[] buffer = new short[audioRecBufferSize];

    OpusDecoder decoder = new OpusDecoder(inputStream, frequency, numberOfChannels,
            frameSize);

    Log.d(TAG, "Audio length of file to be played: " + file.length());
    while (!shouldStopPlaying && bytesRead < file.length()) {
        try {
            bytesRead += decoder.read(buffer);
            atrack.write(buffer, 0, buffer.length);
            //atrack.flush();
            //Log.d(TAG, "Buffer size in frames: " + atrack.getBufferSizeInFrames());
            //Log.d(TAG, "Buffer length: " + buffer.length);
            //Log.d(TAG, "Audio buffer after decoding: " + Arrays.toString(buffer));
        }
        catch (IOException e) {
            Log.e(TAG, e.getLocalizedMessage(), e);
            break;
        }
    }
    atrack.stop();

    this.isPlaying = false;
}

private FileInputStream initInputStreamForFile(File file) {
    try {
        return new FileInputStream(file);
    }
    catch (FileNotFoundException e) {
        Log.e(TAG, e.getLocalizedMessage(), e);
        return null;
    }
}

public void stopPlaying() {
    this.shouldStopPlaying = true;
}

}

OpusDecoder

public class OpusDecoder extends FilterInputStream {

private static String TAG = "OpusDecoder";

private native boolean nativeInitDecoder(int samplingRate, int numberOfChannels, int frameSize);
private native int nativeDecodeBytes(byte[] in, short[] out);
private native boolean nativeReleaseDecoder();

private InputStream in;

static
{
    try
    {
        System.loadLibrary("OpusDecoder");
    }
    catch (Exception e)
    {
        Log.e(TAG, "Could not load SystemLibrary 'OpusDecoder");
    }
}

protected OpusDecoder(InputStream in)
{
    this(in, 48000, 1, 5760);
}

public OpusDecoder(InputStream in, int frequency, int numberOfChannels, int frameSize)
{
    super(in);
    this.in = in;

    this.nativeInitDecoder(frequency, numberOfChannels, frameSize);
}


@Override
public int read() throws IOException {
    throw new UnsupportedOperationException("Method not implemented in inheriting class");
}

@Override
public int read(byte[] buffer) throws IOException {
    throw new UnsupportedOperationException(("Method not implemented in inheriting class for " +
            "byte[]. Please use short[]."));
}

public int read(short[] buffer) throws IOException {

    Log.d(TAG, "Buffer Size: " + buffer.length);

    byte[] encodedBuffer;
    int bytesEncoded = this.in.read();
    int bytesDecoded = 0;

    Log.d(TAG, bytesEncoded + " bytes read from input stream");
    if (bytesEncoded >= 0) {

        encodedBuffer = new byte[bytesEncoded];
        int bytesRead = this.in.read(encodedBuffer);
       // Log.d(TAG, "Bytes read before decoding: " + bytesRead);
       // Log.d(TAG, "Buffer before decoding: " + Arrays.toString(encodedBuffer));
        bytesDecoded = nativeDecodeBytes(encodedBuffer, buffer);
       // Log.d(TAG, bytesDecoded + " bytes decoded");
    }

    return bytesDecoded;
}

@Override
public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
    throw new UnsupportedOperationException("Method not implemented in  inheriting class");
}

@Override
public void close() throws IOException {
    this.in.close();
    this.nativeReleaseDecoder();
}

}

0 个答案:

没有答案