【问题标题】:Record audio to NSData将音频录制到 NSData
【发布时间】:2012-01-19 01:54:31
【问题描述】:

我已经在两部 iPhone 之间建立了 TCP 连接,并且能够在两者之间发送 NSData 包。 我想对着麦克风说话并将录音作为 NSData 对象发送到另一部 iPhone。 我已经成功地使用音频队列服务来录制音频并播放它,但我还没有设法将录音作为 NSData。我posted a question about converting the recording to NSData when using Audio Queue Services 但它没有让我更进一步。

因此,我想知道是否有任何其他方法可以让我对着 iPhone 的麦克风讲话并将输入作为原始数据?

更新:

我需要在录制时连续发送包裹。例如。在录制的每一秒,我都会发送那一秒内录制的数据。

【问题讨论】:

    标签: iphone nsdata record microphone voice


    【解决方案1】:

    这就是我在录制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。

    但我不知道如何读取另一端的数据。我仍在试图弄清楚它是如何工作的。一旦我这样做了,我一定会更新。

    【讨论】:

    • 不要在回答中提问。请编辑问题,添加评论以使问题更清楚,但不要在答案中提出问题
    【解决方案2】:

    Audio Queues 和 RemoteIO Audio Unit 都会以相当低的延迟实时为您提供原始音频缓冲区。您可以使用每个音频回调中给出的缓冲区指针和字节长度来创建一个新的 NSData 块。 RemoteIO 将提供最低延迟,但可能需要在回调线程之外完成网络消息传递。

    【讨论】:

    • 如果我理解正确,我应该能够使用我当前的音频队列并在我的 AudioInputCallback 中执行以下操作? NSUInteger length = inNumberPacketDescriptions * 2;NSData *packet = [NSData dataWithBytes:inBuffer->mAudioData length:length];。那正确吗?我乘以 2 因为这应该是我每个数据包中的字节数(这是在AudioStreamBasicDescription 中设置的)根据idevhub.com/exploring-iphone-audio-part-1 编辑: 看来我不能调用self不过,在我的回调中。
    • 在音频回调之外调用 self。在回调内部设置一个标志,并从外部轮询它需要使用一些数据调用自身。
    • 现在好像可以了。你不知道当数据连续时我将如何播放接收到的数据?
    • 数据并没有真正连续地通过网络传来。您需要一种策略来处理网络延迟抖动和非同步音频采样率。这是两个独立的大问题。
    • 我猜想发送 NSData 数据包并将它们添加到播放队列中不是一种选择。
    【解决方案3】:

    像这样使用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 参考,here

    编辑:

    为了检索录制的音频块,您可以使用NSData 类中的subdataWithRange: 方法。保留您希望从中检索字节的偏移量。您可以让NSTimer 每秒被触发一次,这样您就可以收集字节并发送它们。您需要了解每秒记录了多少字节。

    【讨论】:

    • 我需要在录制时连续发送包。例如。录制时的每一秒,我都会发送那一秒内录制的数据。您提到的解决方案可以实现吗?很抱歉,我没有在我的问题中澄清这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-30
    • 2014-03-04
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多