HarmonyOS鸿蒙Next中java实现音频混合

HarmonyOS鸿蒙Next中java实现音频混合

public class AudioMix {

    public static byte[] mix(final byte[] a, final byte[] b, final boolean bigEndian) {
        final byte[] aa;
        final byte[] bb;

        final int length = Math.max(a.length, b.length);
        // ensure same lengths
        if (a.length != b.length) {
            aa = new byte[length];
            bb = new byte[length];
            System.arraycopy(a, 0, aa, 0, a.length);
            System.arraycopy(b, 0, bb, 0, b.length);
        } else {
            aa = a;
            bb = b;
        }

        // convert to samples
        final int[] aSamples = toSamples(aa, bigEndian);
        final int[] bSamples = toSamples(bb, bigEndian);

        // mix by adding
        final int[] mix = new int[aSamples.length];
        for (int i=0; i<mix.length; i++) {
            mix[i] = aSamples[i] + bSamples[i];
            // enforce min and max (may introduce clipping)
            mix[i] = Math.min(Short.MAX_VALUE, mix[i]);
            mix[i] = Math.max(Short.MIN_VALUE, mix[i]);
        }

        // convert back to bytes
        return toBytes(mix, bigEndian);
    }

    private static int[] toSamples(final byte[] byteSamples, final boolean bigEndian) {
        final int bytesPerChannel = 2;
        final int length = byteSamples.length / bytesPerChannel;
        if ((length % 2) != 0) throw new IllegalArgumentException("For 16 bit audio, length must be even: " + length);
        final int[] samples = new int[length];
        for (int sampleNumber = 0; sampleNumber < length; sampleNumber++) {
            final int sampleOffset = sampleNumber * bytesPerChannel;
            final int sample = bigEndian
                    ? byteToIntBigEndian(byteSamples, sampleOffset, bytesPerChannel)
                    : byteToIntLittleEndian(byteSamples, sampleOffset, bytesPerChannel);
            samples[sampleNumber] = sample;
        }
        return samples;
    }

    private static byte[] toBytes(final int[] intSamples, final boolean bigEndian) {
        final int bytesPerChannel = 2;
        final int length = intSamples.length * bytesPerChannel;
        final byte[] bytes = new byte[length];
        for (int sampleNumber = 0; sampleNumber < intSamples.length; sampleNumber++) {
            final byte[] b = bigEndian
                    ? intToByteBigEndian(intSamples[sampleNumber], bytesPerChannel)
                    : intToByteLittleEndian(intSamples[sampleNumber], bytesPerChannel);
            System.arraycopy(b, 0, bytes, sampleNumber * bytesPerChannel, bytesPerChannel);
        }
        return bytes;
    }

    // from https://github.com/hendriks73/jipes/blob/master/src/main/java/com/tagtraum/jipes/audio/AudioSignalSource.java#L238
    private static int byteToIntLittleEndian(final byte[] buf, final int offset, final int bytesPerSample) {
        int sample = 0;
        for (int byteIndex = 0; byteIndex < bytesPerSample; byteIndex++) {
            final int aByte = buf[offset + byteIndex] & 0xff;
            sample += aByte << 8 * (byteIndex);
        }
        return (short)sample;
    }

    // from https://github.com/hendriks73/jipes/blob/master/src/main/java/com/tagtraum/jipes/audio/AudioSignalSource.java#L247
    private static int byteToIntBigEndian(final byte[] buf, final int offset, final int bytesPerSample) {
        int sample = 0;
        for (int byteIndex = 0; byteIndex < bytesPerSample; byteIndex++) {
            final int aByte = buf[offset + byteIndex] & 0xff;
            sample += aByte << (8 * (bytesPerSample - byteIndex - 1));
        }
        return (short)sample;
    }

    private static byte[] intToByteLittleEndian(final int sample, final int bytesPerSample) {
        byte[] buf = new byte[bytesPerSample];
        for (int byteIndex = 0; byteIndex < bytesPerSample; byteIndex++) {
            buf[byteIndex] = (byte)((sample >>> (8 * byteIndex)) & 0xFF);
        }
        return buf;
    }

    private static byte[] intToByteBigEndian(final int sample, final int bytesPerSample) {
        byte[] buf = new byte[bytesPerSample];
        for (int byteIndex = 0; byteIndex < bytesPerSample; byteIndex++) {
            buf[byteIndex] = (byte)((sample >>> (8 * (bytesPerSample - byteIndex - 1))) & 0xFF);
        }
        return buf;
    }
}

转载:https://stackoverflow.com/questions/60688956/java-combining-4-separate-audio-byte-arrays-into-single-wav-audio-file


更多关于HarmonyOS鸿蒙Next中java实现音频混合的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS鸿蒙Next中,Java实现音频混合可以通过使用AudioManagerAudioTrack类来完成。首先,使用AudioManager获取音频流类型和音量控制。然后,创建AudioTrack实例来播放音频数据。对于音频混合,可以将多个音频源的数据进行叠加处理,生成混合后的音频数据,并通过AudioTrack播放。

具体步骤如下:

  1. 初始化AudioTrack,设置音频格式、采样率、声道数等参数。
  2. 读取多个音频源的数据,进行叠加处理,生成混合后的音频数据。
  3. 将混合后的音频数据写入AudioTrack的缓冲区。
  4. 调用AudioTrackplay方法开始播放混合后的音频。

示例代码片段:

AudioTrack audioTrack = new AudioTrack(
    AudioManager.STREAM_MUSIC,
    sampleRateInHz,
    AudioFormat.CHANNEL_OUT_STEREO,
    AudioFormat.ENCODING_PCM_16BIT,
    bufferSize,
    AudioTrack.MODE_STREAM
);

byte[] mixedAudioData = mixAudioData(audioData1, audioData2);

audioTrack.write(mixedAudioData, 0, mixedAudioData.length);
audioTrack.play();

其中,mixAudioData方法用于将两个音频数据源进行混合处理。

更多关于HarmonyOS鸿蒙Next中java实现音频混合的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,使用Java实现音频混合可以通过AudioManagerAudioTrack类来完成。首先,创建多个AudioTrack实例来加载不同的音频流。然后,使用AudioManager管理音频焦点,确保混合时不会冲突。通过AudioTrackwrite方法将音频数据写入缓冲区,并利用AudioTrackplay方法播放混合后的音频。注意处理音频格式、采样率和通道数的一致性,以确保混合效果正确。

回到顶部