ALCboolean alc_oss_init(BackendFuncs *func_list) { ConfigValueStr("oss", "device", &oss_driver); ConfigValueStr("oss", "capture", &oss_capture); *func_list = oss_funcs; return ALC_TRUE; }
ALCboolean alc_solaris_init(BackendFuncs *func_list) { ConfigValueStr("solaris", "device", &solaris_driver); *func_list = solaris_funcs; return ALC_TRUE; }
static ALCenum alsa_open_playback(ALCdevice *device, const ALCchar *deviceName) { const char *driver = "default"; alsa_data *data; char str[128]; int i; ConfigValueStr("alsa", "device", &driver); if(!deviceName) deviceName = alsaDevice; else if(strcmp(deviceName, alsaDevice) != 0) { size_t idx; if(!allDevNameMap) allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames); for(idx = 0;idx < numDevNames;idx++) { if(allDevNameMap[idx].name && strcmp(deviceName, allDevNameMap[idx].name) == 0) { if(idx > 0) { snprintf(str, sizeof(str), "%sCARD=%s,DEV=%d", device_prefix, allDevNameMap[idx].card, allDevNameMap[idx].dev); driver = str; } break; } } if(idx == numDevNames) return ALC_INVALID_VALUE; } data = (alsa_data*)calloc(1, sizeof(alsa_data)); i = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if(i >= 0) { i = snd_pcm_nonblock(data->pcmHandle, 0); if(i < 0) snd_pcm_close(data->pcmHandle); } if(i < 0) { free(data); ERR("Could not open playback device '%s': %s\n", driver, snd_strerror(i)); return ALC_OUT_OF_MEMORY; } device->szDeviceName = strdup(deviceName); device->ExtraData = data; return ALC_NO_ERROR; }
ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context) { ALCdevice *device = context->Device; al_string fname = AL_STRING_INIT_STATIC(); const char *namelist; if(device->DefaultSfont) return device->DefaultSfont; device->DefaultSfont = calloc(1, sizeof(device->DefaultSfont[0])); ALsoundfont_Construct(device->DefaultSfont); namelist = getenv("ALSOFT_SOUNDFONT"); if(!namelist || !namelist[0]) ConfigValueStr("midi", "soundfont", &namelist); while(namelist && namelist[0]) { const char *next, *end; FILE *f; while(*namelist && (isspace(*namelist) || *namelist == ',')) namelist++; if(!*namelist) break; next = strchr(namelist, ','); end = next ? next++ : (namelist+strlen(namelist)); while(--end != namelist && isspace(*end)) { } if(end == namelist) continue; al_string_append_range(&fname, namelist, end+1); namelist = next; f = OpenDataFile(al_string_get_cstr(fname), "openal/soundfonts"); if(f == NULL) ERR("Failed to open %s\n", al_string_get_cstr(fname)); else { Reader reader; reader.cb = ALsoundfont_read; reader.ptr = f; reader.error = 0; TRACE("Loading %s\n", al_string_get_cstr(fname)); loadSf2(&reader, device->DefaultSfont, context); fclose(f); } al_string_clear(&fname); } AL_STRING_DEINIT(fname); return device->DefaultSfont; }
static struct Hrtf *LoadHrtf(ALuint deviceRate) { const char *fnamelist = NULL; if(!ConfigValueStr(NULL, "hrtf_tables", &fnamelist)) return NULL; while(*fnamelist != '\0') { struct Hrtf *Hrtf = NULL; char fname[PATH_MAX]; ALchar magic[8]; ALuint i; FILE *f; while(isspace(*fnamelist) || *fnamelist == ',') fnamelist++; i = 0; while(*fnamelist != '\0' && *fnamelist != ',') { const char *next = strpbrk(fnamelist, "%,"); while(fnamelist != next && *fnamelist && i < sizeof(fname)) fname[i++] = *(fnamelist++); if(!next || *next == ',') break; /* *next == '%' */ next++; if(*next == 'r') { int wrote = snprintf(&fname[i], sizeof(fname)-i, "%u", deviceRate); i += minu(wrote, sizeof(fname)-i); next++; } else if(*next == '%') { if(i < sizeof(fname)) fname[i++] = '%'; next++; } else ERR("Invalid marker '%%%c'\n", *next); fnamelist = next; } i = minu(i, sizeof(fname)-1); fname[i] = '\0'; while(i > 0 && isspace(fname[i-1])) i--; fname[i] = '\0'; if(fname[0] == '\0') continue; TRACE("Loading %s...\n", fname); f = fopen(fname, "rb"); if(f == NULL) { ERR("Could not open %s\n", fname); continue; } if(fread(magic, 1, sizeof(magic), f) != sizeof(magic)) ERR("Failed to read magic marker\n"); else { if(memcmp(magic, magicMarker00, sizeof(magicMarker00)) == 0) { TRACE("Detected data set format v0\n"); Hrtf = LoadHrtf00(f, deviceRate); } else if(memcmp(magic, magicMarker01, sizeof(magicMarker01)) == 0) { TRACE("Detected data set format v1\n"); Hrtf = LoadHrtf01(f, deviceRate); } else ERR("Invalid magic marker: \"%.8s\"\n", magic); } fclose(f); f = NULL; if(Hrtf) { Hrtf->next = LoadedHrtfs; LoadedHrtfs = Hrtf; TRACE("Loaded HRTF support for format: %s %uhz\n", DevFmtChannelsString(DevFmtStereo), Hrtf->sampleRate); return Hrtf; } ERR("Failed to load %s\n", fname); } return NULL; }
static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList) { const char *main_prefix = "plughw:"; snd_ctl_t *handle; snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; int card, err, dev; DevMap entry; clear_devlist(DeviceList); snd_ctl_card_info_malloc(&info); snd_pcm_info_malloc(&pcminfo); AL_STRING_INIT(entry.name); AL_STRING_INIT(entry.device_name); al_string_copy_cstr(&entry.name, alsaDevice); al_string_copy_cstr(&entry.device_name, GetConfigValue(NULL, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? "device" : "capture", "default")); VECTOR_PUSH_BACK(*DeviceList, entry); card = -1; if((err=snd_card_next(&card)) < 0) ERR("Failed to find a card: %s\n", snd_strerror(err)); ConfigValueStr(NULL, "alsa", prefix_name(stream), &main_prefix); while(card >= 0) { const char *card_prefix = main_prefix; const char *cardname, *cardid; char name[256]; snprintf(name, sizeof(name), "hw:%d", card); if((err = snd_ctl_open(&handle, name, 0)) < 0) { ERR("control open (hw:%d): %s\n", card, snd_strerror(err)); goto next_card; } if((err = snd_ctl_card_info(handle, info)) < 0) { ERR("control hardware info (hw:%d): %s\n", card, snd_strerror(err)); snd_ctl_close(handle); goto next_card; } cardname = snd_ctl_card_info_get_name(info); cardid = snd_ctl_card_info_get_id(info); snprintf(name, sizeof(name), "%s-%s", prefix_name(stream), cardid); ConfigValueStr(NULL, "alsa", name, &card_prefix); dev = -1; while(1) { const char *device_prefix = card_prefix; const char *devname; char device[128]; if(snd_ctl_pcm_next_device(handle, &dev) < 0) ERR("snd_ctl_pcm_next_device failed\n"); if(dev < 0) break; snd_pcm_info_set_device(pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, stream); if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { if(err != -ENOENT) ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err)); continue; } devname = snd_pcm_info_get_name(pcminfo); snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev); ConfigValueStr(NULL, "alsa", name, &device_prefix); snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)", cardname, devname, cardid, dev); snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d", device_prefix, cardid, dev); TRACE("Got device \"%s\", \"%s\"\n", name, device); AL_STRING_INIT(entry.name); AL_STRING_INIT(entry.device_name); al_string_copy_cstr(&entry.name, name); al_string_copy_cstr(&entry.device_name, device); VECTOR_PUSH_BACK(*DeviceList, entry); } snd_ctl_close(handle); next_card: if(snd_card_next(&card) < 0) { ERR("snd_card_next failed\n"); break; } } snd_pcm_info_free(pcminfo); snd_ctl_card_info_free(info); }
void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq) { const char *mode; bool headphones; int bs2blevel; size_t i; device->Hrtf = NULL; al_string_clear(&device->Hrtf_Name); device->Render_Mode = NormalRender; memset(&device->Dry.Ambi, 0, sizeof(device->Dry.Ambi)); device->Dry.CoeffCount = 0; device->Dry.NumChannels = 0; if(device->FmtChans != DevFmtStereo) { ALuint speakermap[MAX_OUTPUT_CHANNELS]; const char *devname, *layout = NULL; AmbDecConf conf, *pconf = NULL; if(hrtf_appreq == Hrtf_Enable) device->Hrtf_Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT; ambdec_init(&conf); devname = al_string_get_cstr(device->DeviceName); switch(device->FmtChans) { case DevFmtQuad: layout = "quad"; break; case DevFmtX51: layout = "surround51"; break; case DevFmtX51Rear: layout = "surround51rear"; break; case DevFmtX61: layout = "surround61"; break; case DevFmtX71: layout = "surround71"; break; /* Mono, Stereo, and B-Fornat output don't use custom decoders. */ case DevFmtMono: case DevFmtStereo: case DevFmtBFormat3D: break; } if(layout) { const char *fname; if(ConfigValueStr(devname, "decoder", layout, &fname)) { if(!ambdec_load(&conf, fname)) ERR("Failed to load layout file %s\n", fname); else { if(conf.ChanMask > 0xffff) ERR("Unsupported channel mask 0x%04x (max 0xffff)\n", conf.ChanMask); else { if(MakeSpeakerMap(device, &conf, speakermap)) pconf = &conf; } } } } if(pconf && GetConfigValueBool(devname, "decoder", "hq-mode", 0)) { if(!device->AmbiDecoder) device->AmbiDecoder = bformatdec_alloc(); } else { bformatdec_free(device->AmbiDecoder); device->AmbiDecoder = NULL; } if(!pconf) InitPanning(device); else if(device->AmbiDecoder) InitHQPanning(device, pconf, speakermap); else InitCustomPanning(device, pconf, speakermap); ambdec_deinit(&conf); return; } bformatdec_free(device->AmbiDecoder); device->AmbiDecoder = NULL; headphones = device->IsHeadphones; if(device->Type != Loopback) { const char *mode; if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "stereo-mode", &mode)) { if(strcasecmp(mode, "headphones") == 0) headphones = true; else if(strcasecmp(mode, "speakers") == 0) headphones = false; else if(strcasecmp(mode, "auto") != 0) ERR("Unexpected stereo-mode: %s\n", mode); } } if(hrtf_userreq == Hrtf_Default) { bool usehrtf = (headphones && hrtf_appreq != Hrtf_Disable) || (hrtf_appreq == Hrtf_Enable); if(!usehrtf) goto no_hrtf; device->Hrtf_Status = ALC_HRTF_ENABLED_SOFT; if(headphones && hrtf_appreq != Hrtf_Disable) device->Hrtf_Status = ALC_HRTF_HEADPHONES_DETECTED_SOFT; } else { if(hrtf_userreq != Hrtf_Enable) { if(hrtf_appreq == Hrtf_Enable) device->Hrtf_Status = ALC_HRTF_DENIED_SOFT; goto no_hrtf; } device->Hrtf_Status = ALC_HRTF_REQUIRED_SOFT; } if(VECTOR_SIZE(device->Hrtf_List) == 0) { VECTOR_DEINIT(device->Hrtf_List); device->Hrtf_List = EnumerateHrtf(device->DeviceName); } if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->Hrtf_List)) { const HrtfEntry *entry = &VECTOR_ELEM(device->Hrtf_List, hrtf_id); if(GetHrtfSampleRate(entry->hrtf) == device->Frequency) { device->Hrtf = entry->hrtf; al_string_copy(&device->Hrtf_Name, entry->name); } } for(i = 0;!device->Hrtf && i < VECTOR_SIZE(device->Hrtf_List);i++) { const HrtfEntry *entry = &VECTOR_ELEM(device->Hrtf_List, i); if(GetHrtfSampleRate(entry->hrtf) == device->Frequency) { device->Hrtf = entry->hrtf; al_string_copy(&device->Hrtf_Name, entry->name); } } if(device->Hrtf) { device->Render_Mode = HrtfRender; if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf-mode", &mode)) { if(strcasecmp(mode, "full") == 0) device->Render_Mode = HrtfRender; else if(strcasecmp(mode, "basic") == 0) device->Render_Mode = NormalRender; else ERR("Unexpected hrtf-mode: %s\n", mode); } TRACE("HRTF enabled, \"%s\"\n", al_string_get_cstr(device->Hrtf_Name)); InitHrtfPanning(device); return; } device->Hrtf_Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT; no_hrtf: TRACE("HRTF disabled\n"); bs2blevel = ((headphones && hrtf_appreq != Hrtf_Disable) || (hrtf_appreq == Hrtf_Enable)) ? 5 : 0; if(device->Type != Loopback) ConfigValueInt(al_string_get_cstr(device->DeviceName), NULL, "cf_level", &bs2blevel); if(bs2blevel > 0 && bs2blevel <= 6) { device->Bs2b = al_calloc(16, sizeof(*device->Bs2b)); bs2b_set_params(device->Bs2b, bs2blevel, device->Frequency); device->Render_Mode = StereoPair; TRACE("BS2B enabled\n"); InitPanning(device); return; } TRACE("BS2B disabled\n"); device->Render_Mode = NormalRender; if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "stereo-panning", &mode)) { if(strcasecmp(mode, "paired") == 0) device->Render_Mode = StereoPair; else if(strcasecmp(mode, "uhj") != 0) ERR("Unexpected stereo-panning: %s\n", mode); } if(device->Render_Mode == NormalRender) { device->Uhj_Encoder = al_calloc(16, sizeof(Uhj2Encoder)); TRACE("UHJ enabled\n"); InitUhjPanning(device); return; } TRACE("UHJ disabled\n"); InitPanning(device); }
static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count) { const char *main_prefix = "plughw:"; snd_ctl_t *handle; int card, err, dev, idx; snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; DevMap *DevList; snd_ctl_card_info_malloc(&info); snd_pcm_info_malloc(&pcminfo); DevList = malloc(sizeof(DevMap) * 1); DevList[0].name = strdup(alsaDevice); DevList[0].device = strdup(GetConfigValue("alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? "device" : "capture", "default")); idx = 1; card = -1; if((err=snd_card_next(&card)) < 0) ERR("Failed to find a card: %s\n", snd_strerror(err)); ConfigValueStr("alsa", prefix_name(stream), &main_prefix); while(card >= 0) { const char *card_prefix = main_prefix; const char *cardname, *cardid; char name[256]; snprintf(name, sizeof(name), "hw:%d", card); if((err = snd_ctl_open(&handle, name, 0)) < 0) { ERR("control open (hw:%d): %s\n", card, snd_strerror(err)); goto next_card; } if((err = snd_ctl_card_info(handle, info)) < 0) { ERR("control hardware info (hw:%d): %s\n", card, snd_strerror(err)); snd_ctl_close(handle); goto next_card; } cardname = snd_ctl_card_info_get_name(info); cardid = snd_ctl_card_info_get_id(info); snprintf(name, sizeof(name), "%s-%s", prefix_name(stream), cardid); ConfigValueStr("alsa", name, &card_prefix); dev = -1; while(1) { const char *devname; void *temp; if(snd_ctl_pcm_next_device(handle, &dev) < 0) ERR("snd_ctl_pcm_next_device failed\n"); if(dev < 0) break; snd_pcm_info_set_device(pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, stream); if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { if(err != -ENOENT) ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err)); continue; } temp = realloc(DevList, sizeof(DevMap) * (idx+1)); if(temp) { const char *device_prefix = card_prefix; char device[128]; DevList = temp; devname = snd_pcm_info_get_name(pcminfo); snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev); ConfigValueStr("alsa", name, &device_prefix); snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)", cardname, devname, cardid, dev); snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d", device_prefix, cardid, dev); TRACE("Got device \"%s\", \"%s\"\n", name, device); DevList[idx].name = strdup(name); DevList[idx].device = strdup(device); idx++; } } snd_ctl_close(handle); next_card: if(snd_card_next(&card) < 0) { ERR("snd_card_next failed\n"); break; } } snd_pcm_info_free(pcminfo); snd_ctl_card_info_free(info); *count = idx; return DevList; }
void InitHrtf(void) { char *fnamelist=NULL, *next=NULL; const char *val; if(ConfigValueStr(NULL, "hrtf_tables", &val)) next = fnamelist = strdup(val); while(next && *next) { const ALubyte maxDelay = SRC_HISTORY_LENGTH-1; struct Hrtf newdata; ALboolean failed; ALchar magic[9]; ALsizei i, j; char *fname; FILE *f; fname = next; next = strchr(fname, ','); if(next) { while(next != fname) { next--; if(!isspace(*next)) { *(next++) = '\0'; break; } } while(isspace(*next) || *next == ',') next++; } if(!fname[0]) continue; TRACE("Loading %s\n", fname); f = fopen(fname, "rb"); if(f == NULL) { ERR("Could not open %s\n", fname); continue; } failed = AL_FALSE; if(fread(magic, 1, sizeof(magicMarker), f) != sizeof(magicMarker)) { ERR("Failed to read magic marker\n"); failed = AL_TRUE; } else if(memcmp(magic, magicMarker, sizeof(magicMarker)) != 0) { magic[8] = 0; ERR("Invalid magic marker: \"%s\"\n", magic); failed = AL_TRUE; } if(!failed) { ALushort hrirCount, hrirSize; ALubyte evCount; newdata.sampleRate = fgetc(f); newdata.sampleRate |= fgetc(f)<<8; newdata.sampleRate |= fgetc(f)<<16; newdata.sampleRate |= fgetc(f)<<24; hrirCount = fgetc(f); hrirCount |= fgetc(f)<<8; hrirSize = fgetc(f); hrirSize |= fgetc(f)<<8; evCount = fgetc(f); if(hrirCount != HRIR_COUNT || hrirSize != HRIR_LENGTH || evCount != ELEV_COUNT) { ERR("Unsupported value: hrirCount=%d (%d), hrirSize=%d (%d), evCount=%d (%d)\n", hrirCount, HRIR_COUNT, hrirSize, HRIR_LENGTH, evCount, ELEV_COUNT); failed = AL_TRUE; } } if(!failed) { for(i = 0;i < ELEV_COUNT;i++) { ALushort offset; offset = fgetc(f); offset |= fgetc(f)<<8; if(offset != evOffset[i]) { ERR("Unsupported evOffset[%d] value: %d (%d)\n", i, offset, evOffset[i]); failed = AL_TRUE; } } } if(!failed) { for(i = 0;i < HRIR_COUNT;i++) { for(j = 0;j < HRIR_LENGTH;j++) { ALshort coeff; coeff = fgetc(f); coeff |= fgetc(f)<<8; newdata.coeffs[i][j] = coeff; } } for(i = 0;i < HRIR_COUNT;i++) { ALubyte delay; delay = fgetc(f); newdata.delays[i] = delay; if(delay > maxDelay) { ERR("Invalid delay[%d]: %d (%d)\n", i, delay, maxDelay); failed = AL_TRUE; } } if(feof(f)) { ERR("Premature end of data\n"); failed = AL_TRUE; } } fclose(f); f = NULL; if(!failed) { void *temp = realloc(LoadedHrtfs, (NumLoadedHrtfs+1)*sizeof(LoadedHrtfs[0])); if(temp != NULL) { LoadedHrtfs = temp; TRACE("Loaded HRTF support for format: %s %uhz\n", DevFmtChannelsString(DevFmtStereo), newdata.sampleRate); LoadedHrtfs[NumLoadedHrtfs++] = newdata; } } else ERR("Failed to load %s\n", fname); } free(fnamelist); fnamelist = NULL; }
static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MAXCHANNELS], enum Channel Speaker2Chan[MAXCHANNELS], ALint chans) { char *confkey, *next; char *layout_str; char *sep, *end; enum Channel val; const char *str; int i; if(!ConfigValueStr(NULL, name, &str) && !ConfigValueStr(NULL, "layout", &str)) return; layout_str = strdup(str); next = confkey = layout_str; while(next && *next) { confkey = next; next = strchr(confkey, ','); if(next) { *next = 0; do { next++; } while(isspace(*next) || *next == ','); } sep = strchr(confkey, '='); if(!sep || confkey == sep) { ERR("Malformed speaker key: %s\n", confkey); continue; } end = sep - 1; while(isspace(*end) && end != confkey) end--; *(++end) = 0; if(strcmp(confkey, "fl") == 0 || strcmp(confkey, "front-left") == 0) val = FRONT_LEFT; else if(strcmp(confkey, "fr") == 0 || strcmp(confkey, "front-right") == 0) val = FRONT_RIGHT; else if(strcmp(confkey, "fc") == 0 || strcmp(confkey, "front-center") == 0) val = FRONT_CENTER; else if(strcmp(confkey, "bl") == 0 || strcmp(confkey, "back-left") == 0) val = BACK_LEFT; else if(strcmp(confkey, "br") == 0 || strcmp(confkey, "back-right") == 0) val = BACK_RIGHT; else if(strcmp(confkey, "bc") == 0 || strcmp(confkey, "back-center") == 0) val = BACK_CENTER; else if(strcmp(confkey, "sl") == 0 || strcmp(confkey, "side-left") == 0) val = SIDE_LEFT; else if(strcmp(confkey, "sr") == 0 || strcmp(confkey, "side-right") == 0) val = SIDE_RIGHT; else { ERR("Unknown speaker for %s: \"%s\"\n", name, confkey); continue; } *(sep++) = 0; while(isspace(*sep)) sep++; for(i = 0;i < chans;i++) { if(Speaker2Chan[i] == val) { long angle = strtol(sep, NULL, 10); if(angle >= -180 && angle <= 180) SpeakerAngle[i] = angle * F_PI/180.0f; else ERR("Invalid angle for speaker \"%s\": %ld\n", confkey, angle); break; } } } free(layout_str); layout_str = NULL; for(i = 0;i < chans;i++) { int min = i; int i2; for(i2 = i+1;i2 < chans;i2++) { if(SpeakerAngle[i2] < SpeakerAngle[min]) min = i2; } if(min != i) { ALfloat tmpf; enum Channel tmpc; tmpf = SpeakerAngle[i]; SpeakerAngle[i] = SpeakerAngle[min]; SpeakerAngle[min] = tmpf; tmpc = Speaker2Chan[i]; Speaker2Chan[i] = Speaker2Chan[min]; Speaker2Chan[min] = tmpc; } } }
int MOB_File_ConfigValueStr(const char *blockName, const char *keyName, const char **ret) { char buffer[ 64 ]; return ConfigValueStr( ConvertBlockName( blockName ), ConvertKeyName( buffer, keyName ), ret ); }
int MOB_ConfigValueStr_KeyStr(const char *blockName, const char *keyName, const char **ret) { return ConfigValueStr( blockName, keyName, ret ); }
static bool LoadChannelSetup(ALCdevice *device) { static const enum Channel mono_chans[1] = { FrontCenter }, stereo_chans[2] = { FrontLeft, FrontRight }, quad_chans[4] = { FrontLeft, FrontRight, BackLeft, BackRight }, surround51_chans[5] = { FrontLeft, FrontRight, FrontCenter, SideLeft, SideRight }, surround51rear_chans[5] = { FrontLeft, FrontRight, FrontCenter, BackLeft, BackRight }, surround61_chans[6] = { FrontLeft, FrontRight, FrontCenter, BackCenter, SideLeft, SideRight }, surround71_chans[7] = { FrontLeft, FrontRight, FrontCenter, BackLeft, BackRight, SideLeft, SideRight }; ChannelMap chanmap[MAX_OUTPUT_CHANNELS]; const enum Channel *channels = NULL; const char *layout = NULL; ALfloat ambiscale = 1.0f; size_t count = 0; int isfuma; int order; size_t i; switch(device->FmtChans) { case DevFmtMono: layout = "mono"; channels = mono_chans; count = COUNTOF(mono_chans); break; case DevFmtStereo: layout = "stereo"; channels = stereo_chans; count = COUNTOF(stereo_chans); break; case DevFmtQuad: layout = "quad"; channels = quad_chans; count = COUNTOF(quad_chans); break; case DevFmtX51: layout = "surround51"; channels = surround51_chans; count = COUNTOF(surround51_chans); break; case DevFmtX51Rear: layout = "surround51rear"; channels = surround51rear_chans; count = COUNTOF(surround51rear_chans); break; case DevFmtX61: layout = "surround61"; channels = surround61_chans; count = COUNTOF(surround61_chans); break; case DevFmtX71: layout = "surround71"; channels = surround71_chans; count = COUNTOF(surround71_chans); break; case DevFmtBFormat3D: break; } if(!layout) return false; else { char name[32] = {0}; const char *type; char eol; snprintf(name, sizeof(name), "%s/type", layout); if(!ConfigValueStr(al_string_get_cstr(device->DeviceName), "layouts", name, &type)) return false; if(sscanf(type, " %31[^: ] : %d%c", name, &order, &eol) != 2) { ERR("Invalid type value '%s' (expected name:order) for layout %s\n", type, layout); return false; } if(strcasecmp(name, "fuma") == 0) isfuma = 1; else if(strcasecmp(name, "n3d") == 0) isfuma = 0; else { ERR("Unhandled type name '%s' (expected FuMa or N3D) for layout %s\n", name, layout); return false; } if(order == 3) ambiscale = THIRD_ORDER_SCALE; else if(order == 2) ambiscale = SECOND_ORDER_SCALE; else if(order == 1) ambiscale = FIRST_ORDER_SCALE; else if(order == 0) ambiscale = ZERO_ORDER_SCALE; else { ERR("Unhandled type order %d (expected 0, 1, 2, or 3) for layout %s\n", order, layout); return false; } } for(i = 0;i < count;i++) { float coeffs[MAX_AMBI_COEFFS] = {0.0f}; const char *channame; char chanlayout[32]; const char *value; int props = 0; char eol = 0; int j; chanmap[i].ChanName = channels[i]; channame = GetLabelFromChannel(channels[i]); snprintf(chanlayout, sizeof(chanlayout), "%s/%s", layout, channame); if(!ConfigValueStr(al_string_get_cstr(device->DeviceName), "layouts", chanlayout, &value)) { ERR("Missing channel %s\n", channame); return false; } if(order == 3) props = sscanf(value, " %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %c", &coeffs[0], &coeffs[1], &coeffs[2], &coeffs[3], &coeffs[4], &coeffs[5], &coeffs[6], &coeffs[7], &coeffs[8], &coeffs[9], &coeffs[10], &coeffs[11], &coeffs[12], &coeffs[13], &coeffs[14], &coeffs[15], &eol ); else if(order == 2) props = sscanf(value, " %f %f %f %f %f %f %f %f %f %c", &coeffs[0], &coeffs[1], &coeffs[2], &coeffs[3], &coeffs[4], &coeffs[5], &coeffs[6], &coeffs[7], &coeffs[8], &eol ); else if(order == 1) props = sscanf(value, " %f %f %f %f %c", &coeffs[0], &coeffs[1], &coeffs[2], &coeffs[3], &eol ); else if(order == 0) props = sscanf(value, " %f %c", &coeffs[0], &eol); if(props == 0) { ERR("Failed to parse option %s properties\n", chanlayout); return false; } if(props > (order+1)*(order+1)) { ERR("Excess elements in option %s (expected %d)\n", chanlayout, (order+1)*(order+1)); return false; } if(isfuma) { /* Reorder FuMa -> ACN */ for(j = 0;j < MAX_AMBI_COEFFS;++j) chanmap[i].Config[FuMa2ACN[j]] = coeffs[j]; } else { /* Rescale N3D -> FuMa */ for(j = 0;j < MAX_AMBI_COEFFS;++j) chanmap[i].Config[j] = coeffs[j] * N3D2FuMaScale[j]; } } SetChannelMap(device, chanmap, count, ambiscale); return true; }
static ALCenum alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName) { const char *driver = "default"; snd_pcm_hw_params_t *p; snd_pcm_uframes_t bufferSizeInFrames; snd_pcm_uframes_t periodSizeInFrames; snd_pcm_format_t format; ALuint frameSize; alsa_data *data; char str[128]; char *err; int i; ConfigValueStr("alsa", "capture", &driver); if(!allCaptureDevNameMap) allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames); if(!deviceName) deviceName = allCaptureDevNameMap[0].name; else { size_t idx; for(idx = 0;idx < numCaptureDevNames;idx++) { if(allCaptureDevNameMap[idx].name && strcmp(deviceName, allCaptureDevNameMap[idx].name) == 0) { if(idx > 0) { snprintf(str, sizeof(str), "%sCARD=%s,DEV=%d", capture_prefix, allCaptureDevNameMap[idx].card, allCaptureDevNameMap[idx].dev); driver = str; } break; } } if(idx == numCaptureDevNames) return ALC_INVALID_VALUE; } data = (alsa_data*)calloc(1, sizeof(alsa_data)); i = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); if(i < 0) { ERR("Could not open capture device '%s': %s\n", driver, snd_strerror(i)); free(data); return ALC_INVALID_VALUE; } format = -1; switch(pDevice->FmtType) { case DevFmtByte: format = SND_PCM_FORMAT_S8; break; case DevFmtUByte: format = SND_PCM_FORMAT_U8; break; case DevFmtShort: format = SND_PCM_FORMAT_S16; break; case DevFmtUShort: format = SND_PCM_FORMAT_U16; break; case DevFmtFloat: format = SND_PCM_FORMAT_FLOAT; break; } err = NULL; bufferSizeInFrames = maxu(pDevice->UpdateSize*pDevice->NumUpdates, 100*pDevice->Frequency/1000); periodSizeInFrames = minu(bufferSizeInFrames, 50*pDevice->Frequency/1000); snd_pcm_hw_params_malloc(&p); if((i=snd_pcm_hw_params_any(data->pcmHandle, p)) < 0) err = "any"; /* set interleaved access */ if(i >= 0 && (i=snd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) err = "set access"; /* set format (implicitly sets sample bits) */ if(i >= 0 && (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0) err = "set format"; /* set channels (implicitly sets frame bits) */ if(i >= 0 && (i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, ChannelsFromDevFmt(pDevice->FmtChans))) < 0) err = "set channels"; /* set rate (implicitly constrains period/buffer parameters) */ if(i >= 0 && (i=snd_pcm_hw_params_set_rate(data->pcmHandle, p, pDevice->Frequency, 0)) < 0) err = "set rate near"; /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */ if(i >= 0 && (i=snd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, p, &bufferSizeInFrames)) < 0) err = "set buffer size near"; /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */ if(i >= 0 && (i=snd_pcm_hw_params_set_period_size_near(data->pcmHandle, p, &periodSizeInFrames, NULL)) < 0) err = "set period size near"; /* install and prepare hardware configuration */ if(i >= 0 && (i=snd_pcm_hw_params(data->pcmHandle, p)) < 0) err = "set params"; if(i < 0) { ERR("%s failed: %s\n", err, snd_strerror(i)); snd_pcm_hw_params_free(p); goto error; } if((i=snd_pcm_hw_params_get_period_size(p, &bufferSizeInFrames, NULL)) < 0) { ERR("get size failed: %s\n", snd_strerror(i)); snd_pcm_hw_params_free(p); goto error; } snd_pcm_hw_params_free(p); frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); data->ring = CreateRingBuffer(frameSize, pDevice->UpdateSize*pDevice->NumUpdates); if(!data->ring) { ERR("ring buffer create failed\n"); goto error; } data->size = snd_pcm_frames_to_bytes(data->pcmHandle, bufferSizeInFrames); data->buffer = malloc(data->size); if(!data->buffer) { ERR("buffer malloc failed\n"); goto error; } pDevice->szDeviceName = strdup(deviceName); pDevice->ExtraData = data; return ALC_NO_ERROR; error: free(data->buffer); DestroyRingBuffer(data->ring); snd_pcm_close(data->pcmHandle); free(data); pDevice->ExtraData = NULL; return ALC_INVALID_VALUE; }