Java 在android中使用liblame将pcm文件转换为mp3
我正在使用将android中使用AudioRecord类创建的pcm文件转换为mp3。我读取pcm文件并将其编码为mp3,然后将其写入文件中。结果是mp3文件,但不是正确的,上面有很多噪音,很难理解它是由pcm文件录制的。 这些是录制的音频规格(pcm文件): 这是我使用liblame对mp3进行编码并将其写入文件的代码:Java 在android中使用liblame将pcm文件转换为mp3,java,android,mp3,lamemp3,Java,Android,Mp3,Lamemp3,我正在使用将android中使用AudioRecord类创建的pcm文件转换为mp3。我读取pcm文件并将其编码为mp3,然后将其写入文件中。结果是mp3文件,但不是正确的,上面有很多噪音,很难理解它是由pcm文件录制的。 这些是录制的音频规格(pcm文件): 这是我使用liblame对mp3进行编码并将其写入文件的代码: //Encoder.Builder(int inSamplerate,int outChannel,int outSampleRate,int outBitrate) Enc
//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;
}
如何修复此代码,缓冲区大小是否正确?使用BufferedInputStream是否正确?而且…就在昨天,我使用lame为我的应用程序实现了一个PCM到MP3编码器。我建议不要使用SimpleLameLibForAndroid,而是自己给项目添加lame。如果您使用的是AndroidStudio,如果您以前没有使用过NDK,那么这里有一个很好的指南可以帮助您开始使用它 至于实现lame本身,下面是一个非常好的指南,我遵循它来启动和运行我的应用程序。使用页面顶部.zip中的
wrapper.c
。这将公开有用的方法,以便您可以避免所有讨厌的流
和缓冲区
内容
当所有这些都说了又做了,对lame编码器的实际调用非常简单,如下所示
对于初始化(使用您喜欢的任何设置):
对于编码(非常简单):
当然,当使用destroycoder()
时,请销毁编码器
//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;
}
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
}