diff -Naurp openal-20050504/linux/src/alc/alc_context.c openal-20050504.alsa/linux/src/alc/alc_context.c --- openal-20050504/linux/src/alc/alc_context.c 2005-04-16 09:59:00.000000000 -0700 +++ openal-20050504.alsa/linux/src/alc/alc_context.c 2005-05-04 16:08:59.545667426 -0700 @@ -1516,6 +1516,8 @@ AL_context *_alcGetDevicesContext(ALCdev return deviceHandle->cc; } +ALint __alcGetAvailableSamples(ALvoid); + void alcGetIntegerv( ALCdevice *deviceHandle, ALCenum token, ALCsizei size , ALCint *dest ) { @@ -1537,6 +1539,9 @@ void alcGetIntegerv( ALCdevice *deviceHa time. Check size */ + case 0x312: /*ALC_CAPTURE_SAMPLES:*/ + *dest = __alcGetAvailableSamples(); + break; case ALC_MAJOR_VERSION: *dest = 1; break; diff -Naurp openal-20050504/linux/src/al_ext.c openal-20050504.alsa/linux/src/al_ext.c --- openal-20050504/linux/src/al_ext.c 2005-04-11 06:51:11.000000000 -0700 +++ openal-20050504.alsa/linux/src/al_ext.c 2005-05-04 16:12:25.886325706 -0700 @@ -998,5 +998,10 @@ ALenum alGetEnumValue( const ALubyte *en return AL_ILLEGAL_COMMAND; } #endif + + if (ustrcmp("ALC_CAPTURE_SAMPLES", ename) == 0) { + return 0x312; + } + return 0; } diff -Naurp openal-20050504/linux/src/al_main.c openal-20050504.alsa/linux/src/al_main.c --- openal-20050504/linux/src/al_main.c 2005-03-25 02:48:23.000000000 -0800 +++ openal-20050504.alsa/linux/src/al_main.c 2005-05-04 16:08:59.544667603 -0700 @@ -137,6 +137,7 @@ ALboolean _alInit( void ) { #ifdef CAPTURE_SUPPORT _alRegisterExtensionGroup( (const ALubyte*) "AL_EXT_capture" ); + _alRegisterExtensionGroup( (const ALubyte*) "ALC_EXT_capture" ); #endif /* CAPTURE_SUPPORT */ #endif /* BUILTIN_EXT_LOKI */ diff -Naurp openal-20050504/linux/src/extensions/al_ext_capture.c openal-20050504.alsa/linux/src/extensions/al_ext_capture.c --- openal-20050504/linux/src/extensions/al_ext_capture.c 2005-03-31 03:22:11.000000000 -0800 +++ openal-20050504.alsa/linux/src/extensions/al_ext_capture.c 2005-05-04 16:40:33.787670845 -0700 @@ -45,6 +45,11 @@ struct { ALubyte *name; void *addr; } al AL_EXT_PAIR(alCaptureStop_EXT), AL_EXT_PAIR(alCaptureGetData_EXT), AL_EXT_PAIR(alCaptureDestroy_EXT), + AL_EXT_PAIR(alcCaptureOpenDevice), + AL_EXT_PAIR(alcCaptureCloseDevice), + AL_EXT_PAIR(alcCaptureStart), + AL_EXT_PAIR(alcCaptureStop), + AL_EXT_PAIR(alcCaptureSamples), { NULL, NULL } }; @@ -72,8 +77,8 @@ void alFiniCapture(void) { return; } -ALboolean alCaptureInit_EXT( UNUSED(ALenum format), - UNUSED(ALuint rate), +ALboolean alCaptureInit_EXT( ALenum format, + ALuint rate, UNUSED(ALsizei bufferSize) ) { ALuint cid; @@ -89,9 +94,27 @@ ALboolean alCaptureInit_EXT( UNUSED(ALen capture_device = cc->read_device; if ( capture_device == NULL ) { char spec[1024]; - char *fmt="'( (direction \"read\") (sampling-rate %d))"; + int speakers; + char *fmt="'( (direction \"read\") (sampling-rate %d) (speaker-num %d) )"; + + switch (format) { + case AL_FORMAT_MONO8: + case AL_FORMAT_MONO16: + default: + speakers = 1; + break; + case AL_FORMAT_STEREO8: + case AL_FORMAT_STEREO16: + speakers = 2; + break; + case AL_FORMAT_QUAD8_LOKI: + case AL_FORMAT_QUAD16_LOKI: + speakers = 4; + break; + } + + snprintf(spec, sizeof(spec), fmt, rate, speakers); - snprintf(spec, sizeof(spec), fmt, rate); capture_device = alcOpenDevice((ALubyte *)spec); if ( capture_device ) { _alcSetContext(NULL, cid, capture_device); @@ -189,8 +212,8 @@ ALsizei alCaptureGetData_EXT( UNUSED(ALv AL_TRUE); } else { /* Hmm, zero size in record.. */ - memset(temp, 0, n); - size = n; + /*memset(temp, 0, n); */ + size = 0; } if(temp == NULL) { fprintf(stderr, "could not canonize data\n"); @@ -203,3 +226,226 @@ ALsizei alCaptureGetData_EXT( UNUSED(ALv } return size; } + + +/* Hacked in ALC_EXT_capture support. --ryan. */ +/* This doesn't support multiple devices, device enumeration, or capture */ +/* devices seperate from an existing context. How painful. */ + +/* ring buffer functionality... */ + +typedef struct +{ + ALubyte *buffer; + ALsizei size; + ALsizei write; + ALsizei read; + ALsizei used; +} __ALRingBuffer; + +static ALboolean __alRingBufferInit(__ALRingBuffer *ring, ALsizei size); +static ALvoid __alRingBufferShutdown(__ALRingBuffer *ring); +static ALsizei __alRingBufferSize(__ALRingBuffer *ring); +static ALvoid __alRingBufferPut(__ALRingBuffer *ring, ALubyte *data, ALsizei size); +static ALsizei __alRingBufferGet(__ALRingBuffer *ring, ALubyte *data, ALsizei size); + +static __ALRingBuffer captureRing; + +static ALboolean __alRingBufferInit(__ALRingBuffer *ring, ALsizei size) +{ + ALubyte *ptr = (ALubyte *) realloc(ring->buffer, size); + if (ptr == NULL) + return(AL_FALSE); + + ring->buffer = ptr; + ring->size = size; + ring->write = 0; + ring->read = 0; + ring->used = 0; + return(AL_TRUE); +} /* __alRingBufferInit */ + +static ALvoid __alRingBufferShutdown(__ALRingBuffer *ring) +{ + free(ring->buffer); + ring->buffer = NULL; +} /* __alRingBufferShutdown */ + +static ALsizei __alRingBufferSize(__ALRingBuffer *ring) +{ + return(ring->used); +} /* __alRingBufferSize */ + +static ALvoid __alRingBufferPut(__ALRingBuffer *ring, ALubyte *data, ALsizei _size) +{ + register ALsizei size = _size; + register ALsizei cpy; + register ALsizei avail; + + if (!size) /* just in case... */ + return; + + /* Putting more data than ring buffer holds in total? Replace it all. */ + if (size > ring->size) + { + ring->write = 0; + ring->read = 0; + ring->used = ring->size; + memcpy(ring->buffer, data + (size - ring->size), ring->size); + return; + } /* if */ + + /* Buffer overflow? Push read pointer to oldest sample not overwritten. */ + avail = ring->size - ring->used; + if (size > avail) + { + ring->read += size - avail; + if (ring->read > ring->size) + ring->read -= ring->size; + } /* if */ + + /* Clip to end of buffer and copy first block... */ + cpy = ring->size - ring->write; + if (size < cpy) + cpy = size; + if (cpy) memcpy(ring->buffer + ring->write, data, cpy); + + /* Wrap around to front of ring buffer and copy remaining data... */ + avail = size - cpy; + if (avail) memcpy(ring->buffer, data + cpy, avail); + + /* Update write pointer... */ + ring->write += size; + if (ring->write > ring->size) + ring->write -= ring->size; + + ring->used += size; + if (ring->used > ring->size) + ring->used = ring->size; +} /* __alRingBufferPut */ + +static ALsizei __alRingBufferGet(__ALRingBuffer *ring, ALubyte *data, ALsizei _size) +{ + register ALsizei cpy; + register ALsizei size = _size; + register ALsizei avail = ring->used; + + /* Clamp amount to read to available data... */ + if (size > avail) + size = avail; + + /* Clip to end of buffer and copy first block... */ + cpy = ring->size - ring->read; + if (cpy > size) cpy = size; + if (cpy) memcpy(data, ring->buffer + ring->read, cpy); + + /* Wrap around to front of ring buffer and copy remaining data... */ + avail = size - cpy; + if (avail) memcpy(data + cpy, ring->buffer, avail); + + /* Update read pointer... */ + ring->read += size; + if (ring->read > ring->size) + ring->read -= ring->size; + + ring->used -= size; + + return(size); /* may have been clamped if there wasn't enough data... */ +} /* __alRingBufferGet */ + +static ALenum captureFmt = AL_NONE; +static ALuint captureFreq = 0; +static ALint captureFmtSize = 0; + +ALCdevice *alcCaptureOpenDevice(const ALubyte *deviceName, + ALuint freq, ALenum fmt, + ALsizei bufsize) +{ + ALCdevice *retval; + AL_context *cc; + ALuint cid; + + if (deviceName != NULL) /* !!! FIXME */ + return NULL; + + switch (fmt) /* try to keep this sane for now... */ + { + case AL_FORMAT_MONO8: + case AL_FORMAT_MONO16: + case AL_FORMAT_STEREO8: + case AL_FORMAT_STEREO16: + break; /* okay format. */ + + default: + return(NULL); + } + + captureFmt = fmt; + captureFreq = freq; + captureFmtSize = (_al_formatbits(fmt) / 8); + if ((fmt == AL_FORMAT_STEREO8) || (fmt == AL_FORMAT_STEREO16)) + captureFmtSize *= 2; + + bufsize *= captureFmtSize; + + if (!__alRingBufferInit(&captureRing, bufsize)) + return NULL; + + if (!alCaptureInit_EXT(fmt, freq, bufsize)) + return NULL; + + cid = _alcCCId; + _alcLockContext( cid ); + cc = _alcGetContext(cid); + retval = cc->read_device; + retval->cc = cc; + _alcUnlockContext( cid ); + + fprintf(stderr, "WARNING: ALC_EXT_capture is subject to change!\n"); + + return(retval); +} + +ALvoid alcCaptureCloseDevice(ALCdevice *dev) +{ + if (dev == NULL) + return; + + alCaptureDestroy_EXT(); + __alRingBufferShutdown(&captureRing); +} + +ALvoid alcCaptureStart(void) +{ + alCaptureStart_EXT(); +} + +ALvoid alcCaptureStop(void) +{ + alCaptureStop_EXT(); +} + +/* !!! FIXME: Not ideal; reads samples in ALC_CAPTURE_SAMPLES query */ +/* !!! FIXME: should query hardware here and do read in alcCaptureSamples() */ +ALint __alcGetAvailableSamples(ALvoid) +{ + static ALubyte buf[2048]; + ALsizei got; + + while ((got = alCaptureGetData_EXT(buf, sizeof (buf), + captureFmt, captureFreq)) > 0) + __alRingBufferPut(&captureRing, buf, got); + /*printf("got %d have %d\n", (int) got, (int) (__alRingBufferSize(&captureRing) / captureFmtSize));*/ + + return(__alRingBufferSize(&captureRing) / captureFmtSize); +} + + +ALvoid alcCaptureSamples(UNUSED(ALCdevice *device), ALvoid *buf, ALsizei samps) +{ + if ((__alRingBufferSize(&captureRing) / captureFmtSize) < samps) + return; /* !!! FIXME: This is an error condition! */ + + __alRingBufferGet(&captureRing, buf, samps * captureFmtSize); +} + diff -Naurp openal-20050504/linux/src/extensions/al_ext_capture.h openal-20050504.alsa/linux/src/extensions/al_ext_capture.h --- openal-20050504/linux/src/extensions/al_ext_capture.h 2002-03-18 06:41:44.000000000 -0800 +++ openal-20050504.alsa/linux/src/extensions/al_ext_capture.h 2005-05-04 16:08:59.548666897 -0700 @@ -13,6 +13,16 @@ #include +ALCdevice *alcCaptureOpenDevice(const ALubyte *deviceName, + ALuint freq, ALenum fmt, + ALsizei bufsize); +ALvoid alcCaptureCloseDevice(ALCdevice *dev); +ALvoid alcCaptureStart(void); +ALvoid alcCaptureStop(void); +ALint __alcGetAvailableSamples(ALvoid); +ALvoid alcCaptureSamples(ALCdevice *device, ALvoid *buf, ALsizei samps); + + /* * alInitCapture( void ) * @@ -38,7 +48,12 @@ void alFiniCapture( void ); AL_EXT_PAIR(alCaptureStart_EXT), \ AL_EXT_PAIR(alCaptureStop_EXT), \ AL_EXT_PAIR(alCaptureGetData_EXT), \ - AL_EXT_PAIR(alCaptureDestroy_EXT) \ + AL_EXT_PAIR(alCaptureDestroy_EXT), \ + AL_EXT_PAIR(alcCaptureOpenDevice), \ + AL_EXT_PAIR(alcCaptureCloseDevice), \ + AL_EXT_PAIR(alcCaptureStart), \ + AL_EXT_PAIR(alcCaptureStop), \ + AL_EXT_PAIR(alcCaptureSamples) \ /* initialization and destruction functions */