Формат данных 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 канал, 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: Я не могу читать данные из звука FMOD в формате PCMFLOAT!


person David Menard    schedule 16.08.2013    source источник


Ответы (1)


Из службы поддержки Fmod: Форумы Fmod Указанный вывод формат не имеет значения. Кодек FMod всегда возвращает PCM16, а кодек iOS возвращает PCMFloats. Итак, мне нужно их преобразовать:

(float)pcm16in[j] / 32768.0f;

В дополнение к этому я (случайно) инициализировал выходной поток файлом MP3, что сделало его так, что я не мог изменить выходной формат.

person David Menard    schedule 20.08.2013