在左右扬声器上播放2个不同的音频流

时间:2015-07-29 14:51:50

标签: android audio

有些特殊情况迫使我去做那种变态的事情。

是否可以在不同的频道播放2个不同的音频流。想象一下耳机,我需要同时播放左扬声器的第一首歌和右扬声器的第二首歌。

经过一番研究后,我发现可以在某个单一频道播放。甚至可以关闭其中一个。但我没有找到任何有关如何同时播放2个音频流的信息。

甚至可能吗?如何?一些代码示例和链接赞赏!

研究结果。

1) AudioTrack能够在不同频道播放

// only play sound on left
for(int i = 0; i < count; i += 2){
    short sample = (short)(Math.sin(2 * Math.PI * i / (44100.0 / freqHz)) * 0x7FFF);
    samples[i + 0] = sample;
    samples[i + 1] = 0;
}
// only play sound on right
for(int i = 0; i < count; i += 2){
    short sample = (short)(Math.sin(2 * Math.PI * i / (44100.0 / freqHz)) * 0x7FFF);
    samples[i + 0] = 0;
    samples[i + 1] = sample;
}

2) SoundPool能够分别设置左右声道的音量。因此从技术上讲,可以启动2个流,并设置为0左侧音量,100个右侧音量,反之亦然,为第2个流。正确?

setVolume(int streamID, float leftVolume, float rightVolume)

样品:

    SoundPool pool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
pool.play(
        pool.load(this, R.raw.my_sound_effect, 1), // The sound effect to play
        0, // The volume for the left channel (0.0 - 1.0)
        1.0f, // The volume for the right channel (0.0 - 1.0)
        0, // Default priority 
        0, // Do not loop
        1.0f); // Playback rate (1.0f == normal)

Perhabs使用MediaPlayer就有这样的解决方案,这样会更好!

: 似乎最简单的解决方案是使用SoundPool。我测试它的方式。

//SDK Version
public CustomSoundPool() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        AudioAttributes attributes = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_GAME)
                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                .build();

        soundPool = new SoundPool.Builder()
                .setAudioAttributes(attributes)
                .build();
    } else {
        soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
    }
    soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
        @Override
        public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
            soundPool.play(sampleId, 1.0f, 0, 0, 0, 1.0f); //left channel
            //soundPool.play(sampleId, 0, 1.0f, 0, 0, 1.0f); //right channel
        }
    });
}

public void playSound(String path) {
    if (soundPool != null) {
        soundPool.load(path, 1);
    }
}

public void release(){
    if (soundPool != null) {
        soundPool.release();
    }
}

虽然缺少MediaPlayer.OnCompletionListener()等功能。现在确定如何实现这一点但无论如何..问题解决了。

2 个答案:

答案 0 :(得分:2)

方法1)2)应该像你说的那样工作。

关于方法1),如果你想同时播放不同的流你可以在同一个循环中用不同的数据写两个通道,而不使用两个循环。 为了设置每个频道的音量,您可以使用AudioTrack的方法setStereoVolume(float leftGain, float rightGain)

由于MediaPlayer是一个高级API,因此它没有提供这种特异性水平;解决方法可以是使用MediaPlayer将音频数据保存到文件(将左/右声道静音)并将其作为常规媒体元素播放

更新:

  

将音频数据保存到文件中(将左/右声道静音)

为此,假设您的音频数据采用AudioTrack兼容格式(PCM),您只需按照所述处理数据(通过重置部分数组使一个通道静音)然后保存数组/缓冲到文件为WAV / PCM。查看here以获取有关如何保存WAV文件的更多详细信息和代码。

答案 1 :(得分:1)

我使用了2个mediaplayer实例,并尝试在耳机上播放两个独立的音乐曲目,它的工作原理就像是一种魅力。它在左侧播放一首曲目,在右侧播放另一首曲目。

MediaPlayer mediaPlayer1 = MediaPlayer.create(this, R.raw.lenka);
MediaPlayer mediaPlayer2 = MediaPlayer.create(this, R.raw.faded);
final int sessionIdA = mediaPlayer1.getAudioSessionId();
final int sessionIdB = mediaPlayer2.getAudioSessionId();
mediaPlayer1.setLooping(true);
mediaPlayer2.setLooping(true);
mediaPlayer1.setVolume(0, 1);
mediaPlayer2.setVolume(1, 0);
mediaPlayer1.start();
mediaPlayer2.start();