iPhone: программно смешать два аудио файла? - PullRequest
14 голосов
/ 26 декабря 2011

Я хочу получить два аудиофайла, микшировать и воспроизводить их программно.Когда я воспроизводю первый аудиофайл, через некоторое время (динамическое время) мне нужно добавить второй небольшой аудиофайл с первым аудиофайлом, когда где-то в середине первого аудиофайла воспроизводится, и, наконец, мне нужно сохранить как один аудиофайл на устройстве.Он должен воспроизводить аудиофайл с микшером аудио, который я включил во второй.

Я прошел много форумов, но не смог понять, как именно этого добиться?

Может кто-нибудьПожалуйста, проясните мои следующие сомнения:

  1. В таком случае, какой аудиофайл / формат мне следует использовать?Могу ли я использовать файлы .avi?
  2. Как программно добавить второй звук после динамического времени, установленного для первого аудиофайла?Например: если общее время первого аудио составляет 2 минуты, мне может потребоваться смешать второй аудиофайл (аудио 3 секунды) где-то в 1 минуте, или 1,5 минуте, или 55 секундах первого файла.Его динамика.
  3. Как сохранить окончательный выходной аудиофайл на устройстве?Если я сохраню аудиофайл программным способом где-нибудь, могу ли я воспроизвести его снова?

Я не знаю, как этого добиться.Пожалуйста, предложите свои мысли!

Ответы [ 4 ]

6 голосов
/ 04 января 2012
  • Открыть каждый аудиофайл
  • Прочитать информацию заголовка
  • Загрузка необработанного несжатого звука в память в виде массива целых чисел для каждого файла
  • Начиная с точки в массиве файла 1, где вы хотите микшировать файл file2, проходите цикл, добавляя значение int файла file2 к файлу file1, обязательно «обрезая» любые значения выше или ниже максимального (именно так вы микшируете аудио. .. да, это это просто). Если file2 длиннее, вам придется сделать первый массив достаточно длинным, чтобы полностью вместить оставшуюся часть file2.
  • Записать новую информацию заголовка, а затем аудио из массива, в который вы добавили файл 2.
  • Если используется сжатие или файлы не помещаются в памяти, возможно, вам придется реализовать более сложную схему буферизации.
2 голосов
/ 11 апреля 2013

Здравствуйте. Вы можете сделать это, используя av foundation

