我正在写一个Unity3D插件,它从MP3文件读取数据,将PCM数据提供给Unity,以便它可以在引擎内播放它。在iOS上,我使用AVAssetReaderAudioMixOutput类来解码和读取数据,而在Android/Windows上,我使用FMOD。 我已经在Windows和iOS上设置了一个使用FMOD播放音乐的程序,就像Unity3D一样。 我无法在iOS和Windows上获得相同的结果,我似乎无法找到会导致差异的音频输出设置/格式的差异。PCM数据格式与fmod - 在多个平台上的差异
因此,首先,这些是我为输出音频数据流设置它们是相同的设置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个通道,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个通道,以便所有内容都与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通道,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声音读取数据!