m4a encoding
This commit is contained in:
parent
c65b1277a0
commit
d422f68e41
7 changed files with 150 additions and 16 deletions
|
|
@ -37,16 +37,16 @@ import android.widget.Toast;
|
|||
import com.github.axet.audiorecorder.R;
|
||||
import com.github.axet.audiorecorder.app.MainApplication;
|
||||
import com.github.axet.audiorecorder.app.Storage;
|
||||
import com.github.axet.audiorecorder.encoders.FileEncoder;
|
||||
import com.github.axet.audiorecorder.encoders.Encoder;
|
||||
import com.github.axet.audiorecorder.encoders.EncoderInfo;
|
||||
import com.github.axet.audiorecorder.encoders.Wav;
|
||||
import com.github.axet.audiorecorder.encoders.FileEncoder;
|
||||
import com.github.axet.audiorecorder.encoders.FormatM4A;
|
||||
import com.github.axet.audiorecorder.encoders.FormatWAV;
|
||||
import com.github.axet.audiorecorder.widgets.PitchView;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class RecordingActivity extends AppCompatActivity {
|
||||
public static final String TAG = RecordingActivity.class.getSimpleName();
|
||||
|
|
@ -551,7 +551,19 @@ public class RecordingActivity extends AppCompatActivity {
|
|||
|
||||
EncoderInfo info = getInfo();
|
||||
|
||||
encoder = new FileEncoder(this, in, new Wav(info, out));
|
||||
Encoder e = null;
|
||||
|
||||
SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
String ext = shared.getString(MainApplication.PREFERENCE_ENCODING, "");
|
||||
|
||||
if (ext.equals("wav")) {
|
||||
e = new FormatWAV(info, out);
|
||||
}
|
||||
if (ext.equals("m4a")) {
|
||||
e = new FormatM4A(info, out);
|
||||
}
|
||||
|
||||
encoder = new FileEncoder(this, in, e);
|
||||
|
||||
final ProgressDialog d = new ProgressDialog(this);
|
||||
d.setTitle("Encoding...");
|
||||
|
|
@ -564,8 +576,7 @@ public class RecordingActivity extends AppCompatActivity {
|
|||
encoder.run(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int i = encoder.getProgress();
|
||||
d.setProgress(i);
|
||||
d.setProgress(encoder.getProgress());
|
||||
}
|
||||
}, new Runnable() {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -217,7 +217,15 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
|||
bindPreferenceSummaryToValue(findPreference(MainApplication.PREFERENCE_STORAGE));
|
||||
}
|
||||
|
||||
bindPreferenceSummaryToValue(findPreference(MainApplication.PREFERENCE_RATE));
|
||||
Preference rate = findPreference(MainApplication.PREFERENCE_RATE);
|
||||
|
||||
if (Build.VERSION.SDK_INT < 21) {
|
||||
getPreferenceScreen().removePreference(rate);
|
||||
} else {
|
||||
bindPreferenceSummaryToValue(rate);
|
||||
}
|
||||
|
||||
bindPreferenceSummaryToValue(findPreference(MainApplication.PREFERENCE_ENCODING));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@ public class FileEncoder {
|
|||
|
||||
int len = is.read(buf);
|
||||
if (len <= 0) {
|
||||
Log.d("23", "end");
|
||||
handler.post(done);
|
||||
return;
|
||||
}
|
||||
if (len > 0) {
|
||||
} else {
|
||||
short[] shorts = new short[len / 2];
|
||||
ByteBuffer.wrap(buf, 0, len).order(ByteOrder.BIG_ENDIAN).asShortBuffer().get(shorts);
|
||||
encoder.encode(shorts);
|
||||
|
|
@ -65,10 +65,13 @@ public class FileEncoder {
|
|||
}
|
||||
}
|
||||
}
|
||||
Log.d("23", "interrupted " + Thread.currentThread().isInterrupted());
|
||||
} catch (IOException e) {
|
||||
Log.d("23", "error " + e.getMessage());
|
||||
t = e;
|
||||
handler.post(error);
|
||||
} finally {
|
||||
Log.d("23", "close");
|
||||
encoder.close();
|
||||
if (is != null) {
|
||||
try {
|
||||
|
|
|
|||
112
app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java
Executable file
112
app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java
Executable file
|
|
@ -0,0 +1,112 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.media.MediaCodec;
|
||||
import android.media.MediaCodecInfo;
|
||||
import android.media.MediaFormat;
|
||||
import android.media.MediaMuxer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@TargetApi(21)
|
||||
public class FormatM4A implements Encoder {
|
||||
EncoderInfo info;
|
||||
MediaCodec encoder;
|
||||
MediaMuxer muxer;
|
||||
int audioTrackIndex;
|
||||
long NumSamples;
|
||||
|
||||
public FormatM4A() {
|
||||
}
|
||||
|
||||
public FormatM4A(EncoderInfo info, File out) {
|
||||
this.info = info;
|
||||
|
||||
MediaFormat format = new MediaFormat();
|
||||
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
|
||||
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
|
||||
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, info.sampleRate);
|
||||
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, info.channels);
|
||||
format.setInteger(MediaFormat.KEY_BIT_RATE, 128 * 1024);
|
||||
|
||||
try {
|
||||
encoder = MediaCodec.createEncoderByType("audio/mp4a-latm");
|
||||
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
|
||||
encoder.start();
|
||||
|
||||
muxer = new MediaMuxer(out.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void encode(short[] buf) {
|
||||
int len = buf.length * 2;
|
||||
int inputIndex = encoder.dequeueInputBuffer(-1);
|
||||
if (inputIndex >= 0) {
|
||||
ByteBuffer input = encoder.getInputBuffer(inputIndex);
|
||||
input.clear();
|
||||
for (int i = 0; i < buf.length; i++)
|
||||
input.putShort(buf[i]);
|
||||
encoder.queueInputBuffer(inputIndex, 0, len, getCurrentTimeStamp(), 0);
|
||||
}
|
||||
|
||||
NumSamples += buf.length / info.channels;
|
||||
|
||||
encode();
|
||||
}
|
||||
|
||||
void encode() {
|
||||
MediaCodec.BufferInfo outputInfo = new MediaCodec.BufferInfo();
|
||||
int outputIndex = encoder.dequeueOutputBuffer(outputInfo, 0);
|
||||
if (outputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
|
||||
audioTrackIndex = muxer.addTrack(encoder.getOutputFormat());
|
||||
muxer.start();
|
||||
}
|
||||
|
||||
while (outputIndex >= 0) {
|
||||
ByteBuffer output = encoder.getOutputBuffer(outputIndex);
|
||||
output.position(outputInfo.offset);
|
||||
output.limit(outputInfo.offset + outputInfo.size);
|
||||
|
||||
// byte[] out = new byte[outputInfo.size];
|
||||
// output.get(out);
|
||||
|
||||
muxer.writeSampleData(audioTrackIndex, output, outputInfo);
|
||||
|
||||
encoder.releaseOutputBuffer(outputIndex, false);
|
||||
outputIndex = encoder.dequeueOutputBuffer(outputInfo, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
end();
|
||||
encode();
|
||||
|
||||
encoder.stop();
|
||||
encoder.release();
|
||||
|
||||
muxer.stop();
|
||||
muxer.release();
|
||||
}
|
||||
|
||||
long getCurrentTimeStamp() {
|
||||
return NumSamples * 1000 * 1000 / info.sampleRate;
|
||||
}
|
||||
|
||||
void end() {
|
||||
int inputIndex = encoder.dequeueInputBuffer(-1);
|
||||
if (inputIndex >= 0) {
|
||||
ByteBuffer input = encoder.getInputBuffer(inputIndex);
|
||||
input.clear();
|
||||
encoder.queueInputBuffer(inputIndex, 0, 0, getCurrentTimeStamp(), MediaCodec.BUFFER_FLAG_END_OF_STREAM);
|
||||
}
|
||||
}
|
||||
|
||||
public EncoderInfo getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import java.io.*;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class Wav implements Encoder {
|
||||
public class FormatWAV implements Encoder {
|
||||
int NumSamples;
|
||||
EncoderInfo info;
|
||||
int BytesPerSample;
|
||||
|
|
@ -16,10 +16,10 @@ public class Wav implements Encoder {
|
|||
|
||||
ByteOrder order = ByteOrder.LITTLE_ENDIAN;
|
||||
|
||||
public Wav() {
|
||||
public FormatWAV() {
|
||||
}
|
||||
|
||||
public Wav(EncoderInfo info, File out) {
|
||||
public FormatWAV(EncoderInfo info, File out) {
|
||||
this.info = info;
|
||||
NumSamples = 0;
|
||||
|
||||
|
|
@ -23,12 +23,12 @@
|
|||
|
||||
<string-array name="encodings" >
|
||||
<item>.wav (default)</item>
|
||||
<item>.aac</item>
|
||||
<item>.m4a</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="encodings_values" >
|
||||
<item>wav</item>
|
||||
<item>aac</item>
|
||||
<item>m4a</item>
|
||||
</string-array>
|
||||
|
||||
<string name="title_activity_main">Audio Recorder</string>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
android:key="encoding"
|
||||
android:negativeButtonText="@null"
|
||||
android:positiveButtonText="@null"
|
||||
android:summary="Output file formats (.wav, .aac, ...)"
|
||||
android:summary="Output file formats (.wav, .m4a, ...)"
|
||||
android:title="Encoding" />
|
||||
|
||||
<SwitchPreference
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue