如何使用AudioQueue在C++中为Mac OSX播放声音

use*_*524 5 c++ macos

我试图在OSX上播放声音,来自缓冲区(例如:等效的Windows"PlaySound"功能).

我已经整理了一些C++代码来播放AudioQueue的音频(因为我的理解是这是在OSX上播放音频的最简单方法).

但是,从未生成声音,并且从不调用音频回调函数.

有人知道我做错了什么,或者有没有人有一个简单的C/C++例子来说明如何在OSX上播放声音?


#include 
#include 

#define BUFFER_COUNT 3
static struct AQPlayerState {
    AudioStreamBasicDescription   desc;
    AudioQueueRef                 queue;
    AudioQueueBufferRef           buffers[BUFFER_COUNT];
    unsigned buffer_size;
} state;

static void audio_callback (void *aux, AudioQueueRef aq, AudioQueueBufferRef bufout)
{
    printf("I never get called!\n");
#define nsamples 4096
    short data[nsamples];
    for (int i=0;imAudioDataByteSize = nsamples * sizeof(short) * 1;

    assert(bufout->mAudioDataByteSize mAudioData, data, bufout->mAudioDataByteSize);

    AudioQueueEnqueueBuffer(state.queue, bufout, 0, NULL);
}

void audio_init()
{
    int i;

    bzero(&state, sizeof(state));

    state.desc.mFormatID = kAudioFormatLinearPCM;
    state.desc.mFormatFlags = kAudioFormatFlagIsSignedInteger   | kAudioFormatFlagIsPacked;
    state.desc.mSampleRate = 44100;
    state.desc.mChannelsPerFrame = 1;
    state.desc.mFramesPerPacket = 1;
    state.desc.mBytesPerFrame = sizeof (short) * state.desc.mChannelsPerFrame;
    state.desc.mBytesPerPacket = state.desc.mBytesPerFrame;
    state.desc.mBitsPerChannel = (state.desc.mBytesPerFrame*8)/state.desc.mChannelsPerFrame;
    state.desc.mReserved = 0;

    state.buffer_size = state.desc.mBytesPerFrame * state.desc.mSampleRate;

    if (noErr != AudioQueueNewOutput(&state.desc, audio_callback, 0, NULL, NULL, 0, &state.queue)) {
    printf("audioqueue error\n");
    return;
    }

    // Start some empty playback so we'll get the callbacks that fill in the actual audio.
    for (i = 0; i mAudioDataByteSize = state.buffer_size;
    AudioQueueEnqueueBuffer(state.queue, state.buffers[i], 0, NULL);
    }
    if (noErr != AudioQueueStart(state.queue, NULL)) printf("AudioQueueStart failed\n");
    printf("started audio\n");
}


int main() {
    audio_init();
    while (1) {
    printf("I can't hear anything!\n");
    }
}
Run Code Online (Sandbox Code Playgroud)

bw1*_*024 10

REFS:

请注意,我必须将mAudioDataByteSize显式设置为我分配的大小.在文档中,他们提到它最初设置为零,这就是我发现的.文档没有说明为什么,但我怀疑它是允许可变大小的缓冲区或什么?

/* Ben's Audio Example for OSX 10.5+ (yeah Audio Queue)
     Ben White, Nov, 2011 

Makefile:


example: example.c
        gcc -o $@ $< -Wimplicit -framework AudioToolbox \
                -framework CoreFoundation -lm

*/

#include "AudioToolbox/AudioToolbox.h"

typedef struct {
  double phase, phase_inc;
  int count;
} PhaseBlah;


void callback (void *ptr, AudioQueueRef queue, AudioQueueBufferRef buf_ref)
{
  OSStatus status;
  PhaseBlah *p = ptr;
  AudioQueueBuffer *buf = buf_ref;
  int nsamp = buf->mAudioDataByteSize / 2;
  short *samp = buf->mAudioData;
  int ii;
  printf ("Callback! nsamp: %d\n", nsamp);
  for (ii = 0; ii < nsamp; ii++) {
    samp[ii] = (int) (30000.0 * sin(p->phase));
    p->phase += p->phase_inc;
    //printf("phase: %.3f\n", p->phase);
  }
  p->count++;
  status = AudioQueueEnqueueBuffer (queue, buf_ref, 0, NULL);
  printf ("Enqueue status: %d\n", status);
}


int main (int argc, char *argv[])
{
  AudioQueueRef queue;
  PhaseBlah phase = { 0, 2 * 3.14159265359 * 450 / 44100 };
  OSStatus status;
  AudioStreamBasicDescription fmt = { 0 };
  AudioQueueBufferRef buf_ref, buf_ref2;

  fmt.mSampleRate = 44100;
  fmt.mFormatID = kAudioFormatLinearPCM;
  fmt.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
  fmt.mFramesPerPacket = 1;
  fmt.mChannelsPerFrame = 1; // 2 for stereo
  fmt.mBytesPerPacket = fmt.mBytesPerFrame = 2; // x2 for stereo
  fmt.mBitsPerChannel = 16;

  status = AudioQueueNewOutput(&fmt, callback, &phase, CFRunLoopGetCurrent(),
                  kCFRunLoopCommonModes, 0, &queue);

  if (status == kAudioFormatUnsupportedDataFormatError) puts ("oops!");
  else printf("NewOutput status: %d\n", status);

  status = AudioQueueAllocateBuffer (queue, 20000, &buf_ref);
  printf ("Allocate status: %d\n", status);

  AudioQueueBuffer *buf = buf_ref;
  printf ("buf: %p, data: %p, len: %d\n", buf, buf->mAudioData, buf->mAudioDataByteSize);
  buf->mAudioDataByteSize = 20000;

  callback (&phase, queue, buf_ref);

  status = AudioQueueAllocateBuffer (queue, 20000, &buf_ref2);
  printf ("Allocate2 status: %d\n", status);

  buf = buf_ref2;
  buf->mAudioDataByteSize = 20000;

  callback (&phase, queue, buf_ref2);

  status = AudioQueueSetParameter (queue, kAudioQueueParam_Volume, 1.0);
  printf ("Volume status: %d\n", status);

  status = AudioQueueStart (queue, NULL);
  printf ("Start status: %d\n", status);

  while (phase.count < 15)
    CFRunLoopRunInMode (
        kCFRunLoopDefaultMode,
        0.25, // seconds
        false // don't return after source handled
    );

  return 0;
}
Run Code Online (Sandbox Code Playgroud)