【问题标题】:Get microphone input using Audio Queue in Swift 3在 Swift 3 中使用音频队列获取麦克风输入
【发布时间】:2017-09-17 01:28:21
【问题描述】:

我正在开发一个应用程序,它通过内置麦克风录制语音并将其实时发送到服务器。所以我需要在录制时从麦克风获取字节流。

在谷歌搜索和堆栈溢出很长一段时间后,我想我知道它应该如何工作,但它没有。我认为使用音频队列可能是要走的路。

这是我目前尝试过的:

func test() {
    func callback(_ a :UnsafeMutableRawPointer?, _ b : AudioQueueRef, _ c :AudioQueueBufferRef, _ d :UnsafePointer<AudioTimeStamp>, _ e :UInt32, _ f :UnsafePointer<AudioStreamPacketDescription>?) {
        print("test")
    }

    var inputQueue: AudioQueueRef? = nil

    var aqData = AQRecorderState(
        mDataFormat: AudioStreamBasicDescription(
            mSampleRate: 16000,
            mFormatID: kAudioFormatLinearPCM,
            mFormatFlags: 0,
            mBytesPerPacket: 2,
            mFramesPerPacket: 1,     // Must be set to 1 for uncomressed formats
            mBytesPerFrame: 2,
            mChannelsPerFrame: 1,    // Mono recording
            mBitsPerChannel: 2 * 8,  // 2 Bytes
            mReserved: 0),  // Must be set to 0 according to https://developer.apple.com/reference/coreaudio/audiostreambasicdescription
        mQueue: inputQueue!,
        mBuffers: [AudioQueueBufferRef](),
        bufferByteSize: 32,
        mCurrentPacket: 0,
        mIsRunning: true)

    var error = AudioQueueNewInput(&aqData.mDataFormat,
                                   callback,
                                   nil,
                                   nil,
                                   nil,
                                   0,
                                   &inputQueue)
    AudioQueueStart(inputQueue!, nil)
}

它编译并且应用程序启动,但是一旦我调用 test() 我得到一个异常:

致命错误:在展开可选值时意外发现 nil

异常是由

引起的
mQueue: inputQueue!

我明白为什么会发生这种情况(inputQueue 没有价值),但我不知道如何正确初始化 inputQueue。问题是 Swift 用户对音频队列的记录非常差,我在互联网上没有找到任何可行的示例。

谁能告诉我我做错了什么?

【问题讨论】:

  • error 中有什么内容?
  • 什么都没有,因为异常发生在错误定义之前
  • 是的,你是对的。我没有找到任何示例如何执行此操作,并且文档没有帮助

标签: ios swift audio-recording audioqueue


【解决方案1】:

使用AudioQueueNewInput(...)(或输出)来初始化您的音频队列之前你正在使用它:

let sampleRate = 16000
let numChannels = 2
var inFormat = AudioStreamBasicDescription(
        mSampleRate:        Double(sampleRate),
        mFormatID:          kAudioFormatLinearPCM,
        mFormatFlags:       kAudioFormatFlagsNativeFloatPacked,
        mBytesPerPacket:    UInt32(numChannels * MemoryLayout<UInt32>.size),
        mFramesPerPacket:   1,
        mBytesPerFrame:     UInt32(numChannels * MemoryLayout<UInt32>.size),
        mChannelsPerFrame:  UInt32(numChannels),
        mBitsPerChannel:    UInt32(8 * (MemoryLayout<UInt32>.size)),
        mReserved:          UInt32(0)

var inQueue: AudioQueueRef? = nil
AudioQueueNewInput(&inFormat, callback, nil, nil, nil, 0, &inQueue)

var aqData = AQRecorderState(
    mDataFormat:    inFormat, 
    mQueue:         inQueue!, // inQueue is initialized now and can be unwrapped
    mBuffers: [AudioQueueBufferRef](),
    bufferByteSize: 32,
    mCurrentPacket: 0,
    mIsRunning:     true)

Apples Documentation中查找详细信息

【讨论】:

  • 谢谢,这比我的效果好,但现在我收到错误代码 1718449215 (kAudioFormatUnsupportedDataFormatError)
  • 您知道如何找出不支持的具体内容吗?
  • 好的,找到了。只需要添加标志 kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
  • 认为 kLinearPCMFormatFlagIsPacked应该足够了。
  • 嘿,你有没有让这个工作?我正在尝试做类似的事情。感谢您链接到 GitHub 中的工作代码。谢谢!
【解决方案2】:

我们项目中的这段代码运行良好:

AudioBuffer * buff; 
AudioQueueRef queue;
AudioStreamBasicDescription  fmt = { 0 };


static void HandleInputBuffer (
                               void                                 *aqData,
                               AudioQueueRef                        inAQ,
                               AudioQueueBufferRef                  inBuffer,
                               const AudioTimeStamp                 *inStartTime,
                               UInt32                               inNumPackets,
                               const AudioStreamPacketDescription   *inPacketDesc

                               ) {

 }



- (void) initialize  {


    thisClass = self;

    __block struct AQRecorderState aqData;

    NSError * error;

    fmt.mFormatID         = kAudioFormatLinearPCM; 
    fmt.mSampleRate       = 44100.0;               
    fmt.mChannelsPerFrame = 1;                     
    fmt.mBitsPerChannel   = 16;                    
    fmt.mChannelsPerFrame = 1;
    fmt.mFramesPerPacket  = 1;
    fmt.mBytesPerFrame = sizeof (SInt16);
    fmt.mBytesPerPacket = sizeof (SInt16);


    fmt.mFormatFlags =  kLinearPCMFormatFlagIsSignedInteger  | kLinearPCMFormatFlagIsPacked;




    OSStatus status = AudioQueueNewInput (                              // 1
                        &fmt,                          // 2
                        HandleInputBuffer,                            // 3
                        &aqData,                                      // 4
                        NULL,                                         // 5
                        kCFRunLoopCommonModes,                        // 6
                        0,                                            // 7
                        &queue                                // 8
                        );



    AudioQueueBufferRef  buffers[kNumberBuffers];
    UInt32 bufferByteSize = kSamplesSize;
    for (int i = 0; i < kNumberBuffers; ++i) {           // 1
        OSStatus allocateStatus;
        allocateStatus =  AudioQueueAllocateBuffer (                       // 2
                                  queue,                               // 3
                                  bufferByteSize,                       // 4
                                  &buffers[i]                          // 5
                                  );
        OSStatus  enqueStatus;
        NSLog(@"allocateStatus = %d" , allocateStatus);
        enqueStatus =   AudioQueueEnqueueBuffer (                        // 6
                                 queue,                               // 7
                                 buffers[i],                          // 8
                                 0,                                           // 9
                                 NULL                                         // 10
                                 );
        NSLog(@"enqueStatus = %d" , enqueStatus);
    }



    AudioQueueStart (                                    // 3
                     queue,                                   // 4
                     NULL                                             // 5
                     );


}

【讨论】:

  • 问题是关于swift
猜你喜欢
  • 2011-09-05
  • 1970-01-01
  • 2020-09-28
  • 2020-05-06
  • 1970-01-01
  • 2017-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多