diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java
index 0435da5..80e5ad8 100644
--- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java
+++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java
@@ -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
diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java
index 04e69db..4629078 100644
--- a/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java
+++ b/app/src/main/java/com/github/axet/audiorecorder/activities/SettingsActivity.java
@@ -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
diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/FileEncoder.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/FileEncoder.java
index 886d13d..3db13e7 100644
--- a/app/src/main/java/com/github/axet/audiorecorder/encoders/FileEncoder.java
+++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/FileEncoder.java
@@ -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 {
diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java
new file mode 100755
index 0000000..513c830
--- /dev/null
+++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java
@@ -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;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/Wav.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatWAV.java
similarity index 93%
rename from app/src/main/java/com/github/axet/audiorecorder/encoders/Wav.java
rename to app/src/main/java/com/github/axet/audiorecorder/encoders/FormatWAV.java
index cac5efd..04bf58c 100755
--- a/app/src/main/java/com/github/axet/audiorecorder/encoders/Wav.java
+++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatWAV.java
@@ -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;
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3078605..2aa6034 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -23,12 +23,12 @@
- .wav (default)
- - .aac
+ - .m4a
- wav
- - aac
+ - m4a
Audio Recorder
diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml
index 9e72cce..ebbb6e0 100644
--- a/app/src/main/res/xml/pref_general.xml
+++ b/app/src/main/res/xml/pref_general.xml
@@ -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" />