static ALCenum WinMMOpenPlayback(ALCdevice *Device, const ALCchar *deviceName) { WinMMData *data = NULL; const al_string *iter, *end; UINT DeviceID; MMRESULT res; if(VECTOR_SIZE(PlaybackDevices) == 0) ProbePlaybackDevices(); // Find the Device ID matching the deviceName if valid iter = VECTOR_ITER_BEGIN(PlaybackDevices); end = VECTOR_ITER_END(PlaybackDevices); for(; iter != end; iter++) { if(!al_string_empty(*iter) && (!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0)) { DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(PlaybackDevices)); break; } } if(iter == end) return ALC_INVALID_VALUE; data = calloc(1, sizeof(*data)); if(!data) return ALC_OUT_OF_MEMORY; Device->ExtraData = data; retry_open: memset(&data->Format, 0, sizeof(WAVEFORMATEX)); if(Device->FmtType == DevFmtFloat) { data->Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; data->Format.wBitsPerSample = 32; } else { data->Format.wFormatTag = WAVE_FORMAT_PCM; if(Device->FmtType == DevFmtUByte || Device->FmtType == DevFmtByte) data->Format.wBitsPerSample = 8; else data->Format.wBitsPerSample = 16; } data->Format.nChannels = ((Device->FmtChans == DevFmtMono) ? 1 : 2); data->Format.nBlockAlign = data->Format.wBitsPerSample * data->Format.nChannels / 8; data->Format.nSamplesPerSec = Device->Frequency; data->Format.nAvgBytesPerSec = data->Format.nSamplesPerSec * data->Format.nBlockAlign; data->Format.cbSize = 0; if((res=waveOutOpen(&data->WaveHandle.Out, DeviceID, &data->Format, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)Device, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR) { if(Device->FmtType == DevFmtFloat) { Device->FmtType = DevFmtShort; goto retry_open; } ERR("waveOutOpen failed: %u\n", res); goto failure; } al_string_copy(&Device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID)); return ALC_NO_ERROR; failure: if(data->WaveHandle.Out) waveOutClose(data->WaveHandle.Out); free(data); Device->ExtraData = NULL; return ALC_INVALID_VALUE; }
static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName) { const al_string *iter, *end; ALbyte *BufferData = NULL; DWORD CapturedDataSize; WinMMData *data = NULL; ALint BufferSize; UINT DeviceID; MMRESULT res; ALuint i; if(VECTOR_SIZE(CaptureDevices) == 0) ProbeCaptureDevices(); // Find the Device ID matching the deviceName if valid iter = VECTOR_ITER_BEGIN(CaptureDevices); end = VECTOR_ITER_END(CaptureDevices); for(; iter != end; iter++) { if(!al_string_empty(*iter) && (!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0)) { DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(CaptureDevices)); break; } } if(iter == end) return ALC_INVALID_VALUE; switch(Device->FmtChans) { case DevFmtMono: case DevFmtStereo: break; case DevFmtQuad: case DevFmtX51: case DevFmtX51Side: case DevFmtX61: case DevFmtX71: return ALC_INVALID_ENUM; } switch(Device->FmtType) { case DevFmtUByte: case DevFmtShort: case DevFmtInt: case DevFmtFloat: break; case DevFmtByte: case DevFmtUShort: case DevFmtUInt: return ALC_INVALID_ENUM; } data = calloc(1, sizeof(*data)); if(!data) return ALC_OUT_OF_MEMORY; Device->ExtraData = data; memset(&data->Format, 0, sizeof(WAVEFORMATEX)); data->Format.wFormatTag = ((Device->FmtType == DevFmtFloat) ? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM); data->Format.nChannels = ChannelsFromDevFmt(Device->FmtChans); data->Format.wBitsPerSample = BytesFromDevFmt(Device->FmtType) * 8; data->Format.nBlockAlign = data->Format.wBitsPerSample * data->Format.nChannels / 8; data->Format.nSamplesPerSec = Device->Frequency; data->Format.nAvgBytesPerSec = data->Format.nSamplesPerSec * data->Format.nBlockAlign; data->Format.cbSize = 0; if((res=waveInOpen(&data->WaveHandle.In, DeviceID, &data->Format, (DWORD_PTR)&WaveInProc, (DWORD_PTR)Device, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR) { ERR("waveInOpen failed: %u\n", res); goto failure; } // Allocate circular memory buffer for the captured audio CapturedDataSize = Device->UpdateSize*Device->NumUpdates; // Make sure circular buffer is at least 100ms in size if(CapturedDataSize < (data->Format.nSamplesPerSec / 10)) CapturedDataSize = data->Format.nSamplesPerSec / 10; data->Ring = CreateRingBuffer(data->Format.nBlockAlign, CapturedDataSize); if(!data->Ring) goto failure; InitRef(&data->WaveBuffersCommitted, 0); // Create 4 Buffers of 50ms each BufferSize = data->Format.nAvgBytesPerSec / 20; BufferSize -= (BufferSize % data->Format.nBlockAlign); BufferData = calloc(4, BufferSize); if(!BufferData) goto failure; for(i = 0; i < 4; i++) { memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR)); data->WaveBuffer[i].dwBufferLength = BufferSize; data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData : (data->WaveBuffer[i-1].lpData + data->WaveBuffer[i-1].dwBufferLength)); data->WaveBuffer[i].dwFlags = 0; data->WaveBuffer[i].dwLoops = 0; waveInPrepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR)); waveInAddBuffer(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR)); IncrementRef(&data->WaveBuffersCommitted); } if(althrd_create(&data->thread, CaptureThreadProc, Device) != althrd_success) goto failure; al_string_copy(&Device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID)); return ALC_NO_ERROR; failure: if(BufferData) { for(i = 0; i < 4; i++) waveInUnprepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR)); free(BufferData); } if(data->Ring) DestroyRingBuffer(data->Ring); if(data->WaveHandle.In) waveInClose(data->WaveHandle.In); free(data); Device->ExtraData = NULL; return ALC_INVALID_VALUE; }
static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALuint speakermap[MAX_OUTPUT_CHANNELS]) { ALuint i; for(i = 0;i < conf->NumSpeakers;i++) { int c = -1; /* NOTE: AmbDec does not define any standard speaker names, however * for this to work we have to by able to find the output channel * the speaker definition corresponds to. Therefore, OpenAL Soft * requires these channel labels to be recognized: * * LF = Front left * RF = Front right * LS = Side left * RS = Side right * LB = Back left * RB = Back right * CE = Front center * CB = Back center * * Additionally, surround51 will acknowledge back speakers for side * channels, and surround51rear will acknowledge side speakers for * back channels, to avoid issues with an ambdec expecting 5.1 to * use the side channels when the device is configured for back, * and vice-versa. */ if(al_string_cmp_cstr(conf->Speakers[i].Name, "LF") == 0) c = GetChannelIdxByName(device->RealOut, FrontLeft); else if(al_string_cmp_cstr(conf->Speakers[i].Name, "RF") == 0) c = GetChannelIdxByName(device->RealOut, FrontRight); else if(al_string_cmp_cstr(conf->Speakers[i].Name, "CE") == 0) c = GetChannelIdxByName(device->RealOut, FrontCenter); else if(al_string_cmp_cstr(conf->Speakers[i].Name, "LS") == 0) { if(device->FmtChans == DevFmtX51Rear) c = GetChannelIdxByName(device->RealOut, BackLeft); else c = GetChannelIdxByName(device->RealOut, SideLeft); } else if(al_string_cmp_cstr(conf->Speakers[i].Name, "RS") == 0) { if(device->FmtChans == DevFmtX51Rear) c = GetChannelIdxByName(device->RealOut, BackRight); else c = GetChannelIdxByName(device->RealOut, SideRight); } else if(al_string_cmp_cstr(conf->Speakers[i].Name, "LB") == 0) { if(device->FmtChans == DevFmtX51) c = GetChannelIdxByName(device->RealOut, SideLeft); else c = GetChannelIdxByName(device->RealOut, BackLeft); } else if(al_string_cmp_cstr(conf->Speakers[i].Name, "RB") == 0) { if(device->FmtChans == DevFmtX51) c = GetChannelIdxByName(device->RealOut, SideRight); else c = GetChannelIdxByName(device->RealOut, BackRight); } else if(al_string_cmp_cstr(conf->Speakers[i].Name, "CB") == 0) c = GetChannelIdxByName(device->RealOut, BackCenter); else { const char *name = al_string_get_cstr(conf->Speakers[i].Name); unsigned int n; char ch; if(sscanf(name, "AUX%u%c", &n, &ch) == 1 && n < 16) c = GetChannelIdxByName(device->RealOut, Aux0+n); else { ERR("AmbDec speaker label \"%s\" not recognized\n", name); return false; } } if(c == -1) { ERR("Failed to lookup AmbDec speaker label %s\n", al_string_get_cstr(conf->Speakers[i].Name)); return false; } speakermap[i] = c; } return true; }