Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71e87bfa authored by Saketh Sathuvalli's avatar Saketh Sathuvalli Committed by Andy Hung
Browse files

libeffects: Add multichannel support to Reverb

Test: SoloTester and Clarity app
Test: Standalone application test
Bug: 129491957
Change-Id: Ifac02eb2a7ac3eba5fae9318c3ae1e1c7df4f681
parent 579a5284
Loading
Loading
Loading
Loading
+43 −25
Original line number Diff line number Diff line
@@ -41,22 +41,30 @@ fs_arr=(
    192000
)

flags_arr=(
    "--M --fch 1"
    "--fch 2"
)

# run reverb at different configs, saving only the stereo channel
# pair.
error_count=0
testcase_count=0
for cmd in "${cmds[@]}"
do
    $cmd
    for flags in "${flags_arr[@]}"
    do
        for preset_val in {0..6}
        do
            for fs in ${fs_arr[*]}
            do
            for chMask in {1..22}
                for chMask in {0..22}
                do
                    adb shell LD_LIBRARY_PATH=/system/vendor/lib/soundfx $testdir/reverb_test \
                        --input $testdir/sinesweepraw.raw \
                        --output $testdir/sinesweep_$((chMask))_$((fs)).raw \
                    --chMask $chMask --fs $fs --preset $preset_val
                        --chMask $chMask $flags --fs $fs --preset $preset_val

                    shell_ret=$?
                    if [ $shell_ret -ne 0 ]; then
@@ -64,24 +72,34 @@ do
                        ((++error_count))
                    fi

                    if [[ "$chMask" -gt 0 ]] && [[ $flags != *"--fch 2"* ]]
                    then
                        # single channel files should be identical to higher channel
                        # computation (first channel).
                        adb shell cmp $testdir/sinesweep_0_$((fs)).raw \
                            $testdir/sinesweep_$((chMask))_$((fs)).raw
                    elif [[ "$chMask" -gt 1 ]]
                    then
                        # two channel files should be identical to higher channel
                        # computation (first 2 channels).
                if [[ "$chMask" -gt 1 ]]
                then
                        adb shell cmp $testdir/sinesweep_1_$((fs)).raw \
                            $testdir/sinesweep_$((chMask))_$((fs)).raw
                    fi

                    # cmp returns EXIT_FAILURE on mismatch.
                    shell_ret=$?
                    if [ $shell_ret -ne 0 ]; then
                        echo "error: $shell_ret"
                        ((++error_count))
                    fi
                    ((++testcase_count))
                done
            done
        done
    done
done

