그래서 모든 것을 설정하고 입력 콜백에서 오디오 데이터를받는 평범한 과정을 거침으로써 입력 대기열에 녹음하고 싶다고합시다. 이 파일을 작성하는 대신 간단히 어딘가에 버퍼링을 시작한 다음 입력 대기열 바로 다음에 실행되도록 출력 대기열에 공급하고 싶습니다. 입력 대기열에서 버퍼링 할 데이터를 사용하고 재생 중입니다. 내가 녹음 할 때의 오디오. 이것이 가능한가? 이 구현을 시도했지만 내 출력 대기열을 시작하는 문제가 발생합니다. 초기화하고 아무 오류도보고하지 않지만 AudioQueueStart 함수를 호출 한 후에는 제공된 출력 콜백이 호출되지 않습니다. 아마도 이것이 내 구현의 문제이지만, 막 다른 골목에 먼저 들어가는 일이 없도록하려는 것입니다. 명령 줄 응용 프로그램에서이 POC를 실행하는 코드 추가두 개의 AudioQueue를 동시에 실행하는 Core Audio
임 :
감사
편집
.static void *buffer[1000];
:
Recorder recorder = {0};
AudioStreamBasicDescription asbd;
memset(&asbd, 0, sizeof(asbd));
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mSampleRate = SAMPLE_RATE;
asbd.mBytesPerPacket = 4;
asbd.mBytesPerFrame = 4;
asbd.mChannelsPerFrame = 2;
asbd.mBitsPerChannel = 16;
asbd.mFramesPerPacket = 1;
asbd.mFormatFlags = kAudioFormatFlagIsBigEndian |
kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
AudioQueueRef queue = {0};
reportError(AudioQueueNewInput(&asbd, MyAQInputCallback, &recorder, NULL, NULL, 0, &queue), "AudioQueue Input Create");
int bufferSize = 88200;
for (int i = 0; i < BUFFER_COUNT; i++) {
AudioQueueBufferRef retBuffer;
reportError(AudioQueueAllocateBuffer(queue, bufferSize, &retBuffer), "Error Allocating Buffer");
reportError(AudioQueueEnqueueBuffer(queue, retBuffer, 0, NULL), "Error enqueuing buffer");
}
recorder.running = YES;
reportError(AudioQueueStart(queue, NULL), "Start Failed");
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 3, false);
내가,이 내가 그냥가 실행 얻을 수 있는지보고 싶어 변경됩니다 들어오는 데이터를 보유하는 글로벌 무효 포인터 배열을 선언 주에서 나는 레코더를 초기화 내 입력 콜백. 레코더 내가이 전에 파일에 기록하며 한 나를 위해 벌금을 실행하고있다, 그래서 이것은 특정 지점의 부름을받을 않습니다
기본적으로
static void MyAQInputCallback(void *inUserData,
AudioQueueRef inQueue,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc)
{
Recorder *recorder = (Recorder *) inUserData;
buffer[globalBufferIndex] = (short *)inBuffer->mAudioData;
++globalBufferIndex;
if (globalBufferIndex == 1000) {
globalBufferIndex = 0;
clearBuffer();
}
if (recorder->running) {
reportError(AudioQueueEnqueueBuffer(inQueue, inBuffer, 0, NULL), "CallbackEnqueue Failed");
}
}
단지 덩어리를 끌어에 저장하는 것입니다 여기에 목표 버퍼 나는 이것이 꼭해야한다고 생각한다.
플레이어가 초기화된다
Player player = {0};
AudioQueueRef que = {0};
reportError(AudioQueueNewOutput(&asbd, MyAQOutputCallback, &player, NULL, NULL, 0, &que), "New Output Error");
AudioQueueBufferRef buffers[BUFFER_COUNT];
for (int i = 0; i < BUFFER_COUNT; ++i) {
reportError(AudioQueueAllocateBuffer(que, bufferSize, &buffers[i]), "Error Buffer Allocating");
MyAQOutputCallback(&player, que, buffers[i]);
}
reportError(AudioQueueStart(que, NULL), "Start Failed");
플레이어 콜백 :
static void MyAQOutputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer)
{
Player *player;
player = (Player *) inUserData;
short *chunk = (short *) inCompleteAQBuffer->mAudioData;
chunk = buffer[globalOutputBufferIndex];
globalOutputBufferIndex++;
AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, sizeof(chunk)/4, player->packetDescs);
}
뭐죠 큐에 글로벌 버퍼에 저장하고를 보낼 수있는 목표.
그래서 이건 훌륭한 구조는 아니지만 내가 실행할 때 얻는 동작은 레코더가 입력 콜백에 대한 호출을 실행하고 데이터를 저장하지만 그 다음에 플레이어 초기화 및 출력 콜백이 실행된다는 것입니다. 3 회 (my for 루프 호출) 호출하고 결코 다시 호출되지 않습니다. getchar()을 호출하여 마지막에 앱 종료를 차단합니다. 나는 플레이어가 파일을 읽고 그것을 읽도록 노력하도록 만들었다. 분명히 이것은 매우 다르다. 레코더는 계속 작동하지만 플레이어 콜백은 호출되지 않습니다. 나는 아마 내 설명에 문제가 있다고 생각했으나 할당하는 동안 오류는 절대로 나에게보고되지 않는다. 여기에 어떤 지침이라도 좋을 것입니다.
https://github.com/alexbw/novocaine이 코드를 표시 :
감사 –