Запись аудио в NSData

Я установил TCP-соединение между двумя iPhone и могу отправлять пакеты NSData между ними. Я хотел бы поговорить в микрофон и получить запись как объект NSData и отправить ее на другой iPhone. Я успешно использовал Audio Queue Services для записи и воспроизведения звука, но мне не удалось получить запись как NSData. Я задал вопрос о преобразовании записи в NSData при использовании Audio Queue Services но дальше меня это не продвинулось.

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

Обновление:

Мне нужно отправлять пакеты непрерывно во время записи. Например. каждую секунду во время записи я буду отправлять данные, записанные в течение этой секунды.


person simonbs    schedule 13.12.2011    source источник


Ответы (3)


И Audio Queues, и RemoteIO Audio Unit предоставят вам буферы необработанного звука в режиме реального времени с довольно низкой задержкой. Вы можете взять указатель буфера и длину байта, заданную в каждом обратном вызове аудио, чтобы создать новый блок NSData. RemoteIO обеспечит наименьшую задержку, но может потребовать, чтобы обмен сетевыми сообщениями выполнялся вне потока обратного вызова.

person hotpaw2    schedule 13.12.2011
comment
Если я правильно вас понимаю, я должен иметь возможность использовать свои текущие аудиоочереди, а в моем AudioInputCallback сделать следующее? NSUInteger length = inNumberPacketDescriptions * 2; NSData *packet = [NSData dataWithBytes:inBuffer->mAudioData length:length];. Это правильно? Я умножаю на два, потому что это должно быть количество байтов в каждом из моих пакетов (это установлено в AudioStreamBasicDescription). Согласно idevhub.com/exploring-iphone-audio-part-1 EDIT: кажется, что я не могу вызвать self в своем обратном вызове. - person simonbs; 13.12.2011
comment
Позвоните себе за пределами звукового обратного вызова. Установите флаг внутри обратного вызова и опросите его извне, что self нужно вызвать с некоторыми данными. - person hotpaw2; 13.12.2011
comment
Кажется, теперь это работает. У вас случайно нет идеи, как я буду воспроизводить полученные данные, когда данные поступают непрерывно? - person simonbs; 13.12.2011
comment
Данные на самом деле не поступают по сети непрерывно. Вам нужна стратегия для борьбы с дрожанием сетевой задержки и несинхронными частотами дискретизации звука. Это два больших отдельных вопроса. - person hotpaw2; 13.12.2011
comment
Я предполагаю, что отправка пакетов NSData и добавление их в очередь для воспроизведения в таком случае не вариант. - person simonbs; 13.12.2011
comment
Это вариант, но возможны некоторые проблемы, в зависимости от размера очереди и других факторов. - person hotpaw2; 14.12.2011

Используя AVAudioRecorder следующим образом:

NSURL *filePath = //Your desired path for the file
NSDictionary *settings; //The settings for the recorded file
NSError *error = nil;
AVAudioRecorder *recorder = [[AVAudioRecorder alloc] initWithURL:filePath settings:recordSetting error:&error];
....
[recorder record];
....
[recorder stop];
....

И получить NSData из файла:

NSData *audioData = [[NSData alloc] initWithContentsOfFile:filePath];

Справочник по AVAudioRecorder, здесь.

Редактировать:

Чтобы получить фрагменты записанного звука, вы можете использовать метод subdataWithRange: в классе NSData. Сохраните смещение, из которого вы хотите получить байты. Вы можете запускать NSTimer каждую секунду, чтобы собирать байты и отправлять их. Вам нужно будет узнать, сколько байтов записывается каждую секунду.

person Fran Sevillano    schedule 13.12.2011
comment
Мне нужно отправлять пакеты непрерывно во время записи. Например. каждую секунду во время записи я буду отправлять данные, записанные в течение этой секунды. Будет ли это возможно с решением, которое вы упомянули? Извините, что я не уточнил это в своем вопросе. - person simonbs; 13.12.2011

Вот что я сделал на записывающем iphone:

void AudioInputCallback(void * inUserData,
                    AudioQueueRef inAQ,
                    AudioQueueBufferRef inBuffer,
                    const AudioTimeStamp * inStartTime,
                    UInt32 inNumberPacketDescriptions,
                    const AudioStreamPacketDescription * inPacketDescs)
{
RecordState * recordState = (RecordState*)inUserData;
if (!recordState->recording)
{
    printf("Not recording, returning\n");
}

// if (inNumberPacketDescriptions == 0 && recordState->dataFormat.mBytesPerPacket != 0)
// {
//     inNumberPacketDescriptions = inBuffer->mAudioDataByteSize / recordState->dataFormat.mBytesPerPacket;
// }

printf("Writing buffer %lld\n", recordState->currentPacket);

OSStatus status = AudioFileWritePackets(recordState->audioFile,
                                        false,
                                        inBuffer->mAudioDataByteSize,
                                        inPacketDescs,
                                        recordState->currentPacket,
                                        &inNumberPacketDescriptions,
                                        inBuffer->mAudioData);
NSLog(@"DATA = %@",[NSData dataWithBytes:inBuffer->mAudioData length:inBuffer->mAudioDataByteSize]);

[[NSNotificationCenter defaultCenter] postNotificationName:@"Recording" object:[NSData dataWithBytes:inBuffer->mAudioData length:inBuffer->mAudioDataByteSize]];

if (status == 0)
{
    recordState->currentPacket += inNumberPacketDescriptions;
}

AudioQueueEnqueueBuffer(recordState->queue, inBuffer, 0, NULL);
}

Я вызвал уведомление, которое помогает отправлять пакеты данных на другой iPhone в сети.

Но я не знаю, как читать данные на другой стороне. Я все еще пытаюсь понять, как это работает. Я обязательно обновлю, как только сделаю это.

person Geekoder    schedule 09.09.2013
comment
Не задавайте вопрос в ответе. Пожалуйста, отредактируйте вопрос, добавьте комментарий, чтобы сделать проблему более понятной, но не помещайте вопрос в ответ - person veljasije; 09.09.2013