void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) { snd_pcm_t* handle; snd_pcm_format_mask_t* formatMask; snd_pcm_format_t format; snd_pcm_hw_params_t* hwParams; int handledBits[MAX_BIT_INDEX+1]; int ret; int sampleSizeInBytes, significantBits, isSigned, isBigEndian, enc; int origSampleSizeInBytes, origSignificantBits; int channels, minChannels, maxChannels; int rate, bitIndex; for (bitIndex = 0; bitIndex <= MAX_BIT_INDEX; bitIndex++) handledBits[bitIndex] = FALSE; if (openPCMfromDeviceID(deviceID, &handle, isSource, TRUE /*query hardware*/) < 0) { return; } ret = snd_pcm_format_mask_malloc(&formatMask); if (ret != 0) { ERROR1("snd_pcm_format_mask_malloc returned error %d\n", ret); } else { ret = snd_pcm_hw_params_malloc(&hwParams); if (ret != 0) { ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret); } else { ret = snd_pcm_hw_params_any(handle, hwParams); if (ret != 0) { ERROR1("snd_pcm_hw_params_any returned error %d\n", ret); } } snd_pcm_hw_params_get_format_mask(hwParams, formatMask); #ifdef ALSA_PCM_NEW_HW_PARAMS_API if (ret == 0) { ret = snd_pcm_hw_params_get_channels_min(hwParams, &minChannels); if (ret != 0) { ERROR1("snd_pcm_hw_params_get_channels_min returned error %d\n", ret); } } if (ret == 0) { ret = snd_pcm_hw_params_get_channels_max(hwParams, &maxChannels); if (ret != 0) { ERROR1("snd_pcm_hw_params_get_channels_max returned error %d\n", ret); } } #else minChannels = snd_pcm_hw_params_get_channels_min(hwParams); maxChannels = snd_pcm_hw_params_get_channels_max(hwParams); if (minChannels > maxChannels) { ERROR2("MinChannels=%d, maxChannels=%d\n", minChannels, maxChannels); } #endif // since we queried the hw: device, for many soundcards, it will only // report the maximum number of channels (which is the only way to talk // to the hw: device). Since we will, however, open the plughw: device // when opening the Source/TargetDataLine, we can safely assume that // also the channels 1..maxChannels are available. #ifdef ALSA_PCM_USE_PLUGHW minChannels = 1; #endif if (ret == 0) { // plughw: supports any sample rate rate = -1; for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) { if (snd_pcm_format_mask_test(formatMask, format)) { // format exists if (getFormatFromAlsaFormat(format, &origSampleSizeInBytes, &origSignificantBits, &isSigned, &isBigEndian, &enc)) { // now if we use plughw:, we can use any bit size below the // natively supported ones. Some ALSA drivers only support the maximum // bit size, so we add any sample rates below the reported one. // E.g. this iteration reports support for 16-bit. // getBitIndex will return 2, so it will add entries for // 16-bit (bitIndex=2) and in the next do-while loop iteration, // it will decrease bitIndex and will therefore add 8-bit support. bitIndex = getBitIndex(origSampleSizeInBytes, origSignificantBits); do { if (bitIndex == 0 || bitIndex == MAX_BIT_INDEX || !handledBits[bitIndex]) { handledBits[bitIndex] = TRUE; sampleSizeInBytes = getSampleSizeInBytes(bitIndex, origSampleSizeInBytes); significantBits = getSignificantBits(bitIndex, origSignificantBits); if (maxChannels - minChannels > MAXIMUM_LISTED_CHANNELS) { // avoid too many channels explicitly listed // just add -1, min, and max DAUDIO_AddAudioFormat(creator, significantBits, -1, -1, rate, enc, isSigned, isBigEndian); DAUDIO_AddAudioFormat(creator, significantBits, sampleSizeInBytes * minChannels, minChannels, rate, enc, isSigned, isBigEndian); DAUDIO_AddAudioFormat(creator, significantBits, sampleSizeInBytes * maxChannels, maxChannels, rate, enc, isSigned, isBigEndian); } else { for (channels = minChannels; channels <= maxChannels; channels++) { DAUDIO_AddAudioFormat(creator, significantBits, (channels < 0)?-1:(sampleSizeInBytes * channels), channels, rate, enc, isSigned, isBigEndian); } } } #ifndef ALSA_PCM_USE_PLUGHW // without plugin, do not add fake formats break; #endif } while (--bitIndex > 0); } else { TRACE1("could not get format from alsa for format %d\n", format); } } else { //TRACE1("Format %d not supported\n", format); } } // for loop snd_pcm_hw_params_free(hwParams); } snd_pcm_format_mask_free(formatMask); } snd_pcm_close(handle); }
void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) { int fd = -1; AudioDeviceDescription desc; am_sample_rates_t *sr; /* hardcoded bits and channels */ int bits[] = {8, 16}; int bitsCount = 2; int channels[] = {1, 2}; int channelsCount = 2; /* for querying sample rates */ int err; int ch, b, s; TRACE2("DAUDIO_GetFormats, mixer %d, isSource=%d\n", mixerIndex, isSource); if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) { fd = open(desc.pathctl, O_RDONLY); } if (fd < 0) { ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex); return; } /* get sample rates */ sr = (am_sample_rates_t*) malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(MAX_SAMPLE_RATES)); if (sr == NULL) { ERROR1("DAUDIO_GetFormats: out of memory for mixer %d\n", (int) mixerIndex); close(fd); return; } sr->num_samp_rates = MAX_SAMPLE_RATES; sr->type = isSource?AUDIO_PLAY:AUDIO_RECORD; sr->samp_rates[0] = -2; err = ioctl(fd, AUDIO_MIXER_GET_SAMPLE_RATES, sr); if (err < 0) { ERROR1(" DAUDIO_GetFormats: AUDIO_MIXER_GET_SAMPLE_RATES failed for mixer %d!\n", (int)mixerIndex); ERROR2(" -> num_sample_rates=%d sample_rates[0] = %d\n", (int) sr->num_samp_rates, (int) sr->samp_rates[0]); /* Some Solaris 8 drivers fail for get sample rates! * Do as if we support all sample rates */ sr->flags = MIXER_SR_LIMITS; } if ((sr->flags & MIXER_SR_LIMITS) || (sr->num_samp_rates > MAX_SAMPLE_RATES)) { #ifdef USE_TRACE if ((sr->flags & MIXER_SR_LIMITS)) { TRACE1(" DAUDIO_GetFormats: floating sample rate allowed by mixer %d\n", (int)mixerIndex); } if (sr->num_samp_rates > MAX_SAMPLE_RATES) { TRACE2(" DAUDIO_GetFormats: more than %d formats. Use -1 for sample rates mixer %d\n", MAX_SAMPLE_RATES, (int)mixerIndex); } #endif /* * Fake it to have only one sample rate: -1 */ sr->num_samp_rates = 1; sr->samp_rates[0] = -1; } close(fd); for (ch = 0; ch < channelsCount; ch++) { for (b = 0; b < bitsCount; b++) { for (s = 0; s < sr->num_samp_rates; s++) { DAUDIO_AddAudioFormat(creator, bits[b], /* significant bits */ 0, /* frameSize: let it be calculated */ channels[ch], (float) ((int) sr->samp_rates[s]), DAUDIO_PCM, /* encoding - let's only do PCM */ (bits[b] > 8)?TRUE:TRUE, /* isSigned */ #if (X_WORD_ORDER == TRUE) FALSE /* little endian */ #else (bits[b] > 8)?TRUE:FALSE /* big endian */ #endif ); } } } free(sr); }