Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/180.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 安卓,C++;:如何使用双簧管转换音频采样率';s重采样器_Android_C++_Audio_Resampling_Oboe - Fatal编程技术网

Android 安卓,C++;:如何使用双簧管转换音频采样率';s重采样器

Android 安卓,C++;:如何使用双簧管转换音频采样率';s重采样器,android,c++,audio,resampling,oboe,Android,C++,Audio,Resampling,Oboe,我使用双簧管在Android上播放声音文件。我有44.1kHz和48kHz的文件,我希望能够在同一音频流上播放,因此我需要重新采样 解码和播放文件很好,但由于我有两种不同的采样率,我需要重新采样(44.1到48是我目前正在尝试的,因为我的音频流是48kHz。) 因此,我试图使用重新采样,但我无法完全理解如何使用。按照自述指南转换固定数量的输入帧(我假设这是我必须做的吗?),我尝试实现如下。代码的第一部分获取解码后的数据,并在采样率相等时返回(该部分按预期工作),第二部分是我尝试在必要时重新采样的

我使用双簧管在Android上播放声音文件。我有44.1kHz和48kHz的文件,我希望能够在同一音频流上播放,因此我需要重新采样

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

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

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),
                                     numSamples,
                                     targetProperties);
}
以下是我的主要问题: 首先,如何正确获取输入的帧数?帧是如何处理音频数据的?我做了研究,但我仍然不确定我是否得到了这个?这是一个常数吗?如何计算帧数。它与采样、采样率和比特率有何关联

第二,我是否使用了正确的输入数据?我使用我的
decodedData
值,因为这是我从解码器返回的值,只是
将其重新解释为
float*

<>因为我对C++没有经验,我不确定我做的是否正确,我可能会在这段代码中引入多个错误。 编辑:由于我正在尝试对解码输出进行重采样,因此我假设以下关于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.

这对我的情况正确吗?这意味着我可以从采样数、音频位长度和频道计数中扣除帧数?

不幸的是,我不能回答所有问题,但我想尝试帮助理解帧数。“如何计算帧数”-对于PCM格式(*.wav),总帧数为“持续时间(秒)*帧速率”。假设您的音频帧速率为44100(44.1kHz),持续时间为5秒。这意味着帧数将为44100*5。这意味着,一个帧包含该文件在特定时间点的所有通道的信息,如上文所述?所以,如果我有一个PCM 44100Hz文件,并且知道它的大小,我是否也知道它的持续时间?文件大小和持续时间之间的关系如何?@michpohl你让它工作了吗?我需要类似的东西遗憾的是,没有。由于这对我来说是一个更好的选择,我最终跳过了它。不幸的是,我不能回答所有的问题,但我想试着帮助我理解框架。“如何计算帧数”-对于PCM格式(*.wav),总帧数为“持续时间(秒)*帧速率”。假设您的音频帧速率为44100(44.1kHz),持续时间为5秒。这意味着帧数将为44100*5。这意味着,一个帧包含该文件在特定时间点的所有通道的信息,如上文所述?所以,如果我有一个PCM 44100Hz文件,并且知道它的大小,我是否也知道它的持续时间?文件大小和持续时间之间的关系如何?@michpohl你让它工作了吗?我需要类似的东西遗憾的是,没有。因为这对我来说是一个更好的选择,我最终跳过了。
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.