2013-08-16 56 views
0

我正在写一个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声音读取数据!

回答

0

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

(float)pcm16in[j]/32768.0f; 

除了这个,我是(意外)与MP3文件,这使得它,这样我可以不改变输出格式初始化输出流。