Updating built in Io code to use += instead of x = x + y
[io/quag.git] / addons / PortAudio / source / AudioDevice.c
blob1c0ce0239daf92b76da8130876bd3c4a7b80396b
2 #include "AudioDevice.h"
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <math.h>
6 #include <limits.h>
7 #include <time.h>
8 #include <unistd.h>
10 #define FRAMES_PER_BUFFER 256
11 #define INPUT_CHANNELS 1
13 void AudioDevice_nanoSleep(AudioDevice *self)
16 struct timespec rqtp;
17 struct timespec extra;
18 rqtp.tv_sec = 0;
19 rqtp.tv_nsec = 10;
20 nanosleep(&rqtp, &extra);
22 usleep(self->lockSleepMicroSeconds);
23 //printf("AudioDevice usleep(%i)\n", self->lockSleepMicroSeconds);
26 AudioDevice *AudioDevice_new(void)
28 AudioDevice *self = calloc(1, sizeof(AudioDevice));
30 self->writeBuffer = UArray_new();
31 self->nextWriteBuffer = UArray_new();
33 self->readBuffer = UArray_new();
34 self->nextReadBuffer = UArray_new();
35 self->maxReadFrame = 4096 * 100;
36 self->lockSleepMicroSeconds = 10;
37 self->needsData = 1;
39 AudioDevice_init(self);
40 return self;
43 inline void AudioDevice_lock(AudioDevice *self)
45 while (self->locked) { AudioDevice_nanoSleep(self); }
46 self->locked = 1;
49 inline void AudioDevice_unlock(AudioDevice *self)
51 self->locked = 0;
54 int AudioDevice_isLocked(AudioDevice *self)
56 return self->locked;
59 void AudioDevice_free(AudioDevice *self)
61 self->isFreed = 1;
62 AudioDevice_lock(self);
64 while (self->locked)
65 { printf("AudioDevice_free waiting on lock %i\n", self->locked); }
67 AudioDevice_terminate(self);
69 UArray_free(self->writeBuffer);
70 UArray_free(self->nextWriteBuffer);
72 UArray_free(self->readBuffer);
73 UArray_free(self->nextReadBuffer);
75 free(self);
78 void AudioDevice_init(AudioDevice *self)
80 self->locked = 0;
81 /*printf("AudioDevice_init\n");*/
82 self->err = Pa_Initialize();
83 AudioDevice_checkForError(self);
86 int AudioDevice_framesPerBuffer(AudioDevice *self)
88 return FRAMES_PER_BUFFER;
91 void AudioDevice_terminate(AudioDevice *self)
93 Pa_Terminate();
96 void AudioDevice_isListening_(AudioDevice *self, int v)
98 self->isListening = v;
101 int AudioDevice_isListening(AudioDevice *self)
103 return self->isListening;
106 void AudioDevice_openForReadingAndWriting(AudioDevice *self)
108 AudioDevice_isListening_(self, 1);
109 AudioDevice_open(self);
112 void AudioDevice_open(AudioDevice *self)
114 if (!self->stream)
116 self->err = Pa_OpenDefaultStream(
117 &(self->stream),
118 self->isListening ? INPUT_CHANNELS : 0, /* input channels */
119 2, /* stereo output */
120 paFloat32,
121 44100, /* sample rate */
122 FRAMES_PER_BUFFER, /* frames per buffer */
123 //0, /* number of buffers, if zero then use default minimum */
124 /*AudioDevice_callbackInputTest, */
125 AudioDevice_callback,
126 (void *)self
127 ); /* pass our data through to callback */
128 AudioDevice_checkForError(self);
129 //printf("opening self->needsData = 1\n");
130 self->needsData = 1;
134 inline int AudioDevice_isOpen(AudioDevice *self)
136 return (self->stream != NULL);
139 void AudioDevice_close(AudioDevice *self)
141 if (AudioDevice_isOpen(self))
143 self->err = Pa_CloseStream( self->stream );
144 self->stream = NULL;
145 AudioDevice_checkForError(self);
149 void AudioDevice_checkForError(AudioDevice *self)
151 if (self->err != paNoError)
153 AudioDevice_printError(self);
157 const char *AudioDevice_error(AudioDevice *self)
159 return self->err ? Pa_GetErrorText(self->err) : NULL;
162 void AudioDevice_printError(AudioDevice *self)
164 printf("AudioDevice error: %s\n", AudioDevice_error(self));
167 void AudioDevice_start(AudioDevice *self)
169 if (!AudioDevice_isOpen(self))
171 AudioDevice_open(self);
174 if (AudioDevice_isOpen(self) && !AudioDevice_isActive(self))
176 self->err = Pa_StartStream( self->stream );
177 AudioDevice_checkForError(self);
181 void AudioDevice_stop(AudioDevice *self)
183 if (AudioDevice_isOpen(self) && AudioDevice_isActive(self))
185 self->err = Pa_StopStream( self->stream );
186 AudioDevice_checkForError(self);
190 int AudioDevice_isActive(AudioDevice *self)
192 return AudioDevice_isOpen(self) ? Pa_IsStreamActive( self->stream ) : 0;
195 int AudioDevice_streamTime(AudioDevice *self)
197 return AudioDevice_isOpen(self) ? Pa_GetStreamTime( self->stream ) : 0;
200 double AudioDevice_cpuLoad(AudioDevice *self)
202 return AudioDevice_isOpen(self) ? Pa_GetStreamCpuLoad( self->stream ) : 0;
205 int AudioDevice_callbackTest(
206 void *inputBuffer,
207 void *outputBuffer,
208 unsigned long framesPerBuffer,
209 PaTimestamp outTime,
210 void *userData)
212 unsigned long frame;
213 float *out = (float *)outputBuffer;
215 for (frame = 0; frame < framesPerBuffer; frame++)
217 double k = frame + outTime;
218 float a = sin((k * 4 * 261.6) / 44100.0);
219 out[frame*2+0] = a;
220 out[frame*2+1] = 0.0;
223 return 0;
226 int AudioDevice_callbackInputTest(
227 void *inputBuffer,
228 void *outputBuffer,
229 unsigned long framesPerBuffer,
230 PaTimestamp outTime,
231 void *userData)
233 unsigned long frame;
234 float *in = (float *)inputBuffer;
235 float *out = (float *)outputBuffer;
237 for (frame = 0; frame < framesPerBuffer; frame++)
239 out[frame*2+0] = in[frame];
240 out[frame*2+1] = in[frame];
243 return 0;
246 unsigned long AudioDevice_bytesPerFrame(AudioDevice *self)
248 return sizeof(float)*2;
251 unsigned long AudioDevice_framesInWriteBuffer(AudioDevice *self)
253 return UArray_size(self->writeBuffer)/AudioDevice_bytesPerFrame(self);
256 int AudioDevice_callback(
257 void *inputBuffer,
258 void *outputBuffer,
259 unsigned long framesPerBuffer,
260 PaTimestamp outTime,
261 void *userData)
263 AudioDevice *self = (AudioDevice *)userData;
264 self->writeBufferIsEmpty = 0;
266 //printf("AudioDevice_callback\n");
268 if (self->isFreed)
270 printf("AudioDevice: auto stop portaudio stream\n");
271 return -1;
272 } /* return non zero to stop stream */
274 memset(outputBuffer, 0, framesPerBuffer*2*4);
276 AudioDevice_lock(self);
278 /* --- speaker output ----------------------- */
280 if (UArray_size(self->writeBuffer) == 0)
282 AudioDevice_swapWriteBuffers(self);
285 if (UArray_size(self->writeBuffer))
287 float *out = (float *)outputBuffer;
288 /*int writeFrames = AudioDevice_framesInWriteBuffer(self);*/
289 float *buf = (float *)UArray_bytes(self->writeBuffer);
290 int outFrame = 0;
292 for (;;)
294 int outFramesLeft = framesPerBuffer - outFrame;
295 int writeFramesLeft = AudioDevice_framesInWriteBuffer(self) - self->writeFrame;
296 //printf("outFramesLeft = %i\n", outFramesLeft);
298 if (writeFramesLeft < outFramesLeft) /* out > in */
300 memcpy(out + (outFrame*2), buf + (self->writeFrame*2), writeFramesLeft*2*4);
302 AudioDevice_swapWriteBuffers(self);
303 buf = (float *)UArray_bytes(self->writeBuffer);
304 outFrame += writeFramesLeft;
306 if (AudioDevice_framesInWriteBuffer(self) == 0)
308 //memset(out + (outFrame*2), 0, outFramesLeft*2*4);
309 //printf("AudioDevice warning: empty buffer ---------------------------------------\n");
310 self->writeBufferIsEmpty = 1;
311 break;
314 else /* in > out */
316 memcpy(out + (outFrame*2), buf + (self->writeFrame*2), outFramesLeft*2*4);
317 self->writeFrame += outFramesLeft;
318 break;
322 else
324 self->writeBufferIsEmpty = 1;
328 /* --- mic input ----------------------- */
330 if (inputBuffer && self->isListening)
332 unsigned long frame = framesPerBuffer;
333 float *input = inputBuffer;
334 float *buf;
336 if (self->readFrame > self->maxReadFrame)
338 self->readFrame = 0;
341 UArray_setSize_(self->readBuffer,
342 (self->readFrame + framesPerBuffer) * sizeof(float) /*bytes */ * 2 /* channels */);
344 buf = (float *)UArray_bytes(self->readBuffer);
346 buf += self->readFrame * 2;
348 // map mono mic input to stereo output
350 while (frame)
352 *buf = *input; buf++;
353 *buf = *input; buf++;
354 input++;
355 frame--;
357 self->readFrame += framesPerBuffer;
361 AudioDevice_unlock(self);
362 return 0;
365 int AudioDevice_swapWriteBuffers(AudioDevice *self)
367 /* clear the current buffer */
368 UArray_setSize_(self->writeBuffer, 0);
369 self->writeFrame = 0;
371 /* swap if the next one has data */
372 if (UArray_size(self->nextWriteBuffer))
374 void *b = self->writeBuffer;
375 self->writeBuffer = self->nextWriteBuffer;
376 self->nextWriteBuffer = b;
377 //printf("swapping buffers self->needsData = 1\n");
378 self->needsData = 1;
381 return 0;
384 int AudioDevice_swapReadBuffers(AudioDevice *self)
386 int didSwap = 0;
388 if (UArray_size(self->readBuffer))
390 /* clear the next buffer */
391 UArray_setSize_(self->nextReadBuffer, 0);
392 self->readFrame = 0;
394 /* swap */
396 void *b = self->readBuffer;
397 self->readBuffer = self->nextReadBuffer;
398 self->nextReadBuffer = b;
400 didSwap = 1;
403 return didSwap;
406 void AudioDevice_clearBuffers(AudioDevice *self)
408 AudioDevice_lock(self);
409 UArray_setSize_(self->readBuffer, 0);
410 UArray_setSize_(self->nextReadBuffer, 0);
411 AudioDevice_unlock(self);
414 /* --- called from the outside --- */
416 void AudioDevice_writeData_length_(AudioDevice *self, uint8_t *data, size_t numBytes)
418 self->writeBufferIsEmpty = 0;
419 AudioDevice_lock(self);
420 UArray_appendBytes_size_(self->nextWriteBuffer, data, numBytes);
421 self->needsData = 0;
422 //printf("writting self->needsData = 0\n");
423 AudioDevice_unlock(self);
424 AudioDevice_start(self);
427 void AudioDevice_write_(AudioDevice *self, UArray *buf)
429 AudioDevice_writeData_length_(self, UArray_bytes(buf), UArray_size(buf));
432 UArray *AudioDevice_read(AudioDevice *self)
434 AudioDevice_start(self);
435 AudioDevice_lock(self);
436 AudioDevice_swapReadBuffers(self);
437 AudioDevice_unlock(self);
438 return self->nextReadBuffer;