/* * return the highest sample rate supported by audio device |dev|. */ static int find_highest_samplerate(int dev) { #if HAVE_SYS_MIXER_H am_sample_rates_t *sr; int i, num, max_rate; for (num = 16; num < 1024; num *= 2) { sr = malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(num)); if (!sr) return 0; sr->type = AUDIO_PLAY; sr->flags = 0; sr->num_samp_rates = num; if (ioctl(dev, AUDIO_MIXER_GET_SAMPLE_RATES, sr)) { free(sr); return 0; } if (sr->num_samp_rates <= num) break; free(sr); } if (sr->flags & MIXER_SR_LIMITS) { /* * HW can playback any rate between * sr->samp_rates[0] .. sr->samp_rates[1] */ max_rate = sr->samp_rates[1]; } else { /* HW supports fixed sample rates only */ max_rate = 0; for (i = 0; i < sr->num_samp_rates; i++) { if (sr->samp_rates[i] > max_rate) max_rate = sr->samp_rates[i]; } } free(sr); return max_rate; #else return 44100; /* should be supported even on old ISA SB cards */ #endif }
/* * match the requested sample rate |sample_rate| against the * sample rates supported by the audio device |dev|. Return * a supported sample rate, it that sample rate is close to * (< 1% difference) the requested rate; return 0 otherwise. */ static int find_close_samplerate_match(int dev, int sample_rate) { #if HAVE_SYS_MIXER_H am_sample_rates_t *sr; int i, num, err, best_err, best_rate; for (num = 16; num < 1024; num *= 2) { sr = malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(num)); if (!sr) return 0; sr->type = AUDIO_PLAY; sr->flags = 0; sr->num_samp_rates = num; if (ioctl(dev, AUDIO_MIXER_GET_SAMPLE_RATES, sr)) { free(sr); return 0; } if (sr->num_samp_rates <= num) break; free(sr); } if (sr->flags & MIXER_SR_LIMITS) { /* * HW can playback any rate between * sr->samp_rates[0] .. sr->samp_rates[1] */ free(sr); return 0; } else { /* HW supports fixed sample rates only */ best_err = 65535; best_rate = 0; for (i = 0; i < sr->num_samp_rates; i++) { err = abs(sr->samp_rates[i] - sample_rate); if (err == 0) { /* * exact supported sample rate match, no need to * retry something else */ best_rate = 0; break; } if (err < best_err) { best_err = err; best_rate = sr->samp_rates[i]; } } free(sr); if (best_rate > 0 && 100*best_err < sample_rate) { /* found a supported sample rate with <1% error? */ return best_rate; } return 0; } #else int i, err; int audiocs_rates[] = { 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, 27420, 32000, 33075, 37800, 44100, 48000, 0 }; for (i = 0; audiocs_rates[i]; i++) { err = abs(audiocs_rates[i] - sample_rate); if (err == 0) { /* * exact supported sample rate match, no need to * retry something elise */ return 0; } if (100*err < audiocs_rates[i]) { /* <1% error? */ return audiocs_rates[i]; } } return 0; #endif }
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); }