Рассчитать уровень / амплитуду / дБ звука для двух каналов - PullRequest
0 голосов
/ 11 апреля 2020

Я прочитал два поста об извлечении семплов из AudioInputStream и преобразовании их в дБ.

{ ссылка }

{ ссылка }

Насколько я понимаю, byte[] bytes; имеет такую ​​структуру:

Index 0: Sample 0 (Left Channel)
Index 1: Sample 0 (Right Channel)
Index 2: Sample 1 (Left Channel)
Index 3: Sample 1 (Right Channel)
Index 4: Sample 2 (Left Channel)
Index 5: Sample 2 (Right Channel)

В первой статье показано, как получить сэмплы из одного канала (моно).

Итак, моя проблема в том, что я хочу получить выборки отдельно для правого канала и отдельно для левого канала, чтобы рассчитать дБ для правого и левого каналов.

Вот код. Как это можно изменить, чтобы получить правый и левый каналы отдельно? Я не могу понять, как меняется индекс i ...

final byte[] buffer = new byte[2048];

float[] samples = new float[buffer.length / 2];

for (int n = 0; n != -1; n = in.read(buffer, 0, buffer.length)) {
    line.write(buffer, 0, n);

    for (int i = 0, sampleIndex = 0; i < n; ) {
        int sample = 0;

        sample |= buffer[i++] & 0xFF; // (reverse these two lines
        sample |= buffer[i++] << 8;   //  if the format is big endian)

        // normalize to range of +/-1.0f
        samples[sampleIndex++] = sample / 32768f;
    }

    float rms = 0f;
    for (float sample : samples) {
        rms += sample * sample;
    }

    rms = (float) Math.sqrt(rms / samples.length);

Надеюсь, вы могли бы мне помочь. Заранее спасибо.

1 Ответ

4 голосов
/ 11 апреля 2020

Формат, в котором сохраняется стереосигнал, называется interleaved . Т.е., как вы правильно описали, это LLRRLLRRLLRR.... Поэтому сначала вам нужно прочитать левый образец, затем правый образец и т. Д.

Я отредактировал ваш код, чтобы отразить это. Однако есть некоторые возможности для улучшения с помощью рефакторинга .

Примечание: Изменения кода касаются только чередования. Я не проверял остальную часть вашего кода.

final byte[] buffer = new byte[2048];

// create two buffers. One for the left, one for the right channel.
float[] leftSamples = new float[buffer.length / 4];
float[] rightSamples = new float[buffer.length / 4];

for (int n = 0; n != -1; n = in.read(buffer, 0, buffer.length)) {
    line.write(buffer, 0, n);

    for (int i = 0, sampleIndex = 0; i < n; ) {
        int sample = 0;

        leftSample |= buffer[i++] & 0xFF; // (reverse these two lines
        leftSample |= buffer[i++] << 8;   //  if the format is big endian)

        rightSample |= buffer[i++] & 0xFF; // (reverse these two lines
        rightSample |= buffer[i++] << 8;   //  if the format is big endian)

        // normalize to range of +/-1.0f
        leftSamples[sampleIndex] = leftSample / 32768f;
        rightSamples[sampleIndex] = rightSample / 32768f;

        sampleIndex++;
    }

    // now compute RMS for left
    float leftRMS = 0f;
    for (float sample : leftSamples) {
        leftRMS += sample * sample;
    }

    leftRMS = (float) Math.sqrt(leftRMS / leftSamples.length);

    // ...and right
    float rightRMS = 0f;
    for (float sample : rightSamples) {
        rightRMS += sample * sample;
    }

    rightRMS = (float) Math.sqrt(rightRMS / rightSamples.length);
}
...