在android中混合音频

Posted

技术标签:

【中文标题】在android中混合音频【英文标题】:Mix audio in android 【发布时间】:2013-05-27 04:23:24 【问题描述】:

我尝试点击此链接:

http://mobilengineering.blogspot.com/2012/06/audio-mix-and-record-in-android.html?showComment=1369622288028#c2333829870074273419

但是混合音频文件后,sdcard上的文件(mixed.wav)无法播放,不知道为什么。 你能帮助我吗?。非常感谢..

这是我的代码:

公共类 MainActivity 扩展 Activity

 public static final int FREQUENCY = 44100;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    try 
        mixSound();
     catch (IOException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    


private void mixSound() throws IOException 
    AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, 44100, AudioTrack.MODE_STREAM);

    InputStream in1 = getResources().openRawResource(R.raw.media_b);
    InputStream in2 = getResources().openRawResource(R.raw.media_c);

    byte[] arrayMusic1 = null;
    arrayMusic1 = new byte[in1.available()];
    arrayMusic1 = createMusicArray(in1);
    in1.close();

    byte[] arrayMusic2 = null;
    arrayMusic2 = new byte[in2.available()];
    arrayMusic2 = createMusicArray(in2);
    in2.close();


    byte[] output = new byte[arrayMusic1.length];

    audioTrack.play();

    for (int i = 0; i < output.length; i++) 
        float samplef1 = arrayMusic1[i] / 128.0f; 
        float samplef2 = arrayMusic2[i] / 128.0f;
        float mixed    = samplef1 + samplef2;

        // reduce the volume a bit:
        mixed *= 0.8;
        // hard clipping
        if (mixed > 1.0f)  mixed = 1.0f;
        if (mixed < -1.0f) mixed = -1.0f;

        byte outputSample = (byte) (mixed * 128.0f);
        output[i]         = outputSample;   
    

    audioTrack.write(output, 0, output.length);
    convertByteToFile(output);


public static byte[] createMusicArray(InputStream is) throws IOException 

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buff = new byte[10240];
    int i = Integer.MAX_VALUE;
    while ((i = is.read(buff, 0, buff.length)) > 0) 
        baos.write(buff, 0, i);
    

    return baos.toByteArray(); // be sure to close InputStream in calling function



public static void convertByteToFile(byte[] fileBytes) throws FileNotFoundException 

    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/mixed.wav"));
    try 
        bos.write(fileBytes);
        bos.flush();
        bos.close();    
     catch (IOException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    

【问题讨论】:

【参考方案1】:

您输出的只是 PCM 数据。一个有效的 WAV 文件也需要一个头文件:

Offset    Size  Name           Description
------------------------------------------------------------------------
0         4     ChunkID        Contains the letters "RIFF" in ASCII form
                               (0x52494646 big-endian form).
4         4     ChunkSize      36 + SubChunk2Size, or more precisely:
                               4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
                               This is the size of the rest of the chunk 
                               following this number.  This is the size of the 
                               entire file in bytes minus 8 bytes for the
                               two fields not included in this count:
                               ChunkID and ChunkSize.
8         4     Format         Contains the letters "WAVE"
                               (0x57415645 big-endian form).

12        4     Subchunk1ID    Contains the letters "fmt "
                               (0x666d7420 big-endian form).
16        4     Subchunk1Size  16 for PCM.  This is the size of the
                               rest of the Subchunk which follows this number.
20        2     AudioFormat    PCM = 1 (i.e. Linear quantization)
                               Values other than 1 indicate some 
                               form of compression.
22        2     NumChannels    Mono = 1, Stereo = 2, etc.
24        4     SampleRate     8000, 44100, etc.
28        4     ByteRate       == SampleRate * NumChannels * BitsPerSample/8
32        2     BlockAlign     == NumChannels * BitsPerSample/8
                               The number of bytes for one sample including
                               all channels. I wonder what happens when
                               this number isn't an integer?
34        2     BitsPerSample  8 bits = 8, 16 bits = 16, etc.
          2     ExtraParamSize if PCM, then doesn't exist
          X     ExtraParams    space for extra parameters

36        4     Subchunk2ID    Contains the letters "data"
                               (0x64617461 big-endian form).
40        4     Subchunk2Size  == NumSamples * NumChannels * BitsPerSample/8
                               This is the number of bytes in the data.
                               You can also think of this as the size
                               of the read of the subchunk following this 
                               number.

在此之后您写入 PCM 数据。

(Reference).

【讨论】:

怎么解决,不知道怎么解决。你能帮助我吗?非常感谢:) 你写了所有在标题中指定的字段。首先是字符串RIFF,然后是包含36+size_of_your_audio_data 的32 位值,然后是字符串WAVE,以此类推。 非常感谢。我取得了喜忧参半的成功。但是mixed.wav文件有噪音。如何修复它,消除白噪声。我该如何处理我的 wav 字节数组。你能帮帮我吗? 您应该在标题之后立即写入 PCM 数据。您可以通过将 PCM 数据转储到没有任何标题的文件中,然后将其作为原始 PCM 数据导入您的 PC 上的 Audacity 来仔细检查您的 PCM 数据是否正常。 在我切换到 short[] 之后,它的效果非常糟糕 :( 我不知道我错在哪里了。

以上是关于在android中混合音频的主要内容,如果未能解决你的问题,请参考以下文章

Android硬编码——音频编码视频编码及音视频混合

Android:如何混合 2 个音频文件并使用 soundPool 重现它们

使用 HTML5 音频的无线电流混合 Android 应用程序的巨大延迟

Android/iOS:通过流混合改善实时流媒体体验

Android/iOS:通过流混合改善实时流媒体体验

Android 音频焦点管理