2015-04-07 3 views
0

Я хочу отсканировать файл midi в автономном режиме, и, поскольку пример PlaySequence делает именно это, я пытаюсь это понять.
Я все время читаю, что вам нужна функция обратного вызова, чтобы что-то делать в CoreAudio, но я не вижу в этом проекте ничего.
Я вставляю петлю, содержащую AudioUnitRender, спасибо за вашу помощь!Где функция обратного вызова в проекте PlaySequence от Apple?

CAStreamBasicDescription clientFormat = CAStreamBasicDescription(); 
    size = sizeof(clientFormat); 
    FailIf ((result = AudioUnitGetProperty (outputUnit, 
               kAudioUnitProperty_StreamFormat, 
               kAudioUnitScope_Output, 0, 
               &clientFormat, &size)), fail, "AudioUnitGetProperty: kAudioUnitProperty_StreamFormat"); 
    size = sizeof(clientFormat); 
    FailIf ((result = ExtAudioFileSetProperty(outfile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat)), fail, "ExtAudioFileSetProperty: kExtAudioFileProperty_ClientDataFormat"); 

    { 
     MusicTimeStamp currentTime; 
     AUOutputBL outputBuffer (clientFormat, numFrames); 
     AudioTimeStamp tStamp; 
     memset (&tStamp, 0, sizeof(AudioTimeStamp)); 
     tStamp.mFlags = kAudioTimeStampSampleTimeValid; 
     int i = 0; 
     int numTimesFor10Secs = (int)(10./(numFrames/srate)); 
     do { 
      outputBuffer.Prepare(); 
      AudioUnitRenderActionFlags actionFlags = 0; 
      FailIf ((result = AudioUnitRender (outputUnit, &actionFlags, &tStamp, 0, numFrames, outputBuffer.ABL())), fail, "AudioUnitRender"); 

      tStamp.mSampleTime += numFrames; 

      FailIf ((result = ExtAudioFileWrite(outfile, numFrames, outputBuffer.ABL())), fail, "ExtAudioFileWrite"); 

      FailIf ((result = MusicPlayerGetTime (player, &currentTime)), fail, "MusicPlayerGetTime"); 
      if (shouldPrint && (++i % numTimesFor10Secs == 0)) 
       printf ("current time: %6.2f beats\n", currentTime); 
     } while (currentTime < sequenceLength); 
    } 

ответ

1

Я взглянул на проект, и вы правы, у него нет rendercallback. Обратные вызовы Render имеют свое место с coreaudio audiounit effect processing. Вызов настройки рендер обратный вызова выглядит следующим образом:

inline OSStatus  SetInputCallback (CAAudioUnit &inUnit, AURenderCallbackStruct &inInputCallback) 
{ 
    return inUnit.SetProperty (kAudioUnitProperty_SetRenderCallback, 
              kAudioUnitScope_Input, 
              0, 
              &inInputCallback, 
              sizeof(inInputCallback)); 
} 

Однако этот код только один большой main() который расстановки вверх последовательность, augraph, музыкальный плеер, а затем FileWriter WriteOutputFile в случае есть более выходной_файл подпрыгивать на.

Я рекомендую вам установить некоторые точки останова по ключевым методам, пройти через код, посмотреть, что он делает и посмотреть на переменные.

EDIT: Обратите внимание, что в настройке rendercallback на прошивке на ваш RemoteIO (который удваивает в качестве входных & выходных блоков), получая правильный формат поток на правильном охват & номерах шины элементов в вашем SetProperty вызовов может быть сложно. Обратитесь к этому из документов Apple.

enter image description here

+0

Thanks ruoho. Я действительно делаю более радикальный «анализ» с этим кодом, поскольку я переношу его на iPhone и Swift. Я успешно настроил график (я могу слушать воспроизведение MIDI-файла), но у меня все еще есть проблемы, когда дело доходит до подталкивания файла MIDI в аудиофайл. Все кажется прекрасным, но цикл не способен извлекать данные: MusicTimeStamp всегда 0.0 – popisar

+0

Хорошо, этот код захватывает выходной блок (kAudioUnitType_Output) AUGraph, а вызов рендеринга записывает образцы в буфер, который записывается на диск , На iOS RemoteIO является вашим «модулем вывода», rendercall обратно на RemoteIO (обратите внимание, правильная шина = 0) даст вам образцы, которые вы можете записать на диск. Для получения дополнительной информации см. Http://stackoverflow.com/questions/8951458/how-to-write-output-of-augraph-to-a-file http://stackoverflow.com/questions/6930609/write-audio -to-disk-from-io-unit –

+0

Я уже знал первую ссылку, которую вы мне дали, но кто знает, почему, когда вы указали это, я увидел это в другом свете. Я был настолько отвлечен AudioBufferList, что не заметил, что мой ASBD был беспорядок (несколько, «get» вместо «set» ... вы называете это). Если у меня все получится, вам понадобится ОДИН ASBD, и вы должны вручную применить его к каждой части вашего графика. Нет никакого «обратного распространения»: если я назначу ASBD выходному узлу, это не будет автоматически распространяться на восходящие узлы (микшер и синтезаторы, в моем случае), правильно? – popisar