Преобразование файла PCM в mp3, используя liblame в Android
Я использую https://github.com/yhirano/SimpleLameLibForAndroid для преобразования файла PCM, созданного с использованием класса AudioRecord в Android, в 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 является правильным? а также...
1 ответ
Я внедрил кодировщик PCM в MP3 только вчера для своего приложения, используя lame. Я предлагаю не использовать SimpleLameLibForAndroid, а вместо этого добавлять в свой проект lame самостоятельно. Если вы используете Android Studio, вот хорошее руководство, с которого можно начать, если вы раньше не делали NDK.
http://www.shaneenishry.com/blog/2014/08/17/ndk-with-android-studio/
Что касается реализации самого lame, ниже приведено действительно хорошее руководство, которому я следовал, чтобы запустить и запустить мое приложение. Использовать wrapper.c
из.zip в верхней части страницы. Это раскрывает полезные методы, чтобы вы могли избежать всего неприятного Stream
а также Buffer
вещи.
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()
,