Я работаю над iOS-приложением, которое использует AVAudioEngine для различных вещей, включая запись звука в файл, применение эффектов к этому звуку с использованием аудиоустройств и воспроизведение звука с применением эффекта. Я использую кран, чтобы также записать вывод в файл. Когда это будет сделано, он записывает файл в режиме реального времени, когда звук воспроизводится.
Можно ли настроить график AVAudioEngine, который читает из файла, обрабатывает звук с помощью аудиоустройства и выводит его в файл, но быстрее, чем в реальном времени (т.е. так быстро, как аппаратное обеспечение может его обрабатывать)? Предпосылкой для этого было бы вывести несколько минут звука с примененными эффектами, и я, конечно, не хотел бы ждать несколько минут для его обработки.
Изменить: здесь код, который я использую, чтобы настроить график AVAudioEngine и воспроизвести звуковой файл:
AVAudioEngine* engine = [[AVAudioEngine alloc] init];
AVAudioPlayerNode* player = [[AVAudioPlayerNode alloc] init];
[engine attachNode:player];
self.player = player;
self.engine = engine;
if (!self.distortionEffect) {
self.distortionEffect = [[AVAudioUnitDistortion alloc] init];
[self.engine attachNode:self.distortionEffect];
[self.engine connect:self.player to:self.distortionEffect format:[self.distortionEffect outputFormatForBus:0]];
AVAudioMixerNode* mixer = [self.engine mainMixerNode];
[self.engine connect:self.distortionEffect to:mixer format:[mixer outputFormatForBus:0]];
}
[self.distortionEffect loadFactoryPreset:AVAudioUnitDistortionPresetDrumsBitBrush];
NSError* error;
if (![self.engine startAndReturnError:&error]) {
NSLog(@"error: %@", error);
} else {
NSURL* fileURL = [[NSBundle mainBundle] URLForResource:@"test2" withExtension:@"mp3"];
AVAudioFile* file = [[AVAudioFile alloc] initForReading:fileURL error:&error];
if (error) {
NSLog(@"error: %@", error);
} else {
[self.player scheduleFile:file atTime:nil completionHandler:nil];
[self.player play];
}
}
Приведенный выше код воспроизводит звук в файле test2.mp3 с установленным префиксом AVAudioUnitDistortionPresetDrumsBitBrush
, установленным в реальном времени.
Затем я модифицировал приведенный выше код, добавив эти строки после [self.player play]:
[self.engine stop];
[self renderAudioAndWriteToFile];
Я изменил метод renderAudioAndWriteToFile, который предоставил Владимир, чтобы вместо того, чтобы выделять новый AVAudioEngine в первой строке, он просто использует self.engine, который уже настроен.
Однако в renderAudioAndWriteToFile он регистрирует "Невозможно отобразить звуковую единицу", потому что AudioUnitRender возвращает статус kAudioUnitErr_Uninitialized
.
Изменить 2. Я должен упомянуть, что я абсолютно счастлив преобразовать код AVAudioEngine, который я опубликовал, чтобы использовать C apis, если это упростит ситуацию. Однако я хотел бы, чтобы код выдавал тот же результат, что и код AVAudioEngine (включая использование пресета factory, показанного выше).