OS X에서 CoreAudio를 사용하여 원시 PCM 데이터 (16 비트 부호)를 재생해야합니다. UDP 소켓을 사용하여 네트워크에서 가져옵니다 (송신 측 데이터는 마이크에서 캡처 됨) .
문제는 내가 들었을 때 짧은 깨지는 소리와 조용한 소리 만 들리는 것입니다.
AudioQueue를 사용하여 데이터를 재생하려고합니다. 이 같은 I 설정을 :CoreAudio에서 AudioQueue를 사용하여 네트워크에서 raw pcm 재생
// Set up stream format fields
AudioStreamBasicDescription streamFormat;
streamFormat.mSampleRate = 44100;
streamFormat.mFormatID = kAudioFormatLinearPCM;
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
streamFormat.mBitsPerChannel = 16;
streamFormat.mChannelsPerFrame = 1;
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
streamFormat.mFramesPerPacket = 1;
streamFormat.mReserved = 0;
OSStatus err = noErr;
// create the audio queue
err = AudioQueueNewOutput(&streamFormat, MyAudioQueueOutputCallback, myData, NULL, NULL, 0, &myData->audioQueue);
if (err)
{ PRINTERROR("AudioQueueNewOutput"); myData->failed = true; result = false;}
// allocate audio queue buffers
for (unsigned int i = 0; i < kNumAQBufs; ++i) {
err = AudioQueueAllocateBuffer(myData->audioQueue, kAQBufSize, &myData->audioQueueBuffer[i]);
if (err)
{ PRINTERROR("AudioQueueAllocateBuffer"); myData->failed = true; break; result = false;}
}
// listen for kAudioQueueProperty_IsRunning
err = AudioQueueAddPropertyListener(myData->audioQueue, kAudioQueueProperty_IsRunning, MyAudioQueueIsRunningCallback, myData);
if (err)
{ PRINTERROR("AudioQueueAddPropertyListener"); myData->failed = true; result = false;}
MyAudioQueueOutputCallback은 다음과 같습니다
void MyAudioQueueOutputCallback(void* inClientData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer)
{
// this is called by the audio queue when it has finished decoding our data.
// The buffer is now free to be reused.
MyData* myData = (MyData*)inClientData;
unsigned int bufIndex = MyFindQueueBuffer(myData, inBuffer);
// signal waiting thread that the buffer is free.
pthread_mutex_lock(&myData->mutex);
myData->inuse[bufIndex] = false;
pthread_cond_signal(&myData->cond);
pthread_mutex_unlock(&myData->mutex);
}
MyAudioQueueIsRunningCallback은 다음과 같습니다
void MyAudioQueueIsRunningCallback(void* inClientData,
AudioQueueRef inAQ,
AudioQueuePropertyID inID)
{
MyData* myData = (MyData*)inClientData;
UInt32 running;
UInt32 size;
OSStatus err = AudioQueueGetProperty(inAQ, kAudioQueueProperty_IsRunning, &running, &size);
if (err) { PRINTERROR("get kAudioQueueProperty_IsRunning"); return; }
if (!running) {
pthread_mutex_lock(&myData->mutex);
pthread_cond_signal(&myData->done);
pthread_mutex_unlock(&myData->mutex);
}
}
및 MyData로는 : 미안 해요
struct MyData
{
AudioQueueRef audioQueue; // the audio queue
AudioQueueBufferRef audioQueueBuffer[kNumAQBufs]; // audio queue buffers
AudioStreamPacketDescription packetDescs[kAQMaxPacketDescs]; // packet descriptions for enqueuing audio
unsigned int fillBufferIndex; // the index of the audioQueueBuffer that is being filled
size_t bytesFilled; // how many bytes have been filled
size_t packetsFilled; // how many packets have been filled
bool inuse[kNumAQBufs]; // flags to indicate that a buffer is still in use
bool started; // flag to indicate that the queue has been started
bool failed; // flag to indicate an error occurred
bool finished; // flag to inidicate that termination is requested
pthread_mutex_t mutex; // a mutex to protect the inuse flags
pthread_mutex_t mutex2; // a mutex to protect the AudioQueue buffer
pthread_cond_t cond; // a condition varable for handling the inuse flags
pthread_cond_t done; // a condition varable for handling the inuse flags
};
나는 경우 너무 많은 코드 게시 - 희망 그것은 내가하는 것을 정확히 이해하는 데 도움이됩니다.
대부분 내 코드는 this 코드를 기반으로합니다.이 코드는 CBR 데이터 작업에 적합한 Mac Developer Library의 AudioFileStreamExample 버전입니다.
또한 this 게시물을보고 거기에 설명 된 AudioStreamBasicDescription을 시도했습니다. 리틀 또는 빅 엔디 언으로 플래그를 변경하려고했습니다. 그것은 작동하지 않았다.
비슷한 문제를 발견하는 동안 여기에 다른 게시물과 다른 리소스를 보았습니다. 예를 들어 내 PCM 데이터의 순서를 확인했습니다. 두 개 이상의 링크를 게시 할 수 없습니다.
내가 뭘 잘못하고 있는지 이해할 수 있도록 도와주세요. 어쩌면 내가 이런 식으로 포기하고 즉시 Audio Units를 사용해야할까요? CoreAudio의 초보자 일 뿐이며 CoreAudio의 중간 레벨이이 문제를 해결하는 데 도움이되기를 바랍니다.
P. 미안해, 내 영어로 할 수있는대로 노력했다.
'MyFindQueueBuffer'는 (는) 어떻게 생겼습니까? 다만 그런 – sbooth
: 'MyFindQueueBuffer INT (MyData로 * MYDATA, AudioQueueBufferRef inBuffer) 용 { (부호 INT I = 0; I audioQueueBuffer [I]) return i; } return -1; } ' –
foobar
죄송합니다, linebreaks %로 엉망이되었습니다. – foobar