我正在写一个基于c的合成器。当我尝试使用AudioQueueEnqueueBuffer函数将缓冲区排入队列时,我遇到了问题。在不同的执行中,我有不同的错误,如缓冲区的malloc-error或BAD_ISTRUCTION或BAD_ACCESS(代码= EXC_I386 _...)。有时回调编码成功排队缓冲区,但程序在尝试启动AudioQueue或将数据复制到缓冲区时崩溃。 这里有代码,希望你能帮助我。
当我的代码进入回调时,Xcode向我打印这个奇怪的警告:“警告:无法加载任何Objective-C类信息。这将显着降低可用类型信息的质量。”,但是我已经'为什么......
synthesis.h
#include <stdio.h>
#include <stdlib.h>
#include <AudioToolBox/AudioQueue.h>
#include <CoreAudio/CoreAudioTypes.h>
#include <math.h>
#include <stdbool.h>
#include <MacTypes.h>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
#define PI 3.141592
#define DBG(func, ex) fprintf(stderr, "Error in %s. n. %d\n", func, ex); exit(ex);
static const UInt8 nOfBuffer = 3;
struct wave {
Float64 samplingRate;
Float64 phase;
UInt32 frequency;
SInt16 *samples;
UInt16 seconds;
};
typedef struct wave Wave;
struct stream {
Wave sine;
AudioStreamBasicDescription asbd;
AudioQueueRef audioQueue;
AudioQueueBufferRef audioBuffer[nOfBuffer];
UInt32 bufferSizeByte;
UInt32 counter;
UInt32 lastPos;
Boolean isRunning;
UInt32 nOfPacketToRead;
};
typedef struct stream Stream;
void init(
Stream *sine
);
static void fillBuffer(
void *userData,
AudioQueueRef aQ,
AudioQueueBufferRef inBuf
);
void generateSine(
Stream *sine
);
的main.c
#include "synthesis.h"
int main() {
Stream *sine = (Stream *)malloc(sizeof(Stream));
init(sine);
generateSine(sine);
return 0;
}
synthesis.c
#include "synthesis.h"
#include <limits.h>
static void fillBuffer(void *userData, AudioQueueRef aQ, AudioQueueBufferRef buf) {
/*
callback for fill audioqueue's buffers
*/
Stream *sine = (Stream *)userData;
if(!sine->isRunning) return;
OSStatus err = noErr;
UInt32 dif = 0;
UInt32 i = 0;
SInt16 *data = (SInt16 *)buf->mAudioData;
UInt32 lenght = buf->mAudioDataBytesCapacity / sizeof(SInt16);
/* fill the buffer with the samples creates in generateSine */
while (sine->counter - sine->lastPos < lenght && sine->counter < (sine->sine.samplingRate *
sine->sine.seconds)) {
data[i] = sine->sine.samples[sine->counter];
i++;
sine->counter++;
}
dif = sine->counter - sine->lastPos;
buf->mAudioDataByteSize = dif * sizeof(SInt16);
if(dif > 0) {
err = AudioQueueEnqueueBuffer(aQ, buf, 0, NULL);
if(err != noErr) {
DBG("aQenqueuebuffer", err);
}
sine->lastPos = sine->counter;
} else {
sine->isRunning = false;
err = AudioQueueStop(aQ, false);
if(err != noErr) {
DBG("aQstop", err);
}
}
}
void init(Stream *sine) {
/*
initialize all var and set the ASBD for an integer 16 bit linear PCM
*/
OSStatus err = noErr;
sine->sine.frequency = 440;
sine->sine.phase = 0.0;
sine->sine.samplingRate = 96000;
sine->counter = 0;
sine->lastPos = 0;
sine->bufferSizeByte = 0x4000;
sine->sine.seconds = 2;
sine->sine.samples = (SInt16 *)malloc(sizeof(SInt16) * sine->sine.seconds * sine->asbd.mSampleRate);
sine->asbd.mBytesPerPacket = 2;
sine->asbd.mFramesPerPacket = 1;
sine->asbd.mBytesPerFrame = 2;
sine->asbd.mChannelsPerFrame = 1;
sine->asbd.mBitsPerChannel = 16;
sine->asbd.mSampleRate = 96000;
sine->asbd.mFormatID = 'lpcm';
sine->asbd.mReserved = 0;
sine->asbd.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
err = AudioQueueNewOutput(&sine->asbd, fillBuffer, sine, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0,
&sine->audioQueue);
if(err != noErr) {
DBG("aQnewOutput", err);
}
for(int i = 0; i < nOfBuffer; i++) {
err = AudioQueueAllocateBuffer(sine->audioQueue, sine->bufferSizeByte, &sine->audioBuffer[i]);
if(err != noErr) {
DBG("aQallocatebuffer", err);
}
}
}
void generateSine(Stream *sine) {
OSStatus err = noErr;
UInt32 lenght = sine->sine.samplingRate * sine->sine.seconds;
for(int i = 0; i < lenght; i++) {
sine->sine.samples[i] = sin(2 * PI * sine->sine.frequency * i + sine->sine.phase) * SHRT_MAX;
}
sine->isRunning = true;
for(int i = 0; i < nOfBuffer; i++) {
fillBuffer((void *)sine, sine->audioQueue, sine->audioBuffer[i]);
}
err = AudioQueueStart(sine->audioQueue, NULL);
if(err != noErr) {
DBG("aQstart", err);
}
do {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false);
}while(sine->isRunning);
AudioQueueDispose(sine->audioQueue, false);
free(sine->sine.samples);
free(sine);
}