38 #ifndef MacOSSoundFunctions_h 39 #define MacOSSoundFunctions_h 41 #include <AudioToolbox/AudioToolbox.h> 51 #pragma mark user data struct 52 #pragma mark user info struct 55 AudioQueueBufferRef buffer;
65 void timer_handler (
int signum);
72 void timer_handler (
int signum)
86 sa.sa_handler = timer_handler;
87 sa.sa_flags = SA_RESETHAND;
88 sigaction(SIGALRM, &sa, 0);
91 #pragma mark record callback function 92 static void AQInputCallback(
void *inUserData, AudioQueueRef inQueue, AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime, UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc);
104 static void AQInputCallback(
void *inUserData, AudioQueueRef inQueue, AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime, UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc)
107 RecorderStruct *recorder = (RecorderStruct *)inUserData;
109 if (inNumPackets > 0) {
110 recorder->buffer = inBuffer;
111 short *goodBuffer = inBuffer->mAudioData;
114 recorder->idWriteMB = (recorder->idWriteMB + recorder->numLastRead) % MiddleBufferSize;
115 if(recorder->idWriteMB == 0) {
116 recorder->toursWrited++;
120 if(recorder->idWriteMB + (inBuffer->mAudioDataByteSize/
sizeof(
short)) > MiddleBufferSize-1)
122 int toTT = MiddleBufferSize - recorder->idWriteMB;
123 while((recorder->idWriteMB > (recorder->idReadMB + MiddleBufferSize*0.5) && recorder->toursReaded == recorder->toursWrited) || (recorder->toursWrited > recorder->toursReaded && (recorder->idWriteMB + MiddleBufferSize*0.5) > recorder->idReadMB) || (recorder->toursWrited < recorder->toursReaded && MiddleBufferSize*0.5 <= recorder->idWriteMB - recorder->idReadMB)){
126 memcpy(&recorder->middleBuffer[recorder->idWriteMB],goodBuffer, toTT*
sizeof(
short));
127 recorder->numLastRead = (inBuffer->mAudioDataByteSize/
sizeof(short)) - toTT;
128 recorder->idWriteMB = 0;
129 recorder->toursWrited++;
130 memcpy(recorder->middleBuffer,&goodBuffer[toTT], recorder->numLastRead*
sizeof(
short));
134 while((recorder->idWriteMB > (recorder->idReadMB + MiddleBufferSize*0.5) && recorder->toursReaded == recorder->toursWrited) || (recorder->toursWrited > recorder->toursReaded && (recorder->idWriteMB + MiddleBufferSize*0.5) > recorder->idReadMB) || (recorder->toursWrited < recorder->toursReaded && MiddleBufferSize*0.5 <= recorder->idWriteMB - recorder->idReadMB)){
137 memcpy(&recorder->middleBuffer[recorder->idWriteMB],goodBuffer, inBuffer->mAudioDataByteSize);
138 recorder->numLastRead = inBuffer->mAudioDataByteSize/
sizeof(short);
141 if (recorder->running)
143 err = AudioQueueEnqueueBuffer(inQueue,inBuffer, 0, NULL);
144 recorder->bufferChange =
true;
148 fprintf(stderr,
"Error: %s (%s)\n",
"AQInputCallback failed",
"(Enqueue or Write Output file?)");
153 #pragma mark utility functions 154 void CheckError(OSStatus error,
const char *operation);
163 void CheckError(OSStatus error,
const char *operation)
165 if (error == noErr)
return;
167 char errorString[20];
169 *(UInt32 *)(errorString + 1) = CFSwapInt32HostToBig(error);
170 if (isprint(errorString[1]) && isprint(errorString[2]) && isprint(errorString[3]) && isprint(errorString[4]))
172 errorString[0] = errorString[5] =
'\'';
173 errorString[6] =
'\0';
177 sprintf(errorString,
"%d", (
int)error);
180 fprintf(stderr,
"Error: %s (%s)\n", operation, errorString);
185 static int ComputeRecordBufferSize(
const AudioStreamBasicDescription *format, AudioQueueRef queue,
float frames);
194 static int ComputeRecordBufferSize(
const AudioStreamBasicDescription *format, AudioQueueRef queue,
float frames)
197 if (format->mBytesPerFrame > 0)
198 bytes = frames * format->mBytesPerFrame;
201 UInt32 maxPacketSize;
202 if (format->mBytesPerPacket > 0)
204 maxPacketSize = format->mBytesPerPacket;
208 UInt32 propertySize =
sizeof(maxPacketSize);
209 CheckError(AudioQueueGetProperty(queue, kAudioConverterPropertyMaximumOutputPacketSize,
210 &maxPacketSize, &propertySize),
"Couldn't get queue's maximum output packet size");
212 if (format->mFramesPerPacket > 0)
213 packets = frames / format->mFramesPerPacket;
220 bytes = packets * maxPacketSize;
225 void ConfigureAndAllocAudioQueues(RecorderStruct* recorder, AudioQueueRef* queue);
233 void ConfigureAndAllocAudioQueues(RecorderStruct* recorder, AudioQueueRef* queue)
236 AudioStreamBasicDescription recordFormat;
237 memset(&recordFormat, 0,
sizeof(recordFormat));
238 recordFormat.mFormatID |= kAudioFormatLinearPCM;
240 recordFormat.mFormatFlags &= ~kLinearPCMFormatFlagsAreAllClear;
241 recordFormat.mFormatFlags &= ~kLinearPCMFormatFlagIsFloat;
242 recordFormat.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
243 recordFormat.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
244 recordFormat.mFormatFlags &= ~kLinearPCMFormatFlagIsNonInterleaved;
245 recordFormat.mFormatFlags &= ~kLinearPCMFormatFlagIsNonMixable;
246 recordFormat.mFormatFlags |= kLinearPCMFormatFlagIsPacked;
248 recordFormat.mChannelsPerFrame = AQChannels;
249 recordFormat.mBitsPerChannel = AQBitsPerChannel;
250 recordFormat.mSampleRate = AQRate;
252 int bytes = (recordFormat.mBitsPerChannel / 8) * recordFormat.mChannelsPerFrame;
253 recordFormat.mBytesPerFrame = bytes;
254 recordFormat.mBytesPerPacket = bytes;
256 UInt32 propSize =
sizeof(recordFormat);
257 CheckError(AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &propSize, &recordFormat),
"AudioFormatGetProperty failed");
260 recorder->middleBuffer = calloc(MiddleBufferSize,
sizeof(
short));
261 recorder->idReadMB = -1;
262 recorder->idWriteMB = 0;
263 recorder->numLastRead = 0;
264 recorder->toursWrited = 0;
265 recorder->toursReaded = 1;
266 recorder->bufferChange =
false;
269 CheckError(AudioQueueNewInput(&recordFormat, AQInputCallback, recorder, NULL, NULL, 0, queue),
"AudioQueueNewInput failed");
270 UInt32 size =
sizeof(recordFormat);
271 CheckError(AudioQueueGetProperty(*queue, kAudioConverterCurrentOutputStreamDescription, &recordFormat, &size),
"Couldn't get queue's format");
274 int bufferByteSize = ComputeRecordBufferSize(&recordFormat, *queue, AQBufferSize);
277 for (bufferIndex = 0; bufferIndex < kNumberRecordBuffers; ++bufferIndex)
279 AudioQueueBufferRef buffer;
280 CheckError(AudioQueueAllocateBuffer(*queue, bufferByteSize, &buffer),
"AudioQueueAllocateBuffer failed");
281 CheckError(AudioQueueEnqueueBuffer(*queue, buffer, 0, NULL),
"AudioQueueEnqueueBuffer failed");
283 CheckError(AudioQueueAllocateBuffer(*queue, bufferByteSize, &recorder->buffer),
"AudioQueueAllocateBuffer failed");
285 printf(
"Rate after config: %f \nBitsPerChannel: %d\nChanels: %d\nBytes Per Frames and Packets: %d\n",recordFormat.mSampleRate, recordFormat.mBitsPerChannel, recordFormat.mChannelsPerFrame, recordFormat.mBytesPerPacket);
288 int ReadAudioQueue1st(
short *frame, RecorderStruct* recorder, FILE *fpdump);
297 int ReadAudioQueue1st(
short *frame, RecorderStruct* recorder, FILE *fpdump)
300 for (i=0; i<=(TAMTRAMA/TAMMUESTRA) ; i++)
302 if (recorder->idReadMB < 0)
304 recorder->idReadMB = 0;
305 while((recorder->idWriteMB < (recorder->idReadMB + MiddleBufferSize*0.5) && recorder->toursReaded == recorder->toursWrited) || (recorder->toursWrited < recorder->toursReaded && recorder->idWriteMB < (recorder->idReadMB + MiddleBufferSize*0.5)) || (recorder->toursWrited > recorder->toursReaded && MiddleBufferSize*0.5 <= recorder->idReadMB - recorder->idWriteMB)){
308 memcpy(&frame[TAMMUESTRA*i],recorder->middleBuffer,TAMMUESTRA*
sizeof(
short));
309 recorder->bufferChange =
false;
313 recorder->idReadMB = (recorder->idReadMB + TAMMUESTRA) % MiddleBufferSize;
314 if(recorder->idReadMB == 0){
315 recorder->toursReaded++;
317 while((recorder->idWriteMB < (recorder->idReadMB + MiddleBufferSize*0.5) && recorder->toursReaded == recorder->toursWrited) || (recorder->toursWrited < recorder->toursReaded && recorder->idWriteMB < (recorder->idReadMB + MiddleBufferSize*0.5)) || (recorder->toursWrited > recorder->toursReaded && MiddleBufferSize*0.5 <= recorder->idReadMB - recorder->idWriteMB)){
320 memcpy(&frame[TAMMUESTRA*i],&recorder->middleBuffer[recorder->idReadMB],TAMMUESTRA*
sizeof(
short));
321 recorder->bufferChange =
false;
326 if (fwrite(&frame[TAMMUESTRA],
sizeof(
short), TTminusTM, fpdump) != TTminusTM)
return ErrWriteFile;
332 int ReadAudioQueue(
short *frame, RecorderStruct* recorder, FILE *fpdump);
341 int ReadAudioQueue(
short *frame, RecorderStruct* recorder, FILE *fpdump)
343 memmove(frame, &frame[TAMMUESTRA],
sizeof(
short)*TTminusTM);
344 recorder->idReadMB = (recorder->idReadMB + TAMMUESTRA) % MiddleBufferSize;
346 if(recorder->idReadMB == 0) {
347 recorder->toursReaded++;
349 while((recorder->idWriteMB < (recorder->idReadMB + MiddleBufferSize*0.5) && recorder->toursReaded == recorder->toursWrited) || (recorder->toursWrited < recorder->toursReaded && recorder->idWriteMB < (recorder->idReadMB + MiddleBufferSize*0.5)) || (recorder->toursWrited > recorder->toursReaded && MiddleBufferSize*0.5 <= recorder->idReadMB - recorder->idWriteMB)){
352 memcpy(&frame[TTminusTM],&recorder->middleBuffer[recorder->idReadMB],TAMMUESTRA*
sizeof(
short));
353 recorder->bufferChange =
false;
355 if (fwrite(&frame[TTminusTM],
sizeof(
short), TAMMUESTRA, fpdump) != TAMMUESTRA)
return ErrWriteFile;
General header file with constants, defines, structs, etc. using by ReMAS, both CPU and GPU...