在 android 中使用 liblame 将 pcm 文件转换为 mp3

converting pcm file to mp3 using liblame in android

我正在使用 SimpleLameLibForAndroid 将使用 android 中的 AudioRecord class 创建的 pcm 文件转换为 mp3。我读取 pcm 文件并将其编码为 mp3,然后将其写入文件。结果 mp3 文件但不正确,上面有很多噪音,真的很难理解它是录制的 pcm 文件。 这些是录制的音频规格(pcm 文件):

    private static final int RECORDER_SAMPLERATE = 8000;
    private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
    private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;    
    int BufferElements2Rec = 1024; // want to play 2048 (2K) since 2 bytes we use only 1024
    int BytesPerElement = 2; // 2 bytes in 16bit format
    recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
    RECORDER_SAMPLERATE, RECORDER_CHANNELS,
    RECORDER_AUDIO_ENCODING, BufferElements2Rec * BytesPerElement);

这是我使用 liblame 编码 mp3 并将其写入文件的代码:

//Encoder.Builder(int inSamplerate,int outChannel,int outSampleRate,int outBitrate)
Encoder en = new Encoder.Builder(8000, 1,8000,128).quality(7).create();
private int PCM_BUF_SIZE = 8192;
private int MP3_SIZE = 8192;
private void readFile()  {
    File pcm = new File("/sdcard/voice8K16bitmono.pcm");
    File mp3 = new File("/sdcard/BOOOB.mp3");
    pcm.setReadable(true);
    mp3.setWritable(true);
    try {
        InputStream is = new FileInputStream(pcm);
        BufferedInputStream bis = new BufferedInputStream(is);
        bis.skip(44);//skip pcm header
        OutputStream os = new FileOutputStream(mp3);
        FileOutputStream fos = new FileOutputStream(mp3);
        int n_bytes_read ;
        int n_bytes_write;
        int i;

        byte mp3_buffer[] = new byte[MP3_SIZE];
        byte pcm_buffer1[] = new byte[PCM_BUF_SIZE * 2];

        do {
            n_bytes_read = bis.read(pcm_buffer1 , 0 , PCM_BUF_SIZE);
            if (n_bytes_read == 0){
                n_bytes_write = en.flush(mp3_buffer);
            }
            else{
                n_bytes_write = en.encodeBufferInterleaved(byte2short(pcm_buffer1) ,n_bytes_read , mp3_buffer);
            }

            bof.write(mp3_buffer, 0, PCM_BUF_SIZE);

        } while (n_bytes_read > 0);
        bis.close();
        fos.close();
        is.close();
        en.close();

    }catch (IOException e) {
        e.printStackTrace();
    }
}
private short[] byte2short(byte[] pcm_buffer1) {
    short[] shorts = new short[pcm_buffer1.length/2];
   ByteBuffer.wrap(pcm_buffer1).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
    return shorts;
}

我该如何修复此代码,bufferSizes 是否正确?使用 BufferedInputStream 是正确的吗?和...

昨天我使用 lame 为我的应用程序实现了一个 PCM 到 MP3 编码器。我建议不要使用 SimpleLameLibForAndroid 而是自己将 lame 添加到您的项目中。如果您使用的是 Android Studio,如果您之前没有使用过 NDK,这里有一个很好的指南可以帮助您入门。

http://www.shaneenishry.com/blog/2014/08/17/ndk-with-android-studio/

至于实现 lame 本身,下面是一个非常好的指南,我遵循它来启动我的应用程序 运行。使用页面顶部 .zip 中的 wrapper.c。这公开了有用的方法,这样你就可以避免所有讨厌的 StreamBuffer 东西。

http://developer.samsung.com/technical-doc/view.do?v=T000000090

总而言之,实际调用 lame 编码器非常简单,如下所示。

用于初始化(使用您喜欢的任何设置):

public static final int NUM_CHANNELS = 1;
public static final int SAMPLE_RATE = 16000;
public static final int BITRATE = 64;
public static final int MODE = 1;
public static final int QUALITY = 7;
...

initEncoder(NUM_CHANNELS, SAMPLE_RATE, BITRATE, MODE, QUALITY);

用于编码(非常简单):

int result = encodeFile(pcm.getPath(), mp3.getPath());
if (result == 0) {
    //success
}

当然,在完成 destroyEncoder() 后销毁编码器。