.
- (BOOL) combineVoices1
{
    NSError *error = nil;
    BOOL ok = NO;


    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,    NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];


    CMTime nextClipStartTime = kCMTimeZero;
    //Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack.
    AVMutableComposition *composition = [[AVMutableComposition alloc] init];

    AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [compositionAudioTrack setPreferredVolume:0.8];
    NSString *soundOne  =[[NSBundle mainBundle]pathForResource:@"test1" ofType:@"caf"];
    NSURL *url = [NSURL fileURLWithPath:soundOne];
    AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
    NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
    AVAssetTrack *clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];

    AVMutableCompositionTrack *compositionAudioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [compositionAudioTrack setPreferredVolume:0.3];
    NSString *soundOne1  =[[NSBundle mainBundle]pathForResource:@"test" ofType:@"caf"];
    NSURL *url1 = [NSURL fileURLWithPath:soundOne1];
    AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil];
    NSArray *tracks1 = [avAsset1 tracksWithMediaType:AVMediaTypeAudio];
    AVAssetTrack *clipAudioTrack1 = [[avAsset1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    [compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack1 atTime:kCMTimeZero error:nil];


    AVMutableCompositionTrack *compositionAudioTrack2 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [compositionAudioTrack2 setPreferredVolume:1.0];
    NSString *soundOne2  =[[NSBundle mainBundle]pathForResource:@"song" ofType:@"caf"];
    NSURL *url2 = [NSURL fileURLWithPath:soundOne2];
    AVAsset *avAsset2 = [AVURLAsset URLAssetWithURL:url2 options:nil];
    NSArray *tracks2 = [avAsset2 tracksWithMediaType:AVMediaTypeAudio];
    AVAssetTrack *clipAudioTrack2 = [[avAsset2 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    [compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset2.duration) ofTrack:clipAudioTrack2 atTime:kCMTimeZero error:nil];



    AVAssetExportSession *exportSession = [AVAssetExportSession
                                           exportSessionWithAsset:composition
                                           presetName:AVAssetExportPresetAppleM4A];
    if (nil == exportSession) return NO;

    NSString *soundOneNew = [documentsDirectory stringByAppendingPathComponent:@"combined10.m4a"];
    //NSLog(@"Output file path - %@",soundOneNew);

    // configure export session  output with all our parameters
    exportSession.outputURL = [NSURL fileURLWithPath:soundOneNew]; // output path
    exportSession.outputFileType = AVFileTypeAppleM4A; // output file type

    // perform the export
    [exportSession exportAsynchronouslyWithCompletionHandler:^{

        if (AVAssetExportSessionStatusCompleted == exportSession.status) {
            NSLog(@"AVAssetExportSessionStatusCompleted");
        } else if (AVAssetExportSessionStatusFailed == exportSession.status) {
            // a failure may happen because of an event out of your control
            // for example, an interruption like a phone call comming in
            // make sure and handle this case appropriately
            NSLog(@"AVAssetExportSessionStatusFailed");
        } else {
            NSLog(@"Export Session Status: %d", exportSession.status);
        }
    }];


    return YES;


}
2 голосов
/ 04 января 2012

В этом случае какой аудио файл / формат мне следует использовать? Могу ли я использовать .avi файлы?

Вы можете выбрать сжатый или несжатый формат. Распространенные несжатые форматы включают Wav и AIFF. CAF может представлять сжатые и несжатые данные. .avi не вариант (предлагается ОС).

Если файлы имеют большой размер и пространство для хранения (на диске) является проблемой, вы можете рассмотреть формат AAC, сохраненный в CAF (или просто .m4a). Для большинства приложений достаточно 16-битных сэмплов, и вы также можете сэкономить место, память и процессор, сохранив эти файлы с соответствующей частотой дискретизации (см .: CD с частотой 44,1 кГц).

Поскольку интерфейс ExtAudioFile абстрагирует процесс преобразования, вам не нужно менять свою программу для сравнения различий в размерах и скорости сжатых и несжатых форматов для вашего дистрибутива (AAC в CAF подойдет для обычных приложений).

Несжатый звук качества CD будет потреблять около 5,3 МБ в минуту на канал. Таким образом, если у вас есть 2 стереофонических аудиофайла, каждый по 3 минуты, и 3-минутный буфер назначения, ваша потребность в памяти составит около 50 МБ.

Поскольку у вас есть «минуты» аудио, вам, возможно, придется избегать одновременной загрузки всех аудиоданных в память. Чтобы читать, манипулировать и комбинировать аудио, вам понадобится несжатое представление для работы в памяти, поэтому форматы сжатия здесь не помогут. Кроме того, преобразование сжатого представления в pcm требует значительного количества ресурсов; чтение сжатого файла, хотя и меньше байтов, может занять больше (или меньше) времени.

Как программно добавить второй звук после динамического времени, установленного для первого аудиофайла? Например: если общее время первого аудио составляет 2 минуты, мне может потребоваться смешать второй аудиофайл (аудио 3 секунды) где-то в 1 минуте, или 1,5 минуте, или 55 секундах первого файла. Его динамика.

Чтобы прочитать файлы и преобразовать их в формат, который вы хотите использовать, используйте API-интерфейсы ExtAudioFile - это преобразует вас в целевой формат примера для вас. Типичные представления PCM в памяти включают SInt32, SInt16 и float, но они могут сильно различаться в зависимости от приложения и аппаратного обеспечения (помимо iOS). API-интерфейсы ExtAudioFile также при необходимости будут преобразовывать сжатые форматы в PCM.

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

Чтобы добавить звуки, вы должны запросить сэмплы PCM из файлов, обработать их и записать в выходной файл (или в буфер в памяти).

Чтобы определить, когда добавлять другие звуки, вам нужно получить частоты дискретизации для входных файлов (через ExtAudioFileGetProperty). Если вы хотите записать второй звук в буфер назначения на 55 с, то вы начнете добавлять звуки с номером семпла SampleRate * 55, где SampleRate - частота семплирования файлов, которые вы читаете.

Для микширования аудио вы просто будете использовать эту форму (псевдокод):

mixed[i] = fileA[i] + fileB[i];

но вы должны быть уверены, что избегаете переполнения / переполнения и других арифметических ошибок. Как правило, вы будете выполнять этот процесс, используя некоторое целочисленное значение, потому что вычисления с плавающей запятой могут занять много времени (когда их так много). Для некоторых приложений вы можете просто перемещать и добавлять, не беспокоясь о переполнении - это эффективно уменьшит каждый ввод наполовину перед их добавлением. Амплитуда результата будет равна половине. Если у вас есть контроль над содержимым файлов (например, они все связаны как ресурсы), вы можете просто убедиться, что ни один из пиковых отсчетов в файлах не превысил половину значения полной шкалы (около -6dBFS). Конечно, сохранение в формате float решит эту проблему за счет повышения требований к процессору, памяти и файловому вводу / выводу.

На этом этапе у вас будет 2 открытых файла для чтения и один открытый для записи, затем несколько небольших временных буферов для обработки и микширования входных данных перед записью в выходной файл. Вы должны выполнять эти запросы в блоках для эффективности (например, прочитать 1024 образца из каждого файла, обработать образцы, записать 1024 образца). API не гарантируют многого в отношении кеширования и буферизации для эффективности.

Как сохранить окончательный выходной аудиофайл на устройстве? Если я сохраню аудиофайл где-нибудь программно, могу ли я воспроизвести его снова?

API ExtAudioFile подойдут для ваших нужд чтения и записи. Да, вы можете прочитать / воспроизвести его позже.

0 голосов
/ 31 декабря 2011

Если вы собираетесь проигрывать несколько звуков одновременно, обязательно используйте формат * .caf. Apple рекомендует его для воспроизведения нескольких звуков одновременно. С точки зрения их микширования программно, я предполагаю, что вы просто хотите, чтобы они играли одновременно. Пока звучит один звук, просто скажите другому, чтобы он воспроизводился в любое время. Чтобы установить конкретное время, используйте NSTimer ( NSTimer Class Reference ) и создайте метод для воспроизведения звука при срабатывании таймера.

...