Ver Fonte

fix: 修复部分安卓机型单声道录音导致声音加速问题

hwh97 há 5 anos atrás
pai
commit
93bea8dddb

+ 93 - 2
android/src/main/kotlin/cn/i2edu/dubbing_lib/audioUtils/AndroidAudioDecoder.java

@@ -4,6 +4,7 @@ import android.media.MediaCodec;
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
 import android.util.Log;
+import cn.i2edu.dubbing_lib.audioUtils.compose.CommonFunction;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -104,9 +105,12 @@ public class AndroidAudioDecoder extends AudioDecoder {
                         byte[] data = new byte[info.size];
                         outBuf.get(data);
                         totalRawSize += data.length;
-                        fosDecoder.write(data);
+
+                        byte[] resultByteArray = ConvertChannelNumber(rawAudioInfo.channel, 2, 2, data);
+
+                        fosDecoder.write(resultByteArray);
                         if (mOnAudioDecoderListener != null)
-                            mOnAudioDecoderListener.onDecode(data, info.presentationTimeUs / audioDurationUs);
+                            mOnAudioDecoderListener.onDecode(resultByteArray, info.presentationTimeUs / audioDurationUs);
                         Log.e("AndroidAudioDecoder", mEncodeFile + " presentationTimeUs : " + info.presentationTimeUs);
                     }
 
@@ -140,4 +144,91 @@ public class AndroidAudioDecoder extends AudioDecoder {
         }
 
     }
+
+    private static byte[] ConvertChannelNumber(int sourceChannelCount, int outputChannelCount, int byteNumber,
+                                               byte[] sourceByteArray) {
+        if (sourceChannelCount == outputChannelCount) {
+            return sourceByteArray;
+        }
+
+        switch (byteNumber) {
+            case 1:
+            case 2:
+                break;
+            default:
+                return sourceByteArray;
+        }
+
+        int sourceByteArrayLength = sourceByteArray.length;
+
+        byte[] byteArray;
+
+        switch (sourceChannelCount) {
+            case 1:
+                switch (outputChannelCount) {
+                    case 2:
+                        byteArray = new byte[sourceByteArrayLength * 2];
+
+                        byte firstByte;
+                        byte secondByte;
+
+                        switch (byteNumber) {
+                            case 1:
+                                for (int index = 0; index < sourceByteArrayLength; index += 1) {
+                                    firstByte = sourceByteArray[index];
+
+                                    byteArray[2 * index] = firstByte;
+                                    byteArray[2 * index + 1] = firstByte;
+                                }
+                                break;
+                            case 2:
+                                for (int index = 0; index < sourceByteArrayLength; index += 2) {
+                                    firstByte = sourceByteArray[index];
+                                    secondByte = sourceByteArray[index + 1];
+
+                                    byteArray[2 * index] = firstByte;
+                                    byteArray[2 * index + 1] = secondByte;
+                                    byteArray[2 * index + 2] = firstByte;
+                                    byteArray[2 * index + 3] = secondByte;
+                                }
+                                break;
+                        }
+
+                        return byteArray;
+                }
+                break;
+            case 2:
+                switch (outputChannelCount) {
+                    case 1:
+                        int outputByteArrayLength = sourceByteArrayLength / 2;
+
+                        byteArray = new byte[outputByteArrayLength];
+
+                        switch (byteNumber) {
+                            case 1:
+                                for (int index = 0; index < outputByteArrayLength; index += 2) {
+                                    short averageNumber =
+                                            (short) ((short) sourceByteArray[2 * index] + (short) sourceByteArray[2 * index + 1]);
+                                    byteArray[index] = (byte) (averageNumber >> 1);
+                                }
+                                break;
+                            case 2:
+                                for (int index = 0; index < outputByteArrayLength; index += 2) {
+                                    byte resultByte[] = CommonFunction.AverageShortByteArray(sourceByteArray[2 * index],
+                                            sourceByteArray[2 * index + 1], sourceByteArray[2 * index + 2],
+                                            sourceByteArray[2 * index + 3], false);
+
+                                    byteArray[index] = resultByte[0];
+                                    byteArray[index + 1] = resultByte[1];
+                                }
+                                break;
+                        }
+
+                        return byteArray;
+                }
+                break;
+        }
+
+        return sourceByteArray;
+    }
 }

+ 149 - 0
android/src/main/kotlin/cn/i2edu/dubbing_lib/audioUtils/compose/CommonFunction.java

