Как бы вы подключили актив библиотеки iPod к службе аудио-очереди и обработали ее с помощью аудиоустройства? - PullRequest
4 голосов
/ 07 июня 2011

Мне нужно обработать звук, поступающий из библиотеки iPod.Единственный способ прочитать ресурс для библиотеки iPod - это AVAssetReader.Для обработки аудио с аудиоустройством он должен быть в стереофоническом формате, поэтому у меня есть значения для левого и правого каналов.Но когда я использую AVAssetReader для чтения ресурса из библиотеки iPod, он не позволяет мне выводить его в стереофоническом формате.Он выходит в чередующемся формате, который я не знаю, как разбить на левый и правый аудиоканалы.

Чтобы добраться туда, куда мне нужно идти, мне нужно будет выполнить одно из следующих действий:

  1. Получить AVAssetReader, чтобы дать мне AudioBufferList в стерео формате
  2. Преобразовать данные с чередованием в без чередования, чтобы получить стерео мне нужен
  3. Отправить его через Audio Queue Services, чтобы получитьМне нужна автоматическая буферизация

Кажется, я ограничен тем, что может сделать существующий публичный API и что поддерживает AVAssetReader при чтении ресурса библиотеки iPod.Чтобы ты делал?Как я могу получить то, что мне нужно для обработки с аудиоустройством?

Еще одно ограничение, которое у меня есть, заключается в том, что я не могу читать всю песню за раз, так как это приведет к заполнению памяти и падению приложения.По этой причине я хочу использовать Audio Queue Services.Если я смогу обработать ресурс из библиотеки iPod как поток в стереофоническом формате, тогда все мои требования будут учтены.

Можно ли это даже сделать?Есть ли где-нибудь документы, блоги или статьи, которые объясняли бы, как это можно сделать?

1 Ответ

3 голосов
/ 23 августа 2011

Похоже, что у вас есть пара вопросов, собранных там.

Когда вы настраиваете AVAssetReader, вы можете передать словарь настроек.Вот как я создаю свои AVAssetReaders ...

    AVAssetReader* CreateAssetReaderFromSong(AVURLAsset* songURL) {

    if([songURL.tracks count] <= 0)
        return NULL;


    AVAssetTrack* songTrack = [songURL.tracks objectAtIndex:0];

    NSDictionary* outputSettingsDict = [[NSDictionary alloc] initWithObjectsAndKeys:

                                        [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
                                        //     [NSNumber numberWithInt:AUDIO_SAMPLE_RATE],AVSampleRateKey,  /*Not Supported*/
                                        //     [NSNumber numberWithInt: 2],AVNumberOfChannelsKey,   /*Not Supported*/

                                        [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
                                        [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,
                                        [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
                                        [NSNumber numberWithBool:NO],AVLinearPCMIsNonInterleaved,

                                        nil];

    NSError* error = nil;
    AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:songURL error:&error];

    {
        AVAssetReaderTrackOutput* output = [[AVAssetReaderTrackOutput alloc] initWithTrack:songTrack outputSettings:outputSettingsDict];
        [reader addOutput:output];
        [output release];
    }

    return reader;
}

Чтобы разделить левый и правый канал, вы можете циклически перебирать данные на основе вашего AVLinearPCMBitDepthKey.

что-то вроде этого для 16 бит ...

for (j=0; j<tBufCopy; j++, pAD+=2) {            // Fill the buffers...
    mProcessingBuffer.Left[(tBlockUsed+j)] = ((sint32)pAD[0]);
    mProcessingBuffer.Right[(tBlockUsed+j)] = ((sint32)pAD[1]);
}

Теперь я предполагаю, что вам нужно это для обработки.Но иметь данные в чередующемся формате действительно очень приятно.Как правило, вы можете взять формат с прямым чередованием и передать его обратно в обратный вызов AudioQueue или Remote I / O, и он будет воспроизводиться правильно.

Для воспроизведения звука с использованием инфраструктуры AudioQueue данные должны следовать этомуflow:

AVAssetReader -> NSData Buffer -> AudioQueueBuffer

Затем в обратном вызове AudioQueue, где он запрашивает дополнительные данные, просто передайте AudioQueueBuffer.Что-то вроде ...

- (void) audioQueueCallback:(AudioQueueRef)aq  buffer:(AudioQueueBufferRef)buffer {

    memcpy(buffer->mAudioData, srcData, mBufferByteSize);
    //Setup buffer->mAudioDataSize

    //...

    AudioQueueEnqueueBuffer(mQueue, buffer, 0 /*CBR*/, 0 /*non compressed*/);
}
...