2015-04-28 2 views
2

У меня есть скелетное аудио приложение, которое использует kAudioUnitSubType_HALOutput для воспроизведения звука через AURenderCallback. Я генерирую простой чистый тон только для того, чтобы проверить все, но тон меняет шаг заметно время от времени; иногда дрейфуя вверх или вниз, и иногда быстро меняется. Это может быть до нескольких тонов на ~ 500 Гц. Вот обратный вызов:Частотный дрейф в Core Audio на OSX

static OSStatus outputCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, 
           const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, 
           UInt32 inNumberFrames, AudioBufferList *ioData) { 

    static const float frequency = 1000; 
    static const float rate = 48000; 
    static float phase = 0; 

    SInt16 *buffer = (SInt16 *)ioData->mBuffers[0].mData; 

    for (int s = 0; s < inNumberFrames; s++) { 
     buffer[s] = (SInt16)(sinf(phase) * INT16_MAX); 
     phase += 2.0 * M_PI * frequency/rate; 
    } 

    return noErr; 

} 

Я понимаю, что аудиоустройства дрейфовать с течением времени (особенно дешевых из них, как встроенных в IO), но это много дрейфа — это непригодное для музыки. Есть идеи?

Recording http://files.danhalliday.com/stackoverflow/audio.png

+0

Вы взяли запись, изучая ее - особенно, если она зависит от буферов? По моему опыту CoreAudio вообще не дрейфует. – Volker

+0

Я добавил его выше. Три отдельных тона в первую минуту; ни один не соответствует желаемому набору 1 кГц. –

+0

, и цикл в вашем обратном вызове дает желаемые результаты - лучше всего тестировать, заполняя его волной? нет различий в выборке или подобных «простых» ошибок? – Volker

ответ

3

Вы никогда не сбросить phase, поэтому его значение будет неограниченно возрастать. Поскольку он хранится в типе с плавающей точкой, точность сохраненного значения будет ухудшаться по мере увеличения значения. Вероятно, это является причиной частотных вариаций, которые вы описываете.

Добавление следующие строки в теле цикла for() должно существенно уменьшить эту проблему:

if (phase > 2.0 * M_PI) 
    phase -= 2.0 * M_PI; 

Изменение типа phase от float к double также поможет значительно.

+0

Спасибо, это было неловко просто! –

Смежные вопросы