android wav to mp3怎么将mp3topcm

android fastest way to decode mp3 to pcm data [MP3解码的PCM数据Android最快的方式] - 问题-字节技术
android fastest way to decode mp3 to pcm data
MP3解码的PCM数据Android最快的方式
问题 (Question)
in my app i need to decode an mp3 file into a pcm buffer. that's a lot of data so i downsample it to mono 22050Hz as i read and decode it.
at the moment i'm using javazoom jlayer decoder
its working but its slow, 30secs to decode a 3min song in run mode, ages in debug mode. on my windows machine using libmpg i can do that in about 1 second.
is there a faster way that anyone knows for sure is faster? i don't want to waste time implementing another method if its not significantly faster. thanks.
by the way, in my app, i need the whole thing downloaded to a pcm buffer in memory so i'm not interested in things that simply play mp3 files.
在我的应用程序,我需要一个MP3文件解码成pcm缓冲。这是一个很大的数据,所以我降质到单22050hz当我阅读和解码。我目前正在使用javazoom jlayer解码器其工作但慢,在运行模式下的3 30secs歌曲解码,年龄在调试模式。在我的Windows机器使用libmpg我可以在1秒做。有更快的方法,任何人都知道的更快?我不想浪费时间如果不显着更快的实现的另一种方法。谢谢。顺便说一下,在我的应用程序,我需要整个东西下载到内存中的PCM缓冲区,所以我不只是播放MP3文件的东西感兴趣。
最佳答案 (Best Answer)
This is the moment when you go Native in android!
-use NDK and find a fast c/c++ library (they are like 20x faster than jlayer, for example 9min sogn in 18sec)
-here are some libs that can be usefull:
/products/mad/
/technetwork/java/javase/download-137625.html (not sure does this one supports MP3toPCM)
lame.sourceforge.net/about.php (this one has an android opensource project on github that i hope is going to be very usefull to you!
这是当你去原生Android!使用NDK并找到一个快速的C / C + +库(他们像20倍的速度比jlayer,例如在9min松恩18sec)这里有一些技术,可以是有用的:</products/mad/ WWW</technetwork/java/javase/download-137625.html WWW(不确定这是否一个支持mp3topcm)lame.sourceforge.net/about.php(这其中有一个Android开源项目在GitHub上,我希望将是非常有用的你!)
本文翻译自StackoverFlow,英语好的童鞋可直接参考原文:Android || IOS录制mp3语音文件方法 - 李长鸿 - 博客园
Android Supported Media Formats :&
The Basics: Audio Codecs, Supported Audio Formats, and Audio Sessions&:&
对比 Android 与 iOS 所支持的音频格式,如果需要跨平台进行音频数据交换,只有 AAC 和 Linear PCM 可以选择
AAC 对音频进行压缩,音频数据较小
Linear PCM未对音频进行压缩,实时性更好,但音频数据较大
做一个有关于语音播放的项目,其中用到了android录音部分,查了好多资料只能录制amr和3gp格式,不能录制mp3格式;IOS端遇到同样问题,
只能录制caf格式,不能录制mp3,所以通用性就得到了考验。在痛苦中挣扎,在烦恼中度过,终于在苦思冥想中,解决了这个问题,总结核心部分如下:
无论是android还是IOS都是同一个思路,android中先想办法录制wav格式,然后通过lame进行转换。IOS是先录制caf文件,然后通过lame转换成mp3格式。
lame是一个mp3的免费格式库,baidu或者google都可以查到源代码,是用c写的。
在开发过程中,由于IOS可以直接录制成caf文件,但是android录制wav遇到了
困难。大家肯定会问为什么不用3gp或者amr直接转换成mp3呢?我最开始也是这样想的,但是经过无数次3gp ||
amr进行lame转换,发现都不成功,最终确认3gp || amr通过lame转换MP3格式行不通。
================================ IOS part =============================================
相对来说,IOS的转换比较简单,下载编译好的lame库文件,libmp3lame.a放在Frameworks下面,把lame.h这个头文件引入项目中,在项目中转换函数如下,其中需要指定被转换和转换后文件路径,视项目需要而定:
//转换Mp3格式方法
-&(IBAction)toMp3&{
&&&&NSString&*mp3AudioPath&=&[[NSString&stringWithFormat:@"%@/%@.mp3",&DOCUMENTS_FOLDER,&@"temp"]&retain];&//新转换mp3文件路径
&&&&//进入转换
&&&&int&read,&
&&&&FILE&*pcm&=&fopen([recorderFilePath&cStringUsingEncoding:1],&"rb");//被转换的文件
&&&&FILE&*mp3&=&fopen([mp3AudioPath&cStringUsingEncoding:1],&"wb");//转换后文件的存放位置
&&&&const&int&PCM_SIZE&=&8192;
&&&&const&int&MP3_SIZE&=&8192;
&&&&short&int&pcm_buffer[PCM_SIZE*2];
&&&&unsigned&char&mp3_buffer[MP3_SIZE];
&&&&lame_t&lame&=&lame_init();
&&&&lame_set_in_samplerate(lame,&44100);
&&&&lame_set_VBR(lame,&vbr_default);
&&&&lame_init_params(lame);
&&&&&&&&read&=&fread(pcm_buffer,&2*sizeof(short&int),&PCM_SIZE,&pcm);
&&&&&&&&if&(read&==&0)
&&&&&&&&&&&&
&&&&&&&&&&&&write&=&lame_encode_flush(lame,&mp3_buffer,&MP3_SIZE);
&&&&&&&&else
&&&&&&&&&&&&
&&&&&&&&&&&&write&=&lame_encode_buffer_interleaved(lame,&pcm_buffer,&read,&mp3_buffer,&MP3_SIZE);
&&&&&&&&fwrite(mp3_buffer,&write,&1,&mp3);
&&&&}&while&(read&!=&0);
&&&&lame_close(lame);
&&&&fclose(mp3);
&&&&fclose(pcm);
至此,新的mp3文件已经生成。
================================ android part ===============================================
android录制wav用到了一个文件ExtAudioRecorder.java,代码如下:
package com.example.
import java.io.F
import java.io.IOE
import java.io.RandomAccessF
import android.media.AudioF
import android.media.AudioR
import android.media.MediaR
import android.media.MediaRecorder.AudioS
import android.util.L
public class ExtAudioRecorder
&&& private final static int[] sampleRates = {4, 1};
&&& public static ExtAudioRecorder getInstanse(Boolean recordingCompressed)
&&&&&&& ExtAudioRecorder result =
&&&&&&& if(recordingCompressed)
&&&&&&&&&&& result = new ExtAudioRecorder(&&& false,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& AudioSource.MIC,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& sampleRates[3],
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& AudioFormat.CHANNEL_IN_STEREO,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //AudioFormat.CHANNEL_CONFIGURATION_MONO,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& AudioFormat.ENCODING_PCM_16BIT);
&&&&&&& else
&&&&&&&&&&& int i=0;
&&&&&&&&&&& do
&&&&&&&&&&& {
&&&&&&&&&&&&&&& result = new ExtAudioRecorder(&&& true,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& AudioSource.MIC,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& sampleRates[i],
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& AudioFormat.CHANNEL_CONFIGURATION_STEREO,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& AudioFormat.ENCODING_PCM_16BIT);
&&&&&&&&&&& } while((++i&sampleRates.length) & !(result.getState() == ExtAudioRecorder.State.INITIALIZING));
&&& * INITIALIZING : reco
&&& * READY : recorder has been initialized, recorder not yet started
&&& * RECORDING : recording
&&& * ERROR : reconstruction needed
&&& * STOPPED: reset needed
&&& public enum State {INITIALIZING, READY, RECORDING, ERROR, STOPPED};
&&& public static final boolean RECORDING_UNCOMPRESSED =
&&& public static final boolean RECORDING_COMPRESSED =
&&& // The interval in which the recorded samples are output to the file
&&& // Used only in uncompressed mode
&&& private static final int TIMER_INTERVAL = 120;
&&& // Toggles uncompressed recording on/ RECORDING_UNCOMPRESSED / RECORDING_COMPRESSED
&&& private boolean&&&&&&&& rU
&&& // Recorder used for uncompressed recording
&&& private AudioRecord&&&& audioRecorder =
&&& // Recorder used for compressed recording
&&& private MediaRecorder&& mediaRecorder =
&&& // Stores current amplitude (only in uncompressed mode)
&&& private int&&&&&&&&&&&& cAmplitude= 0;
&&& // Output file path
&&& private String&&&&&&&&& filePath =
&&& // R see State
&&& private State&&&&&&&&&&&&&
&&& // File writer (only in uncompressed mode)
&&& private RandomAccessFile randomAccessW
&&& // Number of channels, sample rate, sample size(size in bits), buffer size, audio source, sample size(see AudioFormat)
&&& private short&&&&&&&&&&&&&&&&&&& nC
&&& private int&&&&&&&&&&&&&&&&&&&&& sR
&&& private short&&&&&&&&&&&&&&&&&&& bS
&&& private int&&&&&&&&&&&&&&&&&&&&& bufferS
&&& private int&&&&&&&&&&&&&&&&&&&&& aS
&&& private int&&&&&&&&&&&&&&&&&&&&& aF
&&& // Number of frames written to file on each output(only in uncompressed mode)
&&& private int&&&&&&&&&&&&&&&&&&&&& frameP
&&& // Buffer for output(only in uncompressed mode)
&&& private byte[]&&&&&&&&&&&&&&&&&&
&&& // Number of bytes written to file after header(only in uncompressed mode)
&&& // after stop() is called, this size is written to the header/data chunk in the wave file
&&& private int&&&&&&&&&&&&&&&&&&&&& payloadS
&&& * Returns the state of the recorder in a RehearsalAudioRecord.State typed object.
&&& * Useful, as no exceptions are thrown.
&&& * @return recorder state
&&& public State getState()
&&& * Method used for recording.
&&& private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener()
&&&&&&& public void onPeriodicNotification(AudioRecord recorder)
&&&&&&&&&&& audioRecorder.read(buffer, 0, buffer.length); // Fill buffer
&&&&&&&&&&& try
&&&&&&&&&&& {
&&&&&&&&&&&&&&& randomAccessWriter.write(buffer); // Write buffer to file
&&&&&&&&&&&&&&& payloadSize += buffer.
&&&&&&&&&&&&&&& if (bSamples == 16)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& for (int i=0; i&buffer.length/2; i++)
&&&&&&&&&&&&&&&&&&& { // 16bit sample size
&&&&&&&&&&&&&&&&&&&&&&& short curSample = getShort(buffer[i*2], buffer[i*2+1]);
&&&&&&&&&&&&&&&&&&&&&&& if (curSample & cAmplitude)
&&&&&&&&&&&&&&&&&&&&&&& { // Check amplitude
&&&&&&&&&&&&&&&&&&&&&&&&&&& cAmplitude = curS
&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else&&&
&&&&&&&&&&&&&&& { // 8bit sample size
&&&&&&&&&&&&&&&&&&& for (int i=0; i&buffer. i++)
&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&& if (buffer[i] & cAmplitude)
&&&&&&&&&&&&&&&&&&&&&&& { // Check amplitude
&&&&&&&&&&&&&&&&&&&&&&&&&&& cAmplitude = buffer[i];
&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&&&&&& catch (IOException e)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), "Error occured in updateListener, recording is aborted");
&&&&&&&&&&&&&&& //stop();
&&&&&&&&&&& }
&&&&&&& public void onMarkerReached(AudioRecord recorder)
&&&&&&&&&&& // NOT USED
&&&& * Default constructor
&&&& * Instantiates a new recorder, in case of compressed recording the parameters can be left as 0.
&&&& * In case of errors, no exception is thrown, but the state is set to ERROR
&&& public ExtAudioRecorder(boolean uncompressed, int audioSource, int sampleRate, int channelConfig, int audioFormat)
&&&&&&& try
&&&&&&&&&&& rUncompressed =
&&&&&&&&&&& if (rUncompressed)
&&&&&&&&&&& { // RECORDING_UNCOMPRESSED
&&&&&&&&&&&&&&& if (audioFormat == AudioFormat.ENCODING_PCM_16BIT)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& bSamples = 16;
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& bSamples = 8;
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& if (channelConfig == AudioFormat.CHANNEL_CONFIGURATION_MONO)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& nChannels = 1;
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& nChannels = 2;
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& aSource = audioS
&&&&&&&&&&&&&&& sRate&& = sampleR
&&&&&&&&&&&&&&& aFormat = audioF
&&&&&&&&&&&&&&& framePeriod = sampleRate * TIMER_INTERVAL / 1000;
&&&&&&&&&&&&&&& bufferSize = framePeriod * 2 * bSamples * nChannels / 8;
&&&&&&&&&&&&&&& if (bufferSize & AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat))
&&&&&&&&&&&&&&& { // Check to make sure buffer size is not smaller than the smallest allowed one
&&&&&&&&&&&&&&&&&&& bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
&&&&&&&&&&&&&&&&&&& // Set frame period and timer interval accordingly
&&&&&&&&&&&&&&&&&&& framePeriod = bufferSize / ( 2 * bSamples * nChannels / 8 );
&&&&&&&&&&&&&&&&&&& Log.w(ExtAudioRecorder.class.getName(), "Increasing buffer size to " + Integer.toString(bufferSize));
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& audioRecorder = new AudioRecord(audioSource, sampleRate, channelConfig, audioFormat, bufferSize);
&&&&&&&&&&&&&&& if (audioRecorder.getState() != AudioRecord.STATE_INITIALIZED)
&&&&&&&&&&&&&&&&&&& throw new Exception("AudioRecord initialization failed");
&&&&&&&&&&&&&&& audioRecorder.setRecordPositionUpdateListener(updateListener);
&&&&&&&&&&&&&&& audioRecorder.setPositionNotificationPeriod(framePeriod);
&&&&&&&&&&& } else
&&&&&&&&&&& { // RECORDING_COMPRESSED
&&&&&&&&&&&&&&& mediaRecorder = new MediaRecorder();
&&&&&&&&&&&&&&& mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
&&&&&&&&&&&&&&& mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
&&&&&&&&&&&&&&& mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);&&&&&&&&&&&&&&&
&&&&&&&&&&& }
&&&&&&&&&&& cAmplitude = 0;
&&&&&&&&&&& filePath =
&&&&&&&&&&& state = State.INITIALIZING;
&&&&&&& } catch (Exception e)
&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&&& if (e.getMessage() != null)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), e.getMessage());
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), "Unknown error occured while initializing recording");
&&&&&&&&&&& }
&&&&&&&&&&& state = State.ERROR;
&&&& * Sets output file path, call directly after construction/reset.
&&&& * @param output file path
&&& public void setOutputFile(String argPath)
&&&&&&& try
&&&&&&&&&&& if (state == State.INITIALIZING)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& filePath = argP
&&&&&&&&&&&&&&& if (!rUncompressed)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& mediaRecorder.setOutputFile(filePath);&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&& catch (Exception e)
&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&&& if (e.getMessage() != null)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), e.getMessage());
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), "Unknown error occured while setting output path");
&&&&&&&&&&& }
&&&&&&&&&&& state = State.ERROR;
&&&& * Returns the largest amplitude sampled since the last call to this method.
&&&& * @return returns the largest amplitude since the last call, or 0 when not in recording state.
&&& public int getMaxAmplitude()
&&&&&&& if (state == State.RECORDING)
&&&&&&&&&&& if (rUncompressed)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& int result = cA
&&&&&&&&&&&&&&& cAmplitude = 0;
&&&&&&&&&&&&&&&
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& try
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& return mediaRecorder.getMaxAmplitude();
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& catch (IllegalStateException e)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&&&&&&&&&&& return 0;
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&& else
&&&&&&&&&&& return 0;
&&& * Prepares the recorder for recording, in case the recorder is not in the INITIALIZING state and the file path was not set
&&& * the recorder is set to the ERROR state, which makes a reconstruction necessary.
&&& * In case uncompressed recording is toggled, the header of the wave file is written.
&&& * In case of an exception, the state is changed to ERROR
&&& *&&&&&
&&& public void prepare()
&&&&&&& try
&&&&&&&&&&& if (state == State.INITIALIZING)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& if (rUncompressed)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& if ((audioRecorder.getState() == AudioRecord.STATE_INITIALIZED) & (filePath != null))
&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&& // write file header
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter = new RandomAccessFile(filePath, "rw");
&&&&&&&&&&&&&&&&&&&&&&&
randomAccessWriter.setLength(0); // Set file length to 0, to prevent
unexpected behavior in case the file already existed
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeBytes("RIFF");
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeInt(0); // Final file size not known yet, write 0
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeBytes("WAVE");
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeBytes("fmt ");
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeInt(Integer.reverseBytes(16)); // Sub-chunk size, 16 for PCM
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeShort(Short.reverseBytes((short) 1)); // AudioFormat, 1 for PCM
&&&&&&&&&&&&&&&&&&&&&&&
randomAccessWriter.writeShort(Short.reverseBytes(nChannels));// Number
of channels, 1 for mono, 2 for stereo
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeInt(Integer.reverseBytes(sRate)); // Sample rate
&&&&&&&&&&&&&&&&&&&&&&&
randomAccessWriter.writeInt(Integer.reverseBytes(sRate*bSamples*nChannels/8));
// Byte rate, SampleRate*NumberOfChannels*BitsPerSample/8
&&&&&&&&&&&&&&&&&&&&&&&
randomAccessWriter.writeShort(Short.reverseBytes((short)(nChannels*bSamples/8)));
// Block align, NumberOfChannels*BitsPerSample/8
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeShort(Short.reverseBytes(bSamples)); // Bits per sample
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeBytes("data");
&&&&&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeInt(0); // Data chunk size not known yet, write 0
&&&&&&&&&&&&&&&&&&&&&&& buffer = new byte[framePeriod*bSamples/8*nChannels];
&&&&&&&&&&&&&&&&&&&&&&& state = State.READY;
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), "prepare() method called on uninitialized recorder");
&&&&&&&&&&&&&&&&&&&&&&& state = State.ERROR;
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& mediaRecorder.prepare();
&&&&&&&&&&&&&&&&&&& state = State.READY;
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), "prepare() method called on illegal state");
&&&&&&&&&&&&&&& release();
&&&&&&&&&&&&&&& state = State.ERROR;
&&&&&&&&&&& }
&&&&&&& catch(Exception e)
&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&&& if (e.getMessage() != null)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), e.getMessage());
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), "Unknown error occured in prepare()");
&&&&&&&&&&& }
&&&&&&&&&&& state = State.ERROR;
&&&& *& Releases the resources associated with this class, and removes the unnecessary files, when necessary
&&& public void release()
&&&&&&& if (state == State.RECORDING)
&&&&&&&&&&& stop();
&&&&&&& else
&&&&&&&&&&& if ((state == State.READY) & (rUncompressed))
&&&&&&&&&&& {
&&&&&&&&&&&&&&& try
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& randomAccessWriter.close(); // Remove prepared file
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& catch (IOException e)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), "I/O exception occured while closing output file");
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& (new File(filePath)).delete();
&&&&&&&&&&& }
&&&&&&& if (rUncompressed)
&&&&&&&&&&& if (audioRecorder != null)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& audioRecorder.release();
&&&&&&&&&&& }
&&&&&&& else
&&&&&&&&&&& if (mediaRecorder != null)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& mediaRecorder.release();
&&&&&&&&&&& }
&&&& * Resets the recorder to the INITIALIZING state, as if it was just created.
&&&& * In case the class was in RECORDING state, the recording is stopped.
&&&& * In case of exceptions the class is set to the ERROR state.
&&& public void reset()
&&&&&&& try
&&&&&&&&&&& if (state != State.ERROR)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& release();
&&&&&&&&&&&&&&& filePath = // Reset file path
&&&&&&&&&&&&&&& cAmplitude = 0; // Reset amplitude
&&&&&&&&&&&&&&& if (rUncompressed)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& audioRecorder = new AudioRecord(aSource, sRate, nChannels+1, aFormat, bufferSize);
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& mediaRecorder = new MediaRecorder();
&&&&&&&&&&&&&&&&&&& mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
&&&&&&&&&&&&&&&&&&& mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
&&&&&&&&&&&&&&&&&&& mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& state = State.INITIALIZING;
&&&&&&&&&&& }
&&&&&&& catch (Exception e)
&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), e.getMessage());
&&&&&&&&&&& state = State.ERROR;
&&&& * Starts the recording, and sets the state to RECORDING.
&&&& * Call after prepare().
&&& public void start()
&&&&&&& if (state == State.READY)
&&&&&&&&&&& if (rUncompressed)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& payloadSize = 0;
&&&&&&&&&&&&&&& audioRecorder.startRecording();
&&&&&&&&&&&&&&& audioRecorder.read(buffer, 0, buffer.length);
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& mediaRecorder.start();
&&&&&&&&&&& }
&&&&&&&&&&& state = State.RECORDING;
&&&&&&& else
&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), "start() called on illegal state");
&&&&&&&&&&& state = State.ERROR;
&&&& *& Stops the recording, and sets the state to STOPPED.
&&&& * In case of further usage, a reset is needed.
&&&& * Also finalizes the wave file in case of uncompressed recording.
&&& public void stop()
&&&&&&& if (state == State.RECORDING)
&&&&&&&&&&& if (rUncompressed)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& audioRecorder.stop();
&&&&&&&&&&&&&&& try
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& randomAccessWriter.seek(4); // Write size to RIFF header
&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeInt(Integer.reverseBytes(36+payloadSize));
&&&&&&&&&&&&&&&&&&& randomAccessWriter.seek(40); // Write size to Subchunk2Size field
&&&&&&&&&&&&&&&&&&& randomAccessWriter.writeInt(Integer.reverseBytes(payloadSize));
&&&&&&&&&&&&&&&&&&& randomAccessWriter.close();
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& catch(IOException e)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& e.printStackTrace();
&&&&&&&&&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), "I/O exception occured while closing output file");
&&&&&&&&&&&&&&&&&&& state = State.ERROR;
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& mediaRecorder.stop();
&&&&&&&&&&& }
&&&&&&&&&&& state = State.STOPPED;
&&&&&&& else
&&&&&&&&&&& Log.e(ExtAudioRecorder.class.getName(), "stop() called on illegal state");
&&&&&&&&&&& state = State.ERROR;
&&&& * Converts a byte[2] to a short, in LITTLE_ENDIAN format
&&& private short getShort(byte argB1, byte argB2)
&&&&&&& return (short)(argB1 | (argB2 && 8));
在开始录音的地方代码如下:
extRecorder&=&ExtAudioRecorder.getInstanse(false);&&//设置为false,录制wav
extRecorder.setOutputFile(tempPath);
//输出SD卡路径
extRecorder.prepare();
extRecorder.start();
在停止录音的地方代码如下:
extRecorder.stop();
extRecorder.release();&
得到wav文件后,就可以开始lame转换mp3了,如下:
首先,导入相关lame的包,baidu和google都可以搜到lame的库文件,截图如下:
添加LameActivity.java文件,进行mp3的合成操作,LameActivity.java代码如下:
package cn.itcast.
import java.io.F
import com.example.util.FileU
import android.app.A
import android.app.ProgressD
import android.content.I
import android.os.B
import android.util.L
import android.view.V
import android.view.W
import android.widget.T
public class LameActivity extends Activity {
&&& private ProgressD
&&& private String tempP
&&& private String realP
&&& static{
&&&&&&& System.loadLibrary("mp3lame");& //加载mp3lame库文件
&&& public native String getVersion();
&&& public native void Convert(String wav,String mp3);
&&& @Override
&&& public void onCreate(Bundle savedInstanceState) {
&&&&&&& super.onCreate(savedInstanceState);
&&&&&&& requestWindowFeature(Window.FEATURE_NO_TITLE);
&&&&&&& pd = new ProgressDialog(this);
&&&&&&& pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
&&&&&&& Intent intent = getIntent();
&&&&&&& tempPath = intent.getStringExtra("tempPath");
&&&&&&& realPath = intent.getStringExtra("realPath");
&&&&&&& //显示具体进度的进度条对话框
&&&&&&& convert(null);& //合成MP3语音
&&& public void getlameversion(View view){
&&&&&&& String version = getVersion();
&&&&&&& Toast.makeText(this, version, Toast.LENGTH_SHORT).show();
&&& public void convert(View view){
&&&&&&& final String wav = tempP
&&&&&&& final String mp3 = realP
&&&&&&& File wavfile = new File(wav);
&&&&&&& if(wavfile.exists()){
&&&&&&&&&&& int length = (int) wavfile.length();
&&&&&&&&&&& pd.setMax(length);
&&&&&&&&&&& pd.show();
&&&&&&&&&&& new Thread(){
&&&&&&&&&&&&&&& public void run() {
&&&&&&&&&&&&&&&&&&& Convert(wav, mp3);
&&&&&&&&&&&&&&&&&&& FileUtil.deleteTempFile(tempPath);
&&&&&&&&&&&&&&&&&&& pd.dismiss();
&&&&&&&&&&&&&&&&&&& setResult(100);
&&&&&&&&&&&&&&&&&&& finish();
&&&&&&&&&&&&&&& };
&&&&&&&&&&& }.start();
&&&&&&& }else{
&&&&&&&&&&& Log.i("Debug", "合成MP3文件不存在");
&&&&&&&&&&& finish();
&&&&&&&&&&&
&&& public void setPDProgress(int progress){
&&&&&&& pd.setProgress(progress);
利用此文件就可以进行合成mp3,由于项目中涉及业务逻辑的问题比较敏感,只把lame的使用部分进行记录,给遇到同样问题的童鞋们一个参考。
阅读(...) 评论()
Powered By:}

我要回帖

更多关于 android pcm转mp3 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信