Пример кода для Android AudioTrack Mixing

У меня есть два звуковых файла PCM в папке ресурсов. Я использовал inputstream и преобразовал их в bytearray.

Затем я обработал их, нормализовав и добавив музыку1 и музыку2, и вывел в выходной массив байтов. Наконец, поместите выходной массив и передайте его в AudioTrack.

Очевидно, я ничего не слышу, и что-то не так.

 private void mixSound() throws IOException {

    InputStream in1=getResources().openRawResource(R.raw.cheerapp2);      
    InputStream in2=getResources().openRawResource(R.raw.buzzer2);

     byte[] music1 = null;
     music1= new byte[in1.available()]; 
     music1=convertStreamToByteArray(in1);
     in1.close();


     byte[] music2 = null;
     music2= new byte[in2.available()]; 
     music2=convertStreamToByteArray(in2);
     in2.close();

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

     audioTrack.play();

     for(int i=0; i < output.length; i++){

         float samplef1 = music1[i] / 128.0f;      //     2^7=128
         float samplef2 = music2[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, i);
      }   //for loop


      public static byte[] convertStreamToByteArray(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

}

person jason white    schedule 27.02.2013    source источник


Ответы (1)


Я попробовал ваш код (заменив некоторые аудиофайлы своими). Я инициализировал экземпляр AudioTrack следующим образом, надеюсь, это похоже на то, как вы это сделали:

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

И попробовал запустить. Он издавал высокий звук, который со временем становился все тише. Я проверил код, и проблема в том, что вы записываете весь массив выходных байтов в audioTrack на каждой итерации цикла в вашем методе mixSound().

линия

 audioTrack.write(output, 0, i);

необходимо вынести за пределы цикла и изменить на

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

Таким образом, вы смешиваете оба файла вместе в выходной массив байтов, а затем записываете все сразу.

Итак, код рабочего метода mixSound выглядит так:

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.track1);      
    InputStream in2=getResources().openRawResource(R.raw.track2);

    byte[] music1 = null;
    music1= new byte[in1.available()]; 
    music1=convertStreamToByteArray(in1);
    in1.close();


    byte[] music2 = null;
    music2= new byte[in2.available()]; 
    music2=convertStreamToByteArray(in2);
    in2.close();

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

    audioTrack.play();

    for(int i=0; i < output.length; i++){

        float samplef1 = music1[i] / 128.0f;      //     2^7=128
        float samplef2 = music2[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;

    }   //for loop
    audioTrack.write(output, 0, output.length);

}
person combinatorics    schedule 27.02.2013
comment
Внутри цикла for я получил ошибку ArrayIndexOutofBoundsException - person jason white; 28.02.2013
comment
Это может произойти, если ваш второй аудиофайл короче первого. Выходной массив инициализируется длиной первого аудиофайла, а цикл for повторяется по длине выходного массива. Таким образом, вы можете прочитать дальше конца второго аудиофайла. Решением будет добавление защиты в том месте, где вы читаете файл samplef2. Если я › music2.length, вы должны установить для sample2f значение 0 (вы достигли конца клипа). - person combinatorics; 28.02.2013
comment
можно ли сохранить отдельный том для отдельного InputStream? - person pratik bhiyani; 27.01.2020