Как я могу смешать два аудиофайла PCM

Я сделал тестовый микс из двух аудиофайлов PCM. но не получить настоящий аудиофайл.

Я использовал этот пример Итак, мой код:

  private void mixSound() throws IOException {

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];

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

samplef1 = music1[i] / 128.0f; 
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

save = openFileOutput(filename, Context.MODE_PRIVATE);
save.write(output);
save.flush();
save.close();
}

public byte[] convertStreamToByteArray(InputStream is) throws IOException {

ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buff = new byte[8000];
int i;
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

}

2 аудиофайла с битрейтом 64000 и частотой дискретизации 16000 GH и стерео

in1 = getResources().openRawResource(R.raw.a_2);
in2 = getResources().openRawResource(R.raw.a_diz_2);

Также попробуйте преобразовать bytes array to short array -> then calculate-> then convert short to byte, используя такие методы преобразования, как bytes2Shorts(byte[] buf) и shorts2Bytes(short[] s). Но у стали провальный результат.

Кто-то может сказать мне, где я ошибаюсь?


person Serg Burlaka    schedule 18.02.2018    source источник


Ответы (1)


Здесь есть ряд проблем, и я постараюсь решить некоторые из них.

Во-первых, использование byte[] предполагает, что ваш PCM wave data format - это AudioFormat.ENCODING_PCM_8BIT (или это должен быть этот формат, если это уже не так). В этом формате используется 8-bit (1 byte) unsigned, что означает, что звуковые образцы сохраняются в диапазоне [0, 255] (а не в диапазоне [-127, +128] or [-128,+127]).

Это означает, что отрицательные значения находятся в диапазоне [0, 127], а положительные образцы — в диапазоне [128,255].

При смешивании значений лучше не допускать clipping с самого начала, поэтому я бы использовал

byte mixed = (music1[i] + music2[i])/2; //this ensures that mixed remains within the `correct range` for your PCM format

Вы также можете разделить свои образцы на 128 (если вы хотите преобразовать их в значения с плавающей запятой).

float samplef1 = (((float)music1[i]-127)/128 ; //converting samples to [-1, +1] range -- -1 corresponds a sample value of 0 and +1 to 255

float samplef2 = (((float)music2[i]-127)/128;

float mixed = (samplef1+samplef2)/2;

Обратите внимание, что теперь у вас есть 2 варианта воспроизведения данных (сэмплов), сгенерированных таким образом. Либо преобразуйте floats обратно в bytes, либо используйте формат AudioFormat.ENCODING_PCM_FLOAT.

аудиофайлы с битрейтом 64000 и частотой дискретизации 16000 GH и стерео

Это не может быть правильным. Типичная частота дискретизации составляет 4000Hz, 8000Hz, 11000Hz, 16000Hz, 22050Hz or 44100Hz. Для битовой глубины аудио обычно используется 8 bits, 16 bits or 32 bits.

Например, аудио качества CD использует формат 44100Hz, 16bit, stereo.

person dsp_user    schedule 20.02.2018
comment
Привет! Я согласен и думал сейчас то же самое. попробую, спасибо а вообще - person Serg Burlaka; 20.02.2018