adb shell rm -r $testdir
echo "$testcase_count tests performed"
echo "$error_count errors"
exit $error_count
+10 −7
Original line number Diff line number Diff line
@@ -297,6 +297,9 @@ int main(int argc, const char *argv[]) {
  config.inputCfg.samplingRate = config.outputCfg.samplingRate = revConfigParams.sampleRate;
  config.inputCfg.channels = config.outputCfg.channels = revConfigParams.chMask;
  config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
  if (AUDIO_CHANNEL_OUT_MONO == revConfigParams.chMask) {
    config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
  }
  if (int status =
          reverbCreateEffect(&effectHandle, &config, sessionId, ioId, revConfigParams.auxiliary);
      status != 0) {
@@ -332,15 +335,15 @@ int main(int argc, const char *argv[]) {
   * Mono input will be converted to 2 channels internally in the process call
   * by copying the same data into the second channel.
   * Hence when channelCount is 1, output buffer should be allocated for
   * 2 channels. The memAllocChCount takes care of allocation of sufficient
   * 2 channels. The outChannelCount takes care of allocation of sufficient
   * memory for the output buffer.
   */
  const int memAllocChCount = (channelCount == 1 ? 2 : channelCount);
  const int outChannelCount = (channelCount == 1 ? 2 : channelCount);

  std::vector<short> in(frameLength * maxChannelCount);
  std::vector<short> out(frameLength * maxChannelCount);
  std::vector<float> floatIn(frameLength * channelCount);
  std::vector<float> floatOut(frameLength * memAllocChCount);
  std::vector<float> floatOut(frameLength * outChannelCount);

  int frameCounter = 0;

@@ -374,11 +377,11 @@ int main(int argc, const char *argv[]) {
#else
    memcpy(floatOut.data(), floatIn.data(), frameLength * frameSize);
#endif
    memcpy_to_i16_from_float(out.data(), floatOut.data(), frameLength * channelCount);
    memcpy_to_i16_from_float(out.data(), floatOut.data(), frameLength * outChannelCount);

    if (ioChannelCount != channelCount) {
      adjust_channels(out.data(), channelCount, out.data(), ioChannelCount, sizeof(short),
                      frameLength * channelCount * sizeof(short));
    if (ioChannelCount != outChannelCount) {
      adjust_channels(out.data(), outChannelCount, out.data(), ioChannelCount, sizeof(short),
                      frameLength * outChannelCount * sizeof(short));
    }
    (void)fwrite(out.data(), ioFrameSize, frameLength, outputFp.get());
    frameCounter += frameLength;
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ cc_library_shared {

    cppflags: [
        "-fvisibility=hidden",
        "-DSUPPORT_MC",

        "-Wall",
        "-Werror",
+88 −2
Original line number Diff line number Diff line
@@ -259,6 +259,9 @@ extern "C" int EffectCreate(const effect_uuid_t *uuid,

    int channels = audio_channel_count_from_out_mask(pContext->config.inputCfg.channels);

#ifdef SUPPORT_MC
    channels = (pContext->auxiliary == true)? channels : FCC_2;
#endif
    // Allocate memory for reverb process (*2 is for STEREO)
    pContext->bufferSizeIn = LVREV_MAX_FRAME_SIZE * sizeof(process_buffer_t) * channels;
    pContext->bufferSizeOut = LVREV_MAX_FRAME_SIZE * sizeof(process_buffer_t) * FCC_2;
@@ -343,11 +346,18 @@ int process( effect_buffer_t *pIn,
    int channels = audio_channel_count_from_out_mask(pContext->config.inputCfg.channels);
    LVREV_ReturnStatus_en   LvmStatus = LVREV_SUCCESS;              /* Function call status */

    // Check that the input is either mono or stereo
    // Reverb only effects the stereo channels in multichannel source.
#ifdef SUPPORT_MC
    if (channels < 1 || channels > LVM_MAX_CHANNELS) {
        ALOGE("\tLVREV_ERROR : process invalid PCM channels %d", channels);
        return -EINVAL;
    }
#else
    if (!(channels == 1 || channels == FCC_2) ) {
        ALOGE("\tLVREV_ERROR : process invalid PCM format");
        return -EINVAL;
    }
#endif

    size_t inSize = frameCount * sizeof(process_buffer_t) * channels;
    size_t outSize = frameCount * sizeof(process_buffer_t) * FCC_2;
@@ -381,11 +391,27 @@ int process( effect_buffer_t *pIn,
                "pIn and InFrames must be same type");
        memcpy(pContext->InFrames, pIn, frameCount * channels * sizeof(*pIn));
    } else {
        // insert reverb input is always stereo
        // mono input is duplicated
#ifdef SUPPORT_MC
        if (channels >= FCC_2) {
            for (int i = 0; i < frameCount; i++) {
                pContext->InFrames[FCC_2 * i] =
                            (process_buffer_t)pIn[channels * i] * REVERB_SEND_LEVEL;
                pContext->InFrames[FCC_2 * i + 1] =
                            (process_buffer_t)pIn[channels * i + 1] * REVERB_SEND_LEVEL;
            }
        } else {
            for (int i = 0; i < frameCount; i++) {
                pContext->InFrames[FCC_2 * i] = pContext->InFrames[FCC_2 * i + 1] =
                            (process_buffer_t)pIn[i] * REVERB_SEND_LEVEL;
            }
        }
#else
        for (int i = 0; i < frameCount; i++) {
            pContext->InFrames[2 * i] = (process_buffer_t)pIn[2 * i] * REVERB_SEND_LEVEL;
            pContext->InFrames[2 * i + 1] = (process_buffer_t)pIn[2 * i + 1] * REVERB_SEND_LEVEL;
        }
#endif
    }

    if (pContext->preset && pContext->curPreset == REVERB_PRESET_NONE) {
@@ -412,10 +438,26 @@ int process( effect_buffer_t *pIn,
    if (pContext->auxiliary) {
        // nothing to do here
    } else {
#ifdef SUPPORT_MC
        if (channels >= FCC_2) {
            for (int i = 0; i < frameCount; i++) {
                // Mix with dry input
                pContext->OutFrames[FCC_2 * i] += pIn[channels * i];
                pContext->OutFrames[FCC_2 * i + 1] += pIn[channels * i + 1];
            }
        } else {
            for (int i = 0; i < frameCount; i++) {
                // Mix with dry input
                pContext->OutFrames[FCC_2 * i] += pIn[i];
                pContext->OutFrames[FCC_2 * i + 1] += pIn[i];
            }
        }
#else
        for (int i = 0; i < frameCount * FCC_2; i++) { // always stereo here
            // Mix with dry input
            pContext->OutFrames[i] += pIn[i];
        }
#endif
        // apply volume with ramp if needed
        if ((pContext->leftVolume != pContext->prevLeftVolume ||
                pContext->rightVolume != pContext->prevRightVolume) &&
@@ -450,6 +492,35 @@ int process( effect_buffer_t *pIn,
        }
    }

#ifdef SUPPORT_MC
    if (channels > 2) {
        //Accumulate if required
        if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
            for (int i = 0; i < frameCount; i++) {
                pOut[channels * i] += pContext->OutFrames[FCC_2 * i];
                pOut[channels * i + 1] += pContext->OutFrames[FCC_2 * i + 1];
            }
        } else {
            for (int i = 0; i < frameCount; i++) {
                pOut[channels * i] = pContext->OutFrames[FCC_2 * i];
                pOut[channels * i + 1] = pContext->OutFrames[FCC_2 * i + 1];
            }
        }
        for (int i = 0; i < frameCount; i++) {
            for (int j = FCC_2; j < channels; j++) {
                pOut[channels * i + j] = pIn[channels * i + j];
            }
        }
    } else {
        if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
            for (int i = 0; i < frameCount * FCC_2; i++) {
                pOut[i] += pContext->OutFrames[i];
            }
        } else {
            memcpy(pOut, pContext->OutFrames, frameCount * sizeof(*pOut) * FCC_2);
        }
    }
#else

    // Accumulate if required
    if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
@@ -462,6 +533,7 @@ int process( effect_buffer_t *pIn,
        memcpy(pOut, pContext->OutFrames, frameCount * sizeof(*pOut) * FCC_2);
    }

#endif
    return 0;
}    /* end process */

@@ -525,9 +597,18 @@ int Reverb_setConfig(ReverbContext *pContext, effect_config_t *pConfig){

    CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
    CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
#ifdef SUPPORT_MC
    int inputChannels = audio_channel_count_from_out_mask(pConfig->inputCfg.channels);
    CHECK_ARG((pContext->auxiliary && pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
              ((!pContext->auxiliary) &&
              (inputChannels <= LVM_MAX_CHANNELS)));
    int outputChannels = audio_channel_count_from_out_mask(pConfig->outputCfg.channels);
    CHECK_ARG(outputChannels >= FCC_2 && outputChannels <= LVM_MAX_CHANNELS);
#else
    CHECK_ARG((pContext->auxiliary && pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
              ((!pContext->auxiliary) && pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO));
    CHECK_ARG(pConfig->outputCfg.channels == AUDIO_CHANNEL_OUT_STEREO);
#endif
    CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
              || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
    CHECK_ARG(pConfig->inputCfg.format == EFFECT_BUFFER_FORMAT);
@@ -749,6 +830,11 @@ int Reverb_init(ReverbContext *pContext){
        params.SourceFormat   = LVM_STEREO;
    }

#ifdef SUPPORT_MC
    if ((pContext->auxiliary == false) && (params.SourceFormat == LVM_MONO)) {
        params.SourceFormat   = LVM_STEREO;
    }
#endif
    /* Reverb parameters */
    params.Level          = 0;
    params.LPF            = 23999;