audio - 带有 fmod 的 PCM 数据格式 - 多个平台上的差异

标签 audio audio-streaming pcm fmod

我正在编写一个 Unity3D 插件,它从 MP3 文件中读取数据,将 PCM 数据提供给 Unity,以便它可以在引擎内播放。在 iOS 上,我使用 AVAssetReaderAudioMixOutput 类来解码和读取数据,在 Android/Windows 上,我使用 FMOD。
我在 Windows 和 iOS 上都设置了一个程序,它使用 FMOD 播放音乐,就像 Unity3D 一样。
我无法在 iOS 和 Windows 上获得相同的结果,而且我似乎找不到会导致差异的音频输出设置/格式的差异。

首先,这些是我为输出音频流设置的设置,与 Unity3D 使用的设置相同:

FMOD_CREATESOUNDEXINFO   exinfo2;
memset(&exinfo2, 0, sizeof(FMOD_CREATESOUNDEXINFO));
exinfo2.cbsize            = sizeof(FMOD_CREATESOUNDEXINFO);             
exinfo2.decodebuffersize  = 44100;                                  
exinfo2.length            = 44100 * 1 * sizeof(float) * 100;            
exinfo2.numchannels       = 1;                                          
exinfo2.defaultfrequency  = 44100;                                  
exinfo2.format            = FMOD_SOUND_FORMAT_PCMFLOAT;         
exinfo2.pcmreadcallback   = pcmreadcallback;                          
result = system_->createStream("./1.mp3", FMOD_LOOP_NORMAL | FMOD_SOFTWARE | FMOD_OPENUSER | FMOD_CREATESTREAM, &exinfo2, &sound2_);
ERRCHECK(result);
result = system_->playSound(FMOD_CHANNEL_FREE,sound2_,false,0);

基本上,1 channel ,32 位浮点 PCM 数据。这是在 iOS 和 Windows 播放程序上设置的。
现在,在 iOS 上,我像这样设置 AVAssetReaderAudioMixOutput 音频设置:
NSDictionary *audioSetting = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithFloat:44100.0],AVSampleRateKey,
                                  [NSNumber numberWithInt:1],AVNumberOfChannelsKey,    //how many channels has original?
                                  [NSNumber numberWithInt:32],AVLinearPCMBitDepthKey, //was 16
                                  [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
                                  [NSNumber numberWithBool:YES], AVLinearPCMIsFloatKey,  //was NO
                                  [NSNumber numberWithBool:0], AVLinearPCMIsBigEndianKey,
                                  [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
                                  [NSData data], AVChannelLayoutKey, nil];

我将 PCMIsFloatKey 设置为 1,以便 PCM 数据是浮点数,我将位深度设置为 32、1 channel ,以便所有内容都与 FMOD 输出设置匹配。

我读取数据并将其写入循环缓冲区:
        float* convertedBuffer = (float * ) audioBufferList.mBuffers[0].mData;
        //We don't need the audioconverter on iOS
        //Fill up the circular buffer
        for(int i = 0; i < numSamples; i++)
        {
            circularAudioBuffer_[bufferWritePosition_] = convertedBuffer[i];
            bufferWritePosition_++;
            if(bufferWritePosition_ >= circularBufferSize_)
                bufferWritePosition_ = 0;

        }

然后从缓冲区中读取数据,并在 pcmreadcallback 中将其写入音频流中:
float *writeBuffer = (float *)data;
for(int i = 0; i < dataLength; i++)
{
    sampleBuffer[i] = circularAudioBuffer_[bufferReadPosition_];
    bufferReadPosition_++;
    if(bufferReadPosition_ >= circularBufferSize_)
        bufferReadPosition_ = 0;
}

这样,音频播放完美,循环缓冲区内的值范围为 0.0-1.0f

现在,在 Windows 上,我初始化读取数据的声音,如下所示:
exinfo.cbsize            = sizeof(FMOD_CREATESOUNDEXINFO);             
exinfo.decodebuffersize  = 44100;
exinfo.numchannels       = 1;
exinfo.defaultfrequency  = 44100;            
exinfo.format            = FMOD_SOUND_FORMAT_PCMFLOAT;  

设置相同的参数:1 channel ,32位浮点。我读取数据并将数据写入缓冲区:
    FMOD_RESULT result = sound_->readData(rawBuffer, N4, &bytesRead);

    float* floatBuffer = (float*) rawBuffer;
    for(int j = 0; j < N; j++)
    {
        circularAudioBuffer_[bufferWritePosition_++] = floatBuffer[j];
        if(bufferWritePosition_ >= circularBufferSize_)
            bufferWritePosition_ = 0;
    }

现在,当我读取数据时,我会得到非常高或非常低的浮点值(大约 1e34 或 -1e33)。在测试程序中,我听不到输出中的任何内容。

我可以将输入和输出声音格式切换为 PCM32,它在测试程序中播放良好,但在 Unity3D 中无法正确读取(它很刺耳,但我可以听出歌曲)。

谁能帮我解决这个问题并使用 PCMFLOAT 格式使其正常工作?谢谢!

TL;DR:我无法从 PCMFLOAT 格式的 FMOD 声音中读取数据!

最佳答案

来自 Fmod 支持:Fmod Forums
指定的输出格式无关紧要。 FMod 编解码器将始终返回 PCM16,而 iOS 编解码器将返回 PCMFloats。所以,我需要转换它们:

(float)pcm16in[j] / 32768.0f;

除此之外,我(意外地)使用 MP3 文件初始化输出流,这使得我无法更改输出格式。

关于audio - 带有 fmod 的 PCM 数据格式 - 多个平台上的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18281856/

相关文章:

用于创建音频 CD 磁盘镜像的 Java 库

javascript - 如何发送 AJAX POST 请求并在响应中播放音频?

c - RTP 丢包问题(?)

c++ - 音频数据?我需要一个典型的例子

android - 音轨:为原始pcm 16bit WAV文件播放噪音

iOS音频系统。开始&停止还是只是开始?

javascript - 引用错误 : AudioContext not defined

javascript - 如何在 javascript 中的音频 blob 上设置编解码器、采样率和比特率?

java - 使用 JLayer 将 MP3 解码为 PCM 来检测幅度

c - 使用 add + shift 将 pcm16 转换为 pcm14