Android,C ++:如何使用双簧管的重采样器转换音频采样率

问题描述

我正在使用双簧管在Android上播放声音文件。我想同时播放44.1kHz和48kHz的文件,因此需要重新采样。

解码和播放文件效果很好,但是由于我有两个不同的采样率,因此我需要重新采样(由于音频流为48kHz,我目前正在尝试44.1至48。)

因此,我尝试使用oboe's resampler进行重采样,但是我无法完全理解该怎么做。按照自述文件指南转换固定数量的输入帧(我认为这是我必须做的吗?),我尝试实现如下。代码的第一部分获取解码并在采样率相等时返回(这部分按预期工作),第二部分是在必要时我尝试重新采样的地方:

StorageDataSource *StorageDataSource::newFromStorageAsset(AMediaExtractor &extractor,const char *fileName,AudioProperties targetProperties) {

    std::ifstream stream;
    stream.open(fileName,std::ifstream::in | std::ifstream::binary);
    stream.seekg(0,std::ios::end);
    long size = stream.tellg();
    stream.close();

    constexpr int kMaxCompressionRatio{12};
    const long maximumDataSizeInBytes =
            kMaxCompressionRatio * (size) * sizeof(int16_t);
    auto decodedData = new uint8_t[maximumDataSizeInBytes];

    int32_t rate = NDKExtractor::getSampleRate(extractor);
    int32_t *inputSampleRate = &rate;

    int64_t bytesDecoded = NDKExtractor::decode(extractor,decodedData,targetProperties);
    auto numSamples = bytesDecoded / sizeof(int16_t);

    auto outputBuffer = std::make_unique<float[]>(numSamples);

    // The NDK decoder can only decode to int16,we need to convert to floats
    oboe::convertPcm16ToFloat(
            reinterpret_cast<int16_t *>(decodedData),outputBuffer.get(),bytesDecoded / sizeof(int16_t));

 if (*inputSampleRate == targetProperties.sampleRate) {
        return new StorageDataSource(std::move(outputBuffer),numSamples,targetProperties);
    } else {

        // this is where I try to convert the sample rate

        float *inputBuffer;
        inputBuffer = reinterpret_cast<float *>(decodedData); // is this correct?

        float *outputBuffer2;    // multi-channel buffer to be filled,Todo improve name
        int numInputFrames;  // number of frames of input

        // Todo is this correct?
        numInputFrames = numSamples / 2;

        int numOutputFrames = 0;
        int channelCount = 2;  

        resampler::MultiChannelResampler *mResampler = resampler::MultiChannelResampler::make(
                2,// channel count
                44100,// input sampleRate
                48000,// output sampleRate
                resampler::MultiChannelResampler::Quality::Best); // conversion quality

        int inputFramesLeft = numInputFrames;

        while (inputFramesLeft > 0) {

            if (mResampler->isWriteNeeded()) {
                mResampler->writeNextFrame(inputBuffer);
                inputBuffer += channelCount;
                inputFramesLeft--;
            } else {
                mResampler->readNextFrame(outputBuffer2);
                outputBuffer2 += channelCount;
                numOutputFrames++;
            }
        }
        delete mResampler;

// return is missing!
    }

// returning the original data since above code doesn't work properly yet
 return new StorageDataSource(std::move(outputBuffer),targetProperties);
}

重新采样会因SIGSEV而崩溃:

A: signal 11 (SIGSEGV),code 1 (SEGV_MAPERR),fault addr 0x7fe69c7000
A:     x0  0000007c0e3d1e00  x1  0000007fe69c7000  x2  0000007bb77dd198  x3  0000007bf5432140
A:     x4  0000000000000021  x5  8080800000000000  x6  fefeff7b976e0667  x7  7f7f7f7fff7f7f7f
A:     x8  0000000000000660  x9  0000000000000660  x10 0000000000000000  x11 0000007bf5435840
A:     x12 0000007bb77dd118  x13 0000000000000008  x14 0000007bf54321c0  x15 0000000000000008
A:     x16 0000007bf5432200  x17 0000000000000000  x18 0000007fe69bf7ba  x19 0000007c14e14c00
A:     x20 0000000000000000  x21 0000007c14e14c00  x22 0000007fe69c0d70  x23 0000007bfc6e5dc7
A:     x24 0000000000000008  x25 0000007c9b7705f8  x26 0000007c14e14ca0  x27 0000000000000002
A:     x28 0000007fe69c0aa0  x29 0000007fe69c0420
A:     sp  0000007fe69c0400  lr  0000007bf94f61f0  pc  0000007bf9501b5c
A: backtrace:
A:     #00 pc 0000000000078b5c  /data/app/myapp-G-GmPWmPgOGfffk-qHsQxw==/lib/arm64/libnative-lib.so (resampler::polyphaseResamplerStereo::readFrame(float*)+684)
A:     #01 pc 000000000006d1ec  /data/app/myapp-G-GmPWmPgOGfffk-qHsQxw==/lib/arm64/libnative-lib.so (resampler::MultiChannelResampler::readNextFrame(float*)+44)
A:     #02 pc 000000000006c84c  /data/app/myapp-G-GmPWmPgOGfffk-qHsQxw==/lib/arm64/libnative-lib.so (StorageDataSource::newFromStorageAsset(AMediaExtractor&,char const*,AudioProperties)+1316)
A:     #03 pc 78bbcdd7f9b20dbe  <unkNown>

这是我的主要问题: 首先,如何正确获取输入的帧数?帧如何正确处理音频数据?我确实对此进行了研究,但仍不确定是否能得到这个?这是一个常数吗?如何计算帧数。它与样本,采样率和比特率有什么关系?

第二,我是否完全使用了正确的输入数据?我使用我的decodedData值,因为那是我从解码器取回的值,只是将其reinterpret_cast返回到float*

由于我对C ++相当缺乏经验,所以我不确定自己所做的是否正确,并且我可能会在这代码中引入多个错误

编辑:由于我正在尝试对解码后的输出进行重新采样,因此我假设来自here的有关PCM的这一信息在这里解释了帧的含义:

For encodings like PCM,a frame consists of the set of samples for all channels at a given point in time,and so the size of a frame (in bytes) is always equal to the size of a sample (in bytes) times the number of channels.

我的情况是否正确?那意味着我可以从采样数,音频位的长度和通道数中减去帧数吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)