@@ -0,0 +1,149 @@
+package cn.i2edu.dubbing_lib.audioUtils.compose;
+
+import android.os.Looper;
+
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+
+public class CommonFunction {
+    public static String FormatRecordTime(int recordTime) {
+        int minute = recordTime / 60;
+        int second = recordTime % 60;
+
+        String formatRecordTime = "";
+
+        if (minute != 0) {
+            formatRecordTime += String.valueOf(minute) + "′";
+        }
+
+        formatRecordTime += String.valueOf(second) + "″";
+
+        return formatRecordTime;
+    }
+
+    public static String GetDate() {
+        long time = System.currentTimeMillis();
+        SimpleDateFormat simpleDateFormat =
+                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
+        String date = simpleDateFormat.format(time);
+        return date;
+    }
+
+    public static String GetDate(long time) {
+        SimpleDateFormat simpleDateFormat =
+                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
+        String date = simpleDateFormat.format(time);
+        return date;
+    }
+
+    public static boolean notEmpty(CharSequence text) {
+        return !isEmpty(text);
+    }
+
+    public static boolean isEmpty(CharSequence text) {
+        if (text == null || text.length() == 0) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public static byte[] GetBytes(short shortValue, boolean bigEnding) {
+        byte[] byteArray = new byte[2];
+
+        if (bigEnding) {
+            byteArray[1] = (byte) (shortValue & 0x00ff);
+            shortValue >>= 8;
+            byteArray[0] = (byte) (shortValue & 0x00ff);
+        } else {
+            byteArray[0] = (byte) (shortValue & 0x00ff);
+            shortValue >>= 8;
+            byteArray[1] = (byte) (shortValue & 0x00ff);
+        }
+
+        return byteArray;
+    }
+
+    public static short GetShort(byte firstByte, byte secondByte, boolean bigEnding) {
+        short shortValue = 0;
+
+        if (bigEnding) {
+            shortValue |= (firstByte & 0x00ff);
+            shortValue <<= 8;
+            shortValue |= (secondByte & 0x00ff);
+        } else {
+            shortValue |= (secondByte & 0x00ff);
+            shortValue <<= 8;
+            shortValue |= (firstByte & 0x00ff);
+        }
+
+        return shortValue;
+    }
+
+    public static byte[] AverageShortByteArray(byte firstShortHighByte, byte firstShortLowByte,
+                                               byte secondShortHighByte, byte secondShortLowByte,
+                                               boolean bigEnding) {
+        short firstShort =
+                CommonFunction.GetShort(firstShortHighByte, firstShortLowByte, bigEnding);
+        short secondShort =
+                CommonFunction.GetShort(secondShortHighByte, secondShortLowByte, bigEnding);
+        return CommonFunction.GetBytes((short) (firstShort / 2 + secondShort / 2), bigEnding);
+    }
+
+    public static short AverageShort(byte firstShortHighByte, byte firstShortLowByte,
+                                     byte secondShortHighByte, byte secondShortLowByte,
+                                     boolean bigEnding) {
+        short firstShort =
+                CommonFunction.GetShort(firstShortHighByte, firstShortLowByte, bigEnding);
+        short secondShort =
+                CommonFunction.GetShort(secondShortHighByte, secondShortLowByte, bigEnding);
+        return (short) (firstShort / 2 + secondShort / 2);
+    }
+
+    public static short WeightShort(byte firstShortHighByte, byte firstShortLowByte,
+                                    byte secondShortHighByte, byte secondShortLowByte,
+                                    float firstWeight, float secondWeight, boolean bigEnding) {
+        short firstShort =
+                CommonFunction.GetShort(firstShortHighByte, firstShortLowByte, bigEnding);
+        short secondShort =
+                CommonFunction.GetShort(secondShortHighByte, secondShortLowByte, bigEnding);
+        return (short) (firstShort * firstWeight + secondShort * secondWeight);
+    }
+
+    public static boolean IsInMainThread() {
+        return Looper.myLooper() == Looper.getMainLooper();
+    }
+
+    public static byte[] GetByteBuffer(short[] shortArray, boolean bigEnding) {
+        return GetByteBuffer(shortArray, shortArray.length, bigEnding);
+    }
+
+    public static byte[] GetByteBuffer(short[] shortArray, int shortArrayLength,
+                                       boolean bigEnding) {
+        int actualShortArrayLength = shortArray.length;
+
+        if (shortArrayLength > actualShortArrayLength) {
+            shortArrayLength = actualShortArrayLength;
+        }
+
+        short shortValue;
+        byte[] byteArray = new byte[2 * shortArrayLength];
+
+        for (int i = 0; i < shortArrayLength; i++) {
+            shortValue = shortArray[i];
+
+            if (bigEnding) {
+                byteArray[i * 2 + 1] = (byte) (shortValue & 0x00ff);
+                shortValue >>= 8;
+                byteArray[i * 2] = (byte) (shortValue & 0x00ff);
+            } else {
+                byteArray[i * 2] = (byte) (shortValue & 0x00ff);
+                shortValue >>= 8;
+                byteArray[i * 2 + 1] = (byte) (shortValue & 0x00ff);
+            }
+        }
+
+        return byteArray;
+    }
+}