// This should probably move to another c file but for now ... ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize) { ALCboolean DeviceFound = ALC_FALSE; ALCdevice *pDevice = NULL; ALCint i; InitAL(); if(deviceName && !deviceName[0]) deviceName = NULL; pDevice = malloc(sizeof(ALCdevice)); if (pDevice) { if (SampleSize > 0) { //Initialise device structure memset(pDevice, 0, sizeof(ALCdevice)); //Validate device pDevice->InUse = AL_TRUE; pDevice->IsCaptureDevice = AL_TRUE; pDevice->Frequency = frequency; pDevice->Format = format; pDevice->Channels = aluChannelsFromFormat(format); pDevice->FrameSize = aluBytesFromFormat(format) * pDevice->Channels; for(i = 0;BackendList[i].Init;i++) { pDevice->Funcs = &BackendList[i].Funcs; if(ALCdevice_OpenCapture(pDevice, deviceName, frequency, format, SampleSize)) { SuspendContext(NULL); pDevice->next = g_pDeviceList; g_pDeviceList = pDevice; g_ulDeviceCount++; ProcessContext(NULL); DeviceFound = ALC_TRUE; break; } } } else SetALCError(ALC_INVALID_VALUE); if(!DeviceFound) { free(pDevice); pDevice = NULL; } } else SetALCError(ALC_OUT_OF_MEMORY); return pDevice; }
ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples) { if ((pDevice) && (pDevice->IsCaptureDevice)) ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples); else SetALCError(ALC_INVALID_DEVICE); }
/* alcIsExtensionPresent Determines if there is support for a particular extension */ ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName) { ALCboolean bResult = ALC_FALSE; (void)device; if (extName) { const char *ptr; size_t len; len = strlen(extName); ptr = alcExtensionList; while(ptr && *ptr) { if(strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len]))) { bResult = ALC_TRUE; break; } if((ptr=strchr(ptr, ' ')) != NULL) { do { ++ptr; } while(isspace(*ptr)); } } } else SetALCError(ALC_INVALID_VALUE); return bResult; }
/* alcCloseDevice Close the specified Device */ ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice) { ALCboolean bReturn = ALC_FALSE; ALCdevice **list; if ((pDevice)&&(!pDevice->IsCaptureDevice)) { SuspendContext(NULL); list = &g_pDeviceList; while(*list != pDevice) list = &(*list)->next; *list = (*list)->next; g_ulDeviceCount--; ProcessContext(NULL); if(pDevice->Context) alcDestroyContext(pDevice->Context); ALCdevice_ClosePlayback(pDevice); //Release device structure memset(pDevice, 0, sizeof(ALCdevice)); free(pDevice); bReturn = ALC_TRUE; } else SetALCError(ALC_INVALID_DEVICE); return bReturn; }
/* alcMakeContextCurrent Makes the given Context the active Context */ ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context) { ALCcontext *ALContext; ALboolean bReturn = AL_TRUE; SuspendContext(NULL); // context must be a valid Context or NULL if ((IsContext(context)) || (context == NULL)) { if ((ALContext=alcGetCurrentContext())) { SuspendContext(ALContext); ALContext->InUse=AL_FALSE; ProcessContext(ALContext); } if ((ALContext=context) && (ALContext->Device)) { SuspendContext(ALContext); ALContext->InUse=AL_TRUE; ProcessContext(ALContext); } } else { SetALCError(ALC_INVALID_CONTEXT); bReturn = AL_FALSE; } ProcessContext(NULL); return bReturn; }
ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice) { if ((pDevice)&&(pDevice->IsCaptureDevice)) ALCdevice_StopCapture(pDevice); else SetALCError(ALC_INVALID_DEVICE); }
ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice) { ALCboolean bReturn = ALC_FALSE; ALCdevice **list; if ((pDevice)&&(pDevice->IsCaptureDevice)) { SuspendContext(NULL); list = &g_pDeviceList; while(*list != pDevice) list = &(*list)->next; *list = (*list)->next; g_ulDeviceCount--; ProcessContext(NULL); ALCdevice_CloseCapture(pDevice); free(pDevice); bReturn = ALC_TRUE; } else SetALCError(ALC_INVALID_DEVICE); return bReturn; }
static void oss_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples) { oss_data *data = (oss_data*)pDevice->ExtraData; if(lSamples <= (ALCuint)RingBufferSize(data->ring)) ReadRingBuffer(data->ring, pBuffer, lSamples); else SetALCError(ALC_INVALID_VALUE); }
static void pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) //{{{ { pulse_data *data = device->ExtraData; ALCuint available = RingBufferSize(data->ring); if(available < samples) SetALCError(ALC_INVALID_VALUE); else ReadRingBuffer(data->ring, buffer, samples); } //}}}
/* alcGetContextsDevice Returns the Device that a particular Context is attached to */ ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext) { ALCdevice *pDevice = NULL; SuspendContext(NULL); if (IsContext(pContext)) pDevice = pContext->Device; else SetALCError(ALC_INVALID_CONTEXT); ProcessContext(NULL); return pDevice; }
/* alcGetEnumValue Get the value for a particular ALC Enumerated Value */ ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName) { ALsizei i = 0; ALCenum val; (void)device; while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName))) i++; val = enumeration[i].value; if(!enumeration[i].enumName) SetALCError(ALC_INVALID_VALUE); return val; }
/* alcGetProcAddress Retrieves the function address for a particular extension function */ ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName) { ALCvoid *pFunction = NULL; ALsizei i = 0; (void)device; if (funcName) { while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0) i++; pFunction = alcFunctions[i].address; } else SetALCError(ALC_INVALID_VALUE); return pFunction; }
static void WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples) { WinMMData *pData = (WinMMData*)pDevice->ExtraData; ALuint ulSamples = (unsigned long)lSamples; ALuint ulBytes, ulBytesToCopy; ALuint ulCapturedSamples; ALuint ulReadOffset; // Check that we have the requested numbers of Samples ulCapturedSamples = (pData->ulWriteCapturedDataPos - pData->ulReadCapturedDataPos) / pDevice->FrameSize; if(ulSamples > ulCapturedSamples) { SetALCError(ALC_INVALID_VALUE); return; } ulBytes = ulSamples * pDevice->FrameSize; // Get Read Offset ulReadOffset = (pData->ulReadCapturedDataPos % pData->ulCapturedDataSize); // Check for wrap-around condition if ((ulReadOffset + ulBytes) > pData->ulCapturedDataSize) { // Copy data from last Read position to end of data ulBytesToCopy = pData->ulCapturedDataSize - ulReadOffset; memcpy(pBuffer, pData->pCapturedSampleData + ulReadOffset, ulBytesToCopy); // Copy rest of the data from the start of the captured data memcpy(((char *)pBuffer) + ulBytesToCopy, pData->pCapturedSampleData, ulBytes - ulBytesToCopy); } else { // Copy data from the read position in the captured data memcpy(pBuffer, pData->pCapturedSampleData + ulReadOffset, ulBytes); } // Update Read Position pData->ulReadCapturedDataPos += ulBytes; }
/* alcDestroyContext Remove a Context */ ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context) { ALCcontext **list; InitAL(); // Lock context list SuspendContext(NULL); if (IsContext(context)) { // Lock context SuspendContext(context); ReleaseALSources(context); ReleaseALAuxiliaryEffectSlots(context); context->Device->Context = NULL; list = &g_pContextList; while(*list != context) list = &(*list)->next; *list = (*list)->next; g_ulContextCount--; // Unlock context ProcessContext(context); ExitContext(context); // Free memory (MUST do this after ProcessContext) memset(context, 0, sizeof(ALCcontext)); free(context); } else SetALCError(ALC_INVALID_CONTEXT); ProcessContext(NULL); }
static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) { DSBUFFERDESC DSBDescription; DSoundData *pData = NULL; WAVEFORMATEXTENSIBLE OutputType; DWORD frameSize = 0; LPGUID guid = NULL; DWORD speakers; HRESULT hr; if(deviceName) { int i; for(i = 0;DeviceList[i].name;i++) { if(strcmp(deviceName, DeviceList[i].name) == 0) { device->szDeviceName = DeviceList[i].name; if(i > 0) guid = &DeviceList[i].guid; break; } } if(!DeviceList[i].name) return ALC_FALSE; } else device->szDeviceName = DeviceList[0].name; memset(&OutputType, 0, sizeof(OutputType)); //Initialise requested device pData = calloc(1, sizeof(DSoundData)); if(!pData) { SetALCError(ALC_OUT_OF_MEMORY); return ALC_FALSE; } //DirectSound Init code hr = DirectSoundCreate(guid, &pData->lpDS, NULL); if(SUCCEEDED(hr)) hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY); if(SUCCEEDED(hr)) hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers); if(SUCCEEDED(hr)) { speakers = DSSPEAKER_CONFIG(speakers); if(speakers == DSSPEAKER_MONO) { if(aluBytesFromFormat(device->Format) == 1) device->Format = AL_FORMAT_MONO8; else device->Format = AL_FORMAT_MONO16; } else if(speakers == DSSPEAKER_STEREO) { if(aluBytesFromFormat(device->Format) == 1) device->Format = AL_FORMAT_STEREO8; else device->Format = AL_FORMAT_STEREO16; } else if(speakers == DSSPEAKER_QUAD) { if(aluBytesFromFormat(device->Format) == 1) device->Format = AL_FORMAT_QUAD8; else device->Format = AL_FORMAT_QUAD16; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; } else if(speakers == DSSPEAKER_5POINT1) { if(aluBytesFromFormat(device->Format) == 1) device->Format = AL_FORMAT_51CHN8; else device->Format = AL_FORMAT_51CHN16; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; } else if(speakers == DSSPEAKER_7POINT1) { if(aluBytesFromFormat(device->Format) == 1) device->Format = AL_FORMAT_71CHN8; else device->Format = AL_FORMAT_71CHN16; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; } frameSize = aluBytesFromFormat(device->Format) * aluChannelsFromFormat(device->Format); OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; OutputType.Format.nChannels = aluChannelsFromFormat(device->Format); OutputType.Format.wBitsPerSample = aluBytesFromFormat(device->Format) * 8; OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; OutputType.Format.nSamplesPerSec = device->Frequency; OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign; OutputType.Format.cbSize = 0; device->UpdateSize /= DS_FRAGS; } if(OutputType.Format.nChannels > 2) { OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; OutputType.Format.cbSize = 22; OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; } else { if(SUCCEEDED(hr)) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL); } if(SUCCEEDED(hr)) hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType.Format); } if(SUCCEEDED(hr)) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2; DSBDescription.dwBufferBytes=device->UpdateSize * DS_FRAGS * frameSize; DSBDescription.lpwfxFormat=&OutputType.Format; hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL); } if(SUCCEEDED(hr)) hr = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING); device->ExtraData = pData; pData->thread = StartThread(DSoundProc, device); if(!pData->thread) hr = E_FAIL; if(FAILED(hr)) { if (pData->DSsbuffer) IDirectSoundBuffer_Release(pData->DSsbuffer); if (pData->DSpbuffer) IDirectSoundBuffer_Release(pData->DSpbuffer); if (pData->lpDS) IDirectSound_Release(pData->lpDS); free(pData); return ALC_FALSE; } return ALC_TRUE; }
static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize) { WAVEFORMATEX wfexCaptureFormat; WinMMData *pData = NULL; ALint lDeviceID = 0; ALint lBufferSize; ALint i; (void)format; // Find the Device ID matching the deviceName if valid if (deviceName) { for(i = 0;CaptureDeviceList[i];i++) { if (!strcmp(deviceName, CaptureDeviceList[i])) { lDeviceID = i; break; } } if(!CaptureDeviceList[i]) return ALC_FALSE; } pDevice->szDeviceName = CaptureDeviceList[lDeviceID]; pData = calloc(1, sizeof(*pData)); if(!pData) { SetALCError(ALC_OUT_OF_MEMORY); return ALC_FALSE; } memset(&wfexCaptureFormat, 0, sizeof(WAVEFORMATEX)); wfexCaptureFormat.wFormatTag = WAVE_FORMAT_PCM; wfexCaptureFormat.nChannels = pDevice->Channels; wfexCaptureFormat.wBitsPerSample = pDevice->FrameSize / pDevice->Channels * 8; wfexCaptureFormat.nBlockAlign = pDevice->FrameSize; wfexCaptureFormat.nSamplesPerSec = frequency; wfexCaptureFormat.nAvgBytesPerSec = wfexCaptureFormat.nSamplesPerSec * pDevice->FrameSize; wfexCaptureFormat.cbSize = 0; if (waveInOpen(&pData->hWaveInHandle, lDeviceID, &wfexCaptureFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) goto failure; pData->hWaveInHdrEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveInAllHeadersReturned"); if (pData->hWaveInHdrEvent == NULL) goto failure; pData->hWaveInThreadEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveInThreadDestroyed"); if (pData->hWaveInThreadEvent == NULL) goto failure; pData->hWaveInThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveInThreadID); if (pData->hWaveInThread == NULL) goto failure; // Allocate circular memory buffer for the captured audio pData->ulCapturedDataSize = SampleSize * wfexCaptureFormat.nBlockAlign; // Make sure circular buffer is at least 100ms in size (and an exact multiple of // the block alignment if (pData->ulCapturedDataSize < (wfexCaptureFormat.nAvgBytesPerSec / 10)) { pData->ulCapturedDataSize = wfexCaptureFormat.nAvgBytesPerSec / 10; pData->ulCapturedDataSize -= (pData->ulCapturedDataSize % wfexCaptureFormat.nBlockAlign); } pData->pCapturedSampleData = (ALCchar*)malloc(pData->ulCapturedDataSize); pData->lWaveInBuffersCommitted=0; // Create 4 Buffers of 50ms each lBufferSize = wfexCaptureFormat.nAvgBytesPerSec / 20; lBufferSize -= (lBufferSize % wfexCaptureFormat.nBlockAlign); for (i=0;i<4;i++) { memset(&pData->WaveInBuffer[i], 0, sizeof(WAVEHDR)); pData->WaveInBuffer[i].dwBufferLength = lBufferSize; pData->WaveInBuffer[i].lpData = calloc(1,pData->WaveInBuffer[i].dwBufferLength); pData->WaveInBuffer[i].dwFlags = 0; pData->WaveInBuffer[i].dwLoops = 0; waveInPrepareHeader(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR)); waveInAddBuffer(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR)); pData->lWaveInBuffersCommitted++; } pData->ulReadCapturedDataPos = 0; pData->ulWriteCapturedDataPos = 0; pDevice->ExtraData = pData; return ALC_TRUE; failure: if (pData->hWaveInThreadEvent) CloseHandle(pData->hWaveInThreadEvent); if (pData->hWaveInHdrEvent) CloseHandle(pData->hWaveInHdrEvent); if (pData->hWaveInHandle) waveInClose(pData->hWaveInHandle); free(pData); return ALC_FALSE; }
/* alcGetIntegerv Returns information about the Device and the version of Open AL */ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data) { InitAL(); if ((device)&&(device->IsCaptureDevice)) { SuspendContext(NULL); // Capture device switch (param) { case ALC_CAPTURE_SAMPLES: if ((size) && (data)) *data = ALCdevice_AvailableSamples(device); else SetALCError(ALC_INVALID_VALUE); break; default: SetALCError(ALC_INVALID_ENUM); break; } ProcessContext(NULL); } else { if(data) { // Playback Device switch (param) { case ALC_MAJOR_VERSION: if(!size) SetALCError(ALC_INVALID_VALUE); else *data = alcMajorVersion; break; case ALC_MINOR_VERSION: if(!size) SetALCError(ALC_INVALID_VALUE); else *data = alcMinorVersion; break; case ALC_EFX_MAJOR_VERSION: if(!size) SetALCError(ALC_INVALID_VALUE); else *data = alcEFXMajorVersion; break; case ALC_EFX_MINOR_VERSION: if(!size) SetALCError(ALC_INVALID_VALUE); else *data = alcEFXMinorVersion; break; case ALC_MAX_AUXILIARY_SENDS: if(!size) SetALCError(ALC_INVALID_VALUE); else *data = MAX_SENDS; break; case ALC_ATTRIBUTES_SIZE: if(!device) SetALCError(ALC_INVALID_DEVICE); else if(!size) SetALCError(ALC_INVALID_VALUE); else *data = 12; break; case ALC_ALL_ATTRIBUTES: if(!device) SetALCError(ALC_INVALID_DEVICE); else if (size < 7) SetALCError(ALC_INVALID_VALUE); else { int i = 0; data[i++] = ALC_FREQUENCY; data[i++] = device->Frequency; data[i++] = ALC_REFRESH; data[i++] = device->Frequency / device->UpdateSize; data[i++] = ALC_SYNC; data[i++] = ALC_FALSE; SuspendContext(NULL); if(device->Context && size >= 12) { data[i++] = ALC_MONO_SOURCES; data[i++] = device->Context->lNumMonoSources; data[i++] = ALC_STEREO_SOURCES; data[i++] = device->Context->lNumStereoSources; data[i++] = ALC_MAX_AUXILIARY_SENDS; data[i++] = MAX_SENDS; } ProcessContext(NULL); data[i++] = 0; } break; case ALC_FREQUENCY: if(!device) SetALCError(ALC_INVALID_DEVICE); else if(!size) SetALCError(ALC_INVALID_VALUE); else *data = device->Frequency; break; case ALC_REFRESH: if(!device) SetALCError(ALC_INVALID_DEVICE); else if(!size) SetALCError(ALC_INVALID_VALUE); else *data = device->Frequency / device->UpdateSize; break; case ALC_SYNC: if(!device) SetALCError(ALC_INVALID_DEVICE); else if(!size) SetALCError(ALC_INVALID_VALUE); else *data = ALC_FALSE; break; case ALC_MONO_SOURCES: if(!device || !device->Context) SetALCError(ALC_INVALID_DEVICE); else if (size != 1) SetALCError(ALC_INVALID_VALUE); else *data = device->Context->lNumMonoSources; break; case ALC_STEREO_SOURCES: if(!device || !device->Context) SetALCError(ALC_INVALID_DEVICE); else if (size != 1) SetALCError(ALC_INVALID_VALUE); else *data = device->Context->lNumStereoSources; break; default: SetALCError(ALC_INVALID_ENUM); break; } } else if(size) SetALCError(ALC_INVALID_VALUE); } return; }
/* alcGetString Returns information about the Device, and error strings */ ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param) { const ALCchar *value = NULL; InitAL(); switch (param) { case ALC_NO_ERROR: value = alcNoError; break; case ALC_INVALID_ENUM: value = alcErrInvalidEnum; break; case ALC_INVALID_VALUE: value = alcErrInvalidValue; break; case ALC_INVALID_DEVICE: value = alcErrInvalidDevice; break; case ALC_INVALID_CONTEXT: value = alcErrInvalidContext; break; case ALC_OUT_OF_MEMORY: value = alcErrOutOfMemory; break; case ALC_DEFAULT_DEVICE_SPECIFIER: value = alcDefaultDeviceSpecifier; break; case ALC_DEVICE_SPECIFIER: if (pDevice) value = pDevice->szDeviceName; else value = alcDeviceList; break; case ALC_ALL_DEVICES_SPECIFIER: value = alcAllDeviceList; break; case ALC_DEFAULT_ALL_DEVICES_SPECIFIER: value = alcDefaultAllDeviceSpecifier; break; case ALC_CAPTURE_DEVICE_SPECIFIER: if (pDevice) value = pDevice->szDeviceName; else value = alcCaptureDeviceList; break; case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER: value = alcCaptureDefaultDeviceSpecifier; break; case ALC_EXTENSIONS: value = alcExtensionList; break; default: SetALCError(ALC_INVALID_ENUM); break; } return value; }
/* alcCreateContext Create and attach a Context to a particular Device. */ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList) { ALCcontext *ALContext = NULL; ALuint ulAttributeIndex, ulRequestedStereoSources; if ((device)&&(!device->IsCaptureDevice)) { // Reset Context Last Error code g_eLastContextError = ALC_NO_ERROR; // Current implementation only allows one Context per Device if(!device->Context) { ALContext = calloc(1, sizeof(ALCcontext)); if(!ALContext) { SetALCError(ALC_OUT_OF_MEMORY); return NULL; } ALContext->Device = device; InitContext(ALContext); device->Context = ALContext; SuspendContext(NULL); ALContext->next = g_pContextList; g_pContextList = ALContext; g_ulContextCount++; ProcessContext(NULL); // Check for Voice Count attributes if (attrList) { ulAttributeIndex = 0; while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex])) { if (attrList[ulAttributeIndex] == ALC_STEREO_SOURCES) { ulRequestedStereoSources = attrList[ulAttributeIndex + 1]; if (ulRequestedStereoSources > ALContext->Device->MaxNoOfSources) ulRequestedStereoSources = ALContext->Device->MaxNoOfSources; ALContext->lNumStereoSources = ulRequestedStereoSources; ALContext->lNumMonoSources = ALContext->Device->MaxNoOfSources - ALContext->lNumStereoSources; break; } ulAttributeIndex += 2; } } } else { SetALCError(ALC_INVALID_VALUE); ALContext = NULL; } } else SetALCError(ALC_INVALID_DEVICE); return ALContext; }
/* alcOpenDevice Open the Device specified. */ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName) { ALboolean bDeviceFound = AL_FALSE; ALCdevice *device; ALint i; InitAL(); if(deviceName && !deviceName[0]) deviceName = NULL; device = malloc(sizeof(ALCdevice)); if (device) { const char *fmt; //Initialise device structure memset(device, 0, sizeof(ALCdevice)); //Validate device device->IsCaptureDevice = AL_FALSE; //Set output format device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE); if((ALint)device->Frequency <= 0) device->Frequency = SWMIXER_OUTPUT_RATE; fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16"); if(fmt[0]) device->Format = alGetEnumValue(fmt); if(!aluChannelsFromFormat(device->Format)) device->Format = AL_FORMAT_STEREO16; device->UpdateSize = GetConfigValueInt(NULL, "refresh", 4096); if((ALint)device->UpdateSize <= 0) device->UpdateSize = 4096; device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256); if((ALint)device->MaxNoOfSources <= 0) device->MaxNoOfSources = 256; // Find a playback device to open for(i = 0;BackendList[i].Init;i++) { device->Funcs = &BackendList[i].Funcs; if(ALCdevice_OpenPlayback(device, deviceName)) { SuspendContext(NULL); device->next = g_pDeviceList; g_pDeviceList = device; g_ulDeviceCount++; ProcessContext(NULL); bDeviceFound = AL_TRUE; break; } } if (!bDeviceFound) { // No suitable output device found SetALCError(ALC_INVALID_VALUE); free(device); device = NULL; } } else SetALCError(ALC_OUT_OF_MEMORY); return device; }