int getPcmParams(unsigned int i) { struct pcm_params *params; unsigned int min; unsigned int max; params = pcm_params_get(pcmnodes[i].card, pcmnodes[i].device, pcmnodes[i].flags); if (params == NULL) return -ENODEV; min = pcm_params_get_min(params, PCM_PARAM_RATE); max = pcm_params_get_max(params, PCM_PARAM_RATE); EXPECT_LE(min, max); /* printf(" Rate:\tmin=%uHz\tmax=%uHz\n", min, max); */ min = pcm_params_get_min(params, PCM_PARAM_CHANNELS); max = pcm_params_get_max(params, PCM_PARAM_CHANNELS); EXPECT_LE(min, max); /* printf(" Channels:\tmin=%u\t\tmax=%u\n", min, max); */ min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS); max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS); EXPECT_LE(min, max); /* printf(" Sample bits:\tmin=%u\t\tmax=%u\n", min, max); */ min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE); max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE); EXPECT_LE(min, max); /* printf(" Period size:\tmin=%u\t\tmax=%u\n", min, max); */ min = pcm_params_get_min(params, PCM_PARAM_PERIODS); max = pcm_params_get_max(params, PCM_PARAM_PERIODS); EXPECT_LE(min, max); /* printf("Period count:\tmin=%u\t\tmax=%u\n", min, max); */ pcm_params_free(params); return 0; }
status_t AudioALSAPlaybackHandlerBTSCO::open() { ALOGD("+%s(), mDevice = 0x%x", __FUNCTION__, mStreamAttributeSource->output_devices); // debug pcm dump OpenPCMDump(LOG_TAG); int pcmindex = AudioALSADeviceParser::getInstance()->GetPcmIndexByString(keypcmVOIPCallBTPlayback); int cardindex = AudioALSADeviceParser::getInstance()->GetCardIndexByString(keypcmVOIPCallBTPlayback); struct pcm_params *params; params = pcm_params_get(cardindex, pcmindex, PCM_OUT); if (params == NULL) { ALOGD("Device does not exist.\n"); } mStreamAttributeTarget.buffer_size = pcm_params_get_max(params, PCM_PARAM_BUFFER_BYTES); ALOGD("buffersizemax = %d", mStreamAttributeTarget.buffer_size); pcm_params_free(params); // HW attribute config // TODO(Harvey): query this #ifdef PLAYBACK_USE_24BITS_ONLY mStreamAttributeTarget.audio_format = AUDIO_FORMAT_PCM_8_24_BIT; #else mStreamAttributeTarget.audio_format = AUDIO_FORMAT_PCM_16_BIT; #endif mStreamAttributeTarget.audio_channel_mask = AUDIO_CHANNEL_IN_STEREO; mStreamAttributeTarget.num_channels = android_audio_legacy::AudioSystem::popCount(mStreamAttributeTarget.audio_channel_mask); mStreamAttributeTarget.sample_rate = mWCNChipController->GetBTCurrentSamplingRateNumber(); // HW pcm config mConfig.channels = mStreamAttributeTarget.num_channels; mConfig.rate = mStreamAttributeTarget.sample_rate; mConfig.period_count = 2; mConfig.period_size = (mStreamAttributeTarget.buffer_size / (mConfig.channels * mConfig.period_count)) / ((mStreamAttributeTarget.audio_format == AUDIO_FORMAT_PCM_16_BIT) ? 2 : 4); mConfig.format = transferAudioFormatToPcmFormat(mStreamAttributeTarget.audio_format); mConfig.start_threshold = 0; mConfig.stop_threshold = 0; mConfig.silence_threshold = 0; ALOGD("%s(), mConfig: channels = %d, rate = %d, period_size = %d, period_count = %d, format = %d", __FUNCTION__, mConfig.channels, mConfig.rate, mConfig.period_size, mConfig.period_count, mConfig.format); // SRC initBliSrc(); // bit conversion initBitConverter(); // open pcm driver openPcmDriver(pcmindex); ALOGD("-%s()", __FUNCTION__); return NO_ERROR; }
static int validate_output_hardware_params(struct stream_out *out) { struct audio_device *adev = out->dev; struct pcm_params *params; unsigned int min; unsigned int max; params = pcm_params_get(adev->card, adev->device, PCM_OUT); if (params == NULL) { ALOGW("Device does not exist.\n"); return -1; } //always open the device with max capabilities if // input params are not supported min = pcm_params_get_min(params, PCM_PARAM_RATE); max = pcm_params_get_max(params, PCM_PARAM_RATE); ALOGI("hw supported Rate:\tmin=%uHz\tmax=%uHz\n", min, max); if((out->pcm_config.rate < min) || (out->pcm_config.rate > max)) { out->pcm_config.rate = max; } min = pcm_params_get_min(params, PCM_PARAM_CHANNELS); max = pcm_params_get_max(params, PCM_PARAM_CHANNELS); ALOGI("hw supported Channels:\tmin=%u\t\tmax=%u\n", min, max); if((out->pcm_config.channels < min) || (out->pcm_config.channels > max)) { out->pcm_config.channels = max; } min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS); max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS); ALOGI("hw supported Sample bits:\tmin=%u\t\tmax=%u\n", min, max); unsigned int bits_per_sample = format_to_bits(out->pcm_config.format); if((bits_per_sample < min) || (bits_per_sample > max)) { bits_per_sample = max; } out->pcm_config.format = bits_to_format(bits_per_sample); ALOGV("%s exit supported params %d,%d,%d,%d,%d",__func__, out->pcm_config.channels, out->pcm_config.rate, out->pcm_config.period_size, out->pcm_config.period_count, out->pcm_config.format); pcm_params_free(params); return 0; }
/* * Reads and decodes configuration info from the specified ALSA card/device. */ static int read_alsa_device_config(alsa_device_profile * profile, struct pcm_config * config) { ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)", profile->card, profile->device, profile->direction); if (profile->card < 0 || profile->device < 0) { return -EINVAL; } struct pcm_params * alsa_hw_params = pcm_params_get(profile->card, profile->device, profile->direction); if (alsa_hw_params == NULL) { return -EINVAL; } profile->min_period_size = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE); profile->max_period_size = pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE); profile->min_channel_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS); profile->max_channel_count = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS); int ret = 0; /* * This Logging will be useful when testing new USB devices. */ #ifdef LOG_PCM_PARAMS log_pcm_params(alsa_hw_params); #endif config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS); config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE); config->period_size = profile_calc_min_period_size(profile, config->rate); config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS); config->format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT)); #ifdef LOG_PCM_PARAMS log_pcm_config(config, "read_alsa_device_config"); #endif if (config->format == PCM_FORMAT_INVALID) { ret = -EINVAL; } pcm_params_free(alsa_hw_params); return ret; }
uint32_t SpeechANCController::ConfigPCM(String8 stringPCM, int *buffer_size) { struct pcm_params *params; int pcmindex = AudioALSADeviceParser::getInstance()->GetPcmIndexByString(stringPCM); int cardindex = AudioALSADeviceParser::getInstance()->GetCardIndexByString(stringPCM); params = pcm_params_get(cardindex, pcmindex, PCM_IN); if (params == NULL) { ALOGD("Device does not exist.\n"); } *buffer_size = pcm_params_get_max(params, PCM_PARAM_BUFFER_BYTES); pcm_params_free(params); // ALOGD("%s(), pcmindex(%d), cardindex(%d), buffersizemax(%d)", __FUNCTION__, pcmindex, cardindex, *buffer_size); ALOGD("%s(), %s = pcmindex(%d), cardindex(%d), buffersizemax(%d)", __FUNCTION__, stringPCM.string(), pcmindex, cardindex, *buffer_size); return pcmindex; }
static int deinit_tinyalsa(out123_handle* ao) { mpg123_tinyalsa_t* ta = (mpg123_tinyalsa_t*)ao->userptr; /* Free up card/device parameters */ pcm_params_free(ta->params); /* Free up memory */ if(ao->userptr) { free( ao->userptr ); ao->userptr = NULL; } /* Success */ return 0; }
int sample_is_playable(unsigned int card, unsigned int device, unsigned int channels, unsigned int rate, unsigned int bits, unsigned int period_size, unsigned int period_count) { struct pcm_params *params; int can_play; params = pcm_params_get(card, device, PCM_OUT); if (params == NULL) { fprintf(stderr, "Unable to open PCM device %u.\n", device); return 0; } can_play = check_param(params, PCM_PARAM_RATE, rate, "Sample rate", "Hz"); can_play &= check_param(params, PCM_PARAM_CHANNELS, channels, "Sample", " channels"); can_play &= check_param(params, PCM_PARAM_SAMPLE_BITS, bits, "Bitrate", " bits"); can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, period_size, "Period size", "Hz"); can_play &= check_param(params, PCM_PARAM_PERIODS, period_count, "Period count", "Hz"); pcm_params_free(params); return can_play; }
void AudioALSAPlaybackHandlerNormal::OpenHpImpeDancePcm(void) { ALOGD("OpenHpImpeDancePcm"); // Don't lock Sram/Dram lock here, it would be locked by caller function int pcmindex = AudioALSADeviceParser::getInstance()->GetPcmIndexByString(keypcmHpimpedancePlayback); int cardindex = AudioALSADeviceParser::getInstance()->GetCardIndexByString(keypcmHpimpedancePlayback); struct pcm_params *params; params = pcm_params_get(cardindex, pcmindex, PCM_OUT); if (params == NULL) { ALOGD("Device does not exist.\n"); } int buffer_size = pcm_params_get_max(params, PCM_PARAM_BUFFER_BYTES); ALOGD("buffer_size = %d", buffer_size); pcm_params_free(params); // HW pcm config mHpImpedanceConfig.channels = 2; mHpImpedanceConfig.rate = mStreamAttributeSource->sample_rate; mHpImpedanceConfig.period_count = 2; mHpImpedanceConfig.period_size = (buffer_size / (mHpImpedanceConfig.channels * mHpImpedanceConfig.period_count)) / 2; mHpImpedanceConfig.format = PCM_FORMAT_S16_LE; mHpImpedanceConfig.start_threshold = 0; mHpImpedanceConfig.stop_threshold = 0; mHpImpedanceConfig.silence_threshold = 0; ALOGD("%s(), mHpImpedanceConfig: channels = %d, rate = %d, period_size = %d, period_count = %d, format = %d", __FUNCTION__, mHpImpedanceConfig.channels, mHpImpedanceConfig.rate, mHpImpedanceConfig.period_size, mHpImpedanceConfig.period_count, mHpImpedanceConfig.format); // open pcm driver mHpImpeDancePcm = pcm_open(cardindex, pcmindex, PCM_OUT, &mHpImpedanceConfig); if (mHpImpeDancePcm == NULL) { ALOGE("%s(), mPcm == NULL!!", __FUNCTION__); } ALOGD("-%s(), mPcm = %p", __FUNCTION__, mHpImpeDancePcm); ASSERT(mHpImpeDancePcm != NULL); pcm_start(mHpImpeDancePcm); }
status_t AudioALSAPlaybackHandlerNormal::open() { ALOGD("+%s(), mDevice = 0x%x", __FUNCTION__, mStreamAttributeSource->output_devices); AudioAutoTimeoutLock _l(*AudioALSADriverUtility::getInstance()->getStreamSramDramLock()); // debug pcm dump OpenPCMDump(LOG_TAG); // acquire pmic clk mHardwareResourceManager->EnableAudBufClk(true); HpImpeDanceDetect(); int pcmindex = AudioALSADeviceParser::getInstance()->GetPcmIndexByString(keypcmI2S0Dl1Playback); int cardindex = AudioALSADeviceParser::getInstance()->GetCardIndexByString(keypcmI2S0Dl1Playback); ALOGD("AudioALSAPlaybackHandlerNormal::open() pcmindex = %d", pcmindex); ListPcmDriver(cardindex, pcmindex); struct pcm_params *params; params = pcm_params_get(cardindex, pcmindex, PCM_OUT); if (params == NULL) { ALOGD("Device does not exist.\n"); } mStreamAttributeTarget.buffer_size = pcm_params_get_max(params, PCM_PARAM_BUFFER_BYTES); pcm_params_free(params); // HW attribute config // TODO(Harvey): query this #ifdef PLAYBACK_USE_24BITS_ONLY mStreamAttributeTarget.audio_format = AUDIO_FORMAT_PCM_8_24_BIT; #else mStreamAttributeTarget.audio_format = (mStreamAttributeSource->audio_format == AUDIO_FORMAT_PCM_32_BIT) ? AUDIO_FORMAT_PCM_8_24_BIT : AUDIO_FORMAT_PCM_16_BIT; #endif mStreamAttributeTarget.audio_channel_mask = AUDIO_CHANNEL_IN_STEREO; mStreamAttributeTarget.num_channels = android_audio_legacy::AudioSystem::popCount(mStreamAttributeTarget.audio_channel_mask); mStreamAttributeTarget.sample_rate = ChooseTargetSampleRate(mStreamAttributeSource->sample_rate,mStreamAttributeSource->output_devices); // HW pcm config mConfig.channels = mStreamAttributeTarget.num_channels; mConfig.rate = mStreamAttributeTarget.sample_rate; // Buffer size: 1536(period_size) * 2(ch) * 4(byte) * 2(period_count) = 24 kb mConfig.period_count = 2; mConfig.period_size = (mStreamAttributeTarget.buffer_size / (mConfig.channels * mConfig.period_count)) / ((mStreamAttributeTarget.audio_format == AUDIO_FORMAT_PCM_16_BIT) ? 2 : 4); mConfig.format = transferAudioFormatToPcmFormat(mStreamAttributeTarget.audio_format); mConfig.start_threshold = 0; mConfig.stop_threshold = 0; mConfig.silence_threshold = 0; ALOGD("%s(), mConfig: channels = %d, rate = %d, period_size = %d, period_count = %d, format = %d", __FUNCTION__, mConfig.channels, mConfig.rate, mConfig.period_size, mConfig.period_count, mConfig.format); // post processing initPostProcessing(); #if defined(MTK_SPEAKER_MONITOR_SUPPORT) unsigned int fc, bw; int th; if (mAudioFilterManagerHandler) { AudioALSASpeakerMonitor::getInstance()->GetFilterParam(&fc, &bw, &th); ALOGD("%s(), fc %d bw %d, th %d", __FUNCTION__, fc, bw, th); mAudioFilterManagerHandler->setSpkFilterParam(fc, bw, th); } #endif // SRC initBliSrc(); // bit conversion initBitConverter(); initDataPending(); // disable lowjitter mode SetLowJitterMode(true, mStreamAttributeTarget.sample_rate); // open pcm driver openPcmDriver(pcmindex); // open codec driver mHardwareResourceManager->startOutputDevice(mStreamAttributeSource->output_devices, mStreamAttributeTarget.sample_rate); //============Voice UI&Unlock REFERECE============= AudioVUnlockDL *VUnlockhdl = AudioVUnlockDL::getInstance(); if (VUnlockhdl != NULL) { VUnlockhdl->SetInputStandBy(false); VUnlockhdl-> GetSRCInputParameter(mStreamAttributeTarget.sample_rate, mStreamAttributeTarget.num_channels, mStreamAttributeTarget.audio_format); VUnlockhdl->GetFirstDLTime(); } //=========================================== ALOGD("-%s()", __FUNCTION__); return NO_ERROR; }
static gboolean gst_tinyalsa_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec) { GstTinyalsaSink *sink = GST_TINYALSA_SINK (asink); struct pcm_config config = { 0, }; struct pcm_params *params = NULL; int period_size_min, period_size_max; int periods_min, periods_max; pcm_config_from_spec (&config, spec); GST_DEBUG_OBJECT (sink, "Requesting %u periods of %u frames", config.period_count, config.period_size); params = pcm_params_get (sink->card, sink->device, PCM_OUT); if (!params) GST_ERROR_OBJECT (sink, "Could not get PCM params"); period_size_min = pcm_params_get_min (params, PCM_PARAM_PERIOD_SIZE); period_size_max = pcm_params_get_max (params, PCM_PARAM_PERIOD_SIZE); periods_min = pcm_params_get_min (params, PCM_PARAM_PERIODS); periods_max = pcm_params_get_max (params, PCM_PARAM_PERIODS); pcm_params_free (params); /* Snap period size/count to the permitted range */ config.period_size = CLAMP (config.period_size, period_size_min, period_size_max); config.period_count = CLAMP (config.period_count, periods_min, periods_max); /* mutex with getcaps */ GST_OBJECT_LOCK (sink); sink->pcm = pcm_open (sink->card, sink->device, PCM_OUT | PCM_NORESTART, &config); GST_OBJECT_UNLOCK (sink); if (!sink->pcm || !pcm_is_ready (sink->pcm)) { GST_ERROR_OBJECT (sink, "Could not open device: %s", pcm_get_error (sink->pcm)); goto fail; } if (pcm_prepare (sink->pcm) < 0) { GST_ERROR_OBJECT (sink, "Could not prepare device: %s", pcm_get_error (sink->pcm)); goto fail; } spec->segsize = pcm_frames_to_bytes (sink->pcm, config.period_size); spec->segtotal = config.period_count; GST_DEBUG_OBJECT (sink, "Configured for %u periods of %u frames", config.period_count, config.period_size); return TRUE; fail: if (sink->pcm) pcm_close (sink->pcm); return FALSE; }
static GstCaps * gst_tinyalsa_sink_getcaps (GstBaseSink * bsink, GstCaps * filter) { GstTinyalsaSink *sink = GST_TINYALSA_SINK (bsink); GstCaps *caps = NULL; GValue formats = { 0, }; GValue format = { 0, }; struct pcm_params *params = NULL; struct pcm_mask *mask; int rate_min, rate_max, channels_min, channels_max; guint16 m; GST_DEBUG_OBJECT (sink, "Querying caps"); GST_OBJECT_LOCK (sink); if (sink->cached_caps) { GST_DEBUG_OBJECT (sink, "Returning cached caps"); caps = gst_caps_ref (sink->cached_caps); goto done; } if (sink->pcm) { /* We can't query the device while it's open, so return current caps */ caps = gst_pad_get_current_caps (GST_BASE_SINK_PAD (bsink)); goto done; } params = pcm_params_get (sink->card, sink->device, PCM_OUT); if (!params) { GST_ERROR_OBJECT (sink, "Could not get PCM params"); goto done; } mask = pcm_params_get_mask (params, PCM_PARAM_FORMAT); m = (mask->bits[1] << 8) | mask->bits[0]; if (!(m & SNDRV_PCM_FORMAT_ANY)) { GST_ERROR_OBJECT (sink, "Could not find any supported format"); goto done; } caps = gst_caps_new_empty_simple ("audio/x-raw"); g_value_init (&formats, GST_TYPE_LIST); g_value_init (&format, G_TYPE_STRING); if (m & (1 << SNDRV_PCM_FORMAT_S8)) { g_value_set_static_string (&format, "S8"); gst_value_list_prepend_value (&formats, &format); } if (m & (1 << SNDRV_PCM_FORMAT_S16_LE)) { g_value_set_static_string (&format, "S16LE"); gst_value_list_prepend_value (&formats, &format); } if (m & (1 << SNDRV_PCM_FORMAT_S24_LE)) { g_value_set_static_string (&format, "S24_32LE"); gst_value_list_prepend_value (&formats, &format); } if (m & (1 << SNDRV_PCM_FORMAT_S32_LE)) { g_value_set_static_string (&format, "S32LE"); gst_value_list_prepend_value (&formats, &format); } gst_caps_set_value (caps, "format", &formats); g_value_unset (&format); g_value_unset (&formats); /* This is a bit of a lie, since the device likely only supports some * standard rates in this range. We should probably filter the range to * those, standard audio rates but even that isn't guaranteed to be accurate. */ rate_min = pcm_params_get_min (params, PCM_PARAM_RATE); rate_max = pcm_params_get_max (params, PCM_PARAM_RATE); if (rate_min == rate_max) gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate_min, NULL); else gst_caps_set_simple (caps, "rate", GST_TYPE_INT_RANGE, rate_min, rate_max, NULL); channels_min = pcm_params_get_min (params, PCM_PARAM_CHANNELS); channels_max = pcm_params_get_max (params, PCM_PARAM_CHANNELS); if (channels_min == channels_max) gst_caps_set_simple (caps, "channels", G_TYPE_INT, channels_min, NULL); else gst_caps_set_simple (caps, "channels", GST_TYPE_INT_RANGE, channels_min, channels_max, NULL); gst_caps_replace (&sink->cached_caps, caps); done: GST_OBJECT_UNLOCK (sink); GST_DEBUG_OBJECT (sink, "Got caps %" GST_PTR_FORMAT, caps); if (caps && filter) { GstCaps *intersection = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (caps); caps = intersection; } if (params) pcm_params_free (params); return caps; }
int main(int argc, char **argv) { unsigned int device = 0; unsigned int card = 0; int i; if (argc < 3) { fprintf(stderr, "Usage: %s -D card -d device\n", argv[0]); return 1; } /* parse command line arguments */ argv += 1; while (*argv) { if (strcmp(*argv, "-D") == 0) { argv++; if (*argv) card = atoi(*argv); } if (strcmp(*argv, "-d") == 0) { argv++; if (*argv) device = atoi(*argv); } if (*argv) argv++; } printf("Info for card %u, device %u:\n", card, device); for (i = 0; i < 2; i++) { struct pcm_params *params; struct pcm_mask *m; unsigned int min; unsigned int max; printf("\nPCM %s:\n", i == 0 ? "out" : "in"); params = pcm_params_get(card, device, i == 0 ? PCM_OUT : PCM_IN); if (params == NULL) { printf("Device does not exist.\n"); continue; } m = pcm_params_get_mask(params, PCM_PARAM_ACCESS); if (m) { /* bitmask, refer to SNDRV_PCM_ACCESS_*, generally interleaved */ printf(" Access:\t%#08x\n", m->bits[0]); } m = pcm_params_get_mask(params, PCM_PARAM_FORMAT); if (m) { /* bitmask, refer to: SNDRV_PCM_FORMAT_* */ unsigned j, k, count = 0; const unsigned bitcount = sizeof(m->bits[0]) * 8; /* we only check first two format masks (out of 8) - others are zero. */ printf(" Format[0]:\t%#08x\n", m->bits[0]); printf(" Format[1]:\t%#08x\n", m->bits[1]); /* print friendly format names, if they exist */ for (k = 0; k < 2; ++k) { for (j = 0; j < bitcount; ++j) { const char *name; if (m->bits[k] & (1 << j)) { name = pcm_get_format_name(j + k*bitcount); if (name) { if (count++ == 0) { printf(" Format Name:\t"); } else { printf (", "); } printf("%s", name); } } } } if (count) { printf("\n"); } } m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT); if (m) { /* bitmask, should be 1: SNDRV_PCM_SUBFORMAT_STD */ printf(" Subformat:\t%#08x\n", m->bits[0]); } min = pcm_params_get_min(params, PCM_PARAM_RATE); max = pcm_params_get_max(params, PCM_PARAM_RATE); printf(" Rate:\tmin=%uHz\tmax=%uHz\n", min, max); min = pcm_params_get_min(params, PCM_PARAM_CHANNELS); max = pcm_params_get_max(params, PCM_PARAM_CHANNELS); printf(" Channels:\tmin=%u\t\tmax=%u\n", min, max); min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS); max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS); printf(" Sample bits:\tmin=%u\t\tmax=%u\n", min, max); min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE); max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE); printf(" Period size:\tmin=%u\t\tmax=%u\n", min, max); min = pcm_params_get_min(params, PCM_PARAM_PERIODS); max = pcm_params_get_max(params, PCM_PARAM_PERIODS); printf("Period count:\tmin=%u\t\tmax=%u\n", min, max); pcm_params_free(params); } return 0; }
status_t AudioALSAPlaybackHandlerSphDL::open() { ALOGD("+%s(), mDevice = 0x%x", __FUNCTION__, mStreamAttributeSource->output_devices); // debug pcm dump OpenPCMDump(LOG_TAG); int pcmindex = AudioALSADeviceParser::getInstance()->GetPcmIndexByString(keypcmI2S0Dl1Playback); int cardindex = AudioALSADeviceParser::getInstance()->GetCardIndexByString(keypcmI2S0Dl1Playback); ALOGD("AudioALSAPlaybackHandlerSphDL::open() pcmindex = %d", pcmindex); ListPcmDriver(cardindex, pcmindex); struct pcm_params *params; params = pcm_params_get(cardindex, pcmindex, PCM_OUT); if (params == NULL) { ALOGD("Device does not exist.\n"); } mStreamAttributeTarget.buffer_size = pcm_params_get_max(params, PCM_PARAM_BUFFER_BYTES); ALOGD("buffersizemax = %d", mStreamAttributeTarget.buffer_size); pcm_params_free(params); // HW attribute config // TODO(Harvey): query this mStreamAttributeTarget.audio_format = AUDIO_FORMAT_PCM_16_BIT; mStreamAttributeTarget.audio_channel_mask = AUDIO_CHANNEL_IN_MONO; mStreamAttributeTarget.num_channels = android_audio_legacy::AudioSystem::popCount(mStreamAttributeTarget.audio_channel_mask); mStreamAttributeTarget.sample_rate = mStreamAttributeSource->sample_rate; // same as source stream // HW pcm config mConfig.channels = mStreamAttributeTarget.num_channels; mConfig.rate = mStreamAttributeTarget.sample_rate; // Buffer size: 1536(period_size) * 2(ch) * 4(byte) * 2(period_count) = 24 kb mConfig.period_count = 4; //mConfig.period_size = (0x4000/(mConfig.channels*mConfig.period_count))/((mStreamAttributeTarget.audio_format == AUDIO_FORMAT_PCM_16_BIT) ? 2 : 4); mConfig.period_size = 512; mConfig.format = transferAudioFormatToPcmFormat(mStreamAttributeTarget.audio_format); mConfig.start_threshold = 0; mConfig.stop_threshold = 0; mConfig.silence_threshold = 0; ALOGD("%s(), mConfig: channels = %d, rate = %d, period_size = %d, period_count = %d, format = %d", __FUNCTION__, mConfig.channels, mConfig.rate, mConfig.period_size, mConfig.period_count, mConfig.format); // post processing initPostProcessing(); #if defined(MTK_SPEAKER_MONITOR_SUPPORT) unsigned int fc, bw; int th; if (mAudioFilterManagerHandler) { AudioALSASpeakerMonitor::getInstance()->GetFilterParam(&fc, &bw, &th); ALOGD("%s(), fc %d bw %d, th %d", __FUNCTION__, fc, bw, th); mAudioFilterManagerHandler->setSpkFilterParam(fc, bw, th); } #endif // SRC initBliSrc(); // bit conversion initBitConverter(); // open pcm driver openPcmDriver(pcmindex); //Echo reference path if (mixer_ctl_set_enum_by_string(mixer_get_ctl_by_name(mMixer, "Audio_Dl1_MD_Echo_Ref_Switch"), "On")) { ALOGE("Error: Audio_Dl1_MD_Echo_Ref_Switch invalid value"); } // open codec driver // Don't startoutputDevice here, let speech driver to open. mHardwareResourceManager->startOutputDevice(mStreamAttributeSource->output_devices, mStreamAttributeTarget.sample_rate); ALOGD("-%s()", __FUNCTION__); return NO_ERROR; }
status_t AudioALSAPlaybackHandlerOffload::open() { ALOGD("+%s(), mDevice = 0x%x", __FUNCTION__, mStreamAttributeSource->output_devices); ALOGD("%s(), mStreamAttributeSource: format = %d",__FUNCTION__, mStreamAttributeSource->audio_format); AudioAutoTimeoutLock _l(*AudioALSADriverUtility::getInstance()->getStreamSramDramLock()); // debug pcm dump OpenPCMDump(LOG_TAG); // acquire pmic clk mHardwareResourceManager->EnableAudBufClk(true); //doug to check //HpImpeDanceDetect(); //doug to check #if 1 int pcmindex = AudioALSADeviceParser::getInstance()->GetPcmIndexByString(keypcmDl1Meida); int cardindex = AudioALSADeviceParser::getInstance()->GetCardIndexByString(keypcmDl1Meida); ALOGD("AudioALSAPlaybackHandlerOffload::open() pcmindex = %d", pcmindex); ListPcmDriver(cardindex, pcmindex); struct pcm_params *params; params = pcm_params_get(cardindex, pcmindex, PCM_OUT); if (params == NULL) { ALOGD("Device does not exist.\n"); } mStreamAttributeTarget.buffer_size = pcm_params_get_max(params, PCM_PARAM_BUFFER_BYTES); ALOGD("%s buffersizemax = %d", __FUNCTION__, mStreamAttributeTarget.buffer_size); pcm_params_free(params); #endif //mStreamAttributeTarget.buffer_size = 32768; //#ifdef PLAYBACK_USE_24BITS_ONLY //mStreamAttributeTarget.audio_format = AUDIO_FORMAT_PCM_32_BIT; mStreamAttributeTarget.audio_format = AUDIO_FORMAT_PCM_8_24_BIT; //mStreamAttributeTarget.audio_format = AUDIO_FORMAT_PCM_16_BIT; //#else // mStreamAttributeTarget.audio_format = (mStreamAttributeSource->audio_format == AUDIO_FORMAT_PCM_32_BIT) ? AUDIO_FORMAT_PCM_8_24_BIT : AUDIO_FORMAT_PCM_16_BIT; //#endif mStreamAttributeTarget.audio_channel_mask = AUDIO_CHANNEL_IN_STEREO; mStreamAttributeTarget.num_channels = android_audio_legacy::AudioSystem::popCount(mStreamAttributeTarget.audio_channel_mask); mStreamAttributeTarget.sample_rate = ChooseTargetSampleRate(mStreamAttributeSource->sample_rate); // HW pcm config mConfig.channels = mStreamAttributeTarget.num_channels; mConfig.rate = mStreamAttributeTarget.sample_rate; // Buffer size: 1536(period_size) * 2(ch) * 4(byte) * 2(period_count) = 24 kb mConfig.period_count = 2; mConfig.period_size = (mStreamAttributeTarget.buffer_size / (mConfig.channels * mConfig.period_count)) / ((mStreamAttributeTarget.audio_format == AUDIO_FORMAT_PCM_16_BIT) ? 2 : 4); mConfig.format = transferAudioFormatToPcmFormat(mStreamAttributeTarget.audio_format); mConfig.start_threshold = 0; mConfig.stop_threshold = 0; mConfig.silence_threshold = 0; ALOGD("%s(), mConfig: channels = %d, rate = %d, period_size = %d, period_count = %d, format = %d", __FUNCTION__, mConfig.channels, mConfig.rate, mConfig.period_size, mConfig.period_count, mConfig.format); mComprConfig.codec = (struct snd_codec*)malloc(sizeof(struct snd_codec)); if(mComprConfig.codec == NULL) ALOGE("%s(), allocate mComprConfig.codec fail"); mComprConfig.fragments = 1024; mComprConfig.fragment_size = 8192; //mComprConfig.fragment_size = mStreamAttributeTarget.buffer_size; mComprConfig.codec->sample_rate = mStreamAttributeTarget.sample_rate; mComprConfig.codec->reserved[0] = mConfig.period_size; mComprConfig.codec->reserved[1] = mComprConfig.fragments*mComprConfig.fragment_size; if(mConfig.format == PCM_FORMAT_S16_LE) mComprConfig.codec->format = SNDRV_PCM_FORMAT_S16_LE; else mComprConfig.codec->format = SNDRV_PCM_FORMAT_S32_LE; mComprConfig.codec->id = SND_AUDIOCODEC_MP3; mComprConfig.codec->ch_in = 2; mComprConfig.codec->ch_out = 2; //init decoder mDecHandler = AudioDecHandlerCreate(); if(mDecHandler == NULL) { ALOGE("+%s(), DecHandler create fail", __FUNCTION__); ASSERT(false); return -ENOSYS; } if(!mDecHandler->InitAudioDecoder()) { ALOGE("+%s(), Decoder IP init fail", __FUNCTION__); ASSERT(false); return -ENOSYS; } // post processing initPostProcessing(); // SRC initBliSrc(); // bit conversion initBitConverter(); initDataPending(); // disable lowjitter mode //doug to check SetLowJitterMode(true, mStreamAttributeTarget.sample_rate); openComprDriver(23); if( compress_set_gapless_metadata(mComprStream, &offload_stream.offload_mdata) != 0) ALOGE("%s(), compress_set_gapless_metadata() error= %s", __FUNCTION__, compress_get_error(mComprStream)); mHardwareResourceManager->startOutputDevice(mStreamAttributeSource->output_devices, mStreamAttributeTarget.sample_rate); offload_stream.tmpBuffer = (void*)malloc(mComprConfig.fragment_size); mWritebytes = mComprConfig.fragment_size; list_init(&offload_stream.offload_cmd_list); int ret = pthread_mutex_init(&offload_stream.offload_mutex, NULL); if (ret != 0) { ALOGE("%s, Failed to initialize Mutex!", __FUNCTION__); ASSERT(false); return -ENOSYS; } ret = pthread_cond_init(&offload_stream.offload_cond, NULL); if (ret != 0) { ALOGE("%s, Failed to initialize Cond!", __FUNCTION__); ASSERT(false); return -ENOSYS; } threadExit = false; ret = pthread_create(&offload_stream.offload_pthread, NULL, &offload_threadloop, this); if (ret != 0) { ALOGE("%s() create thread OffloadWrite fail!!", __FUNCTION__); ASSERT(false); return -ENOSYS; } usleep(1 * 1000); ALOGD("-%s()", __FUNCTION__); return NO_ERROR; }
static int validate_input_hardware_params(struct stream_in *in) { struct audio_device *adev = in->dev; struct pcm_params *params; unsigned int min; unsigned int max; params = pcm_params_get(adev->card, adev->device, PCM_IN); if (params == NULL) { ALOGW("Device does not exist.\n"); return -1; } /* always open the device with min capabilities if * input params are not supported */ min = pcm_params_get_min(params, PCM_PARAM_RATE); max = pcm_params_get_max(params, PCM_PARAM_RATE); ALOGI("hw supported Rate:\tmin=%uHz\tmax=%uHz\n", min, max); if((in->pcm_config.rate < min) || (in->pcm_config.rate > max)) { in->pcm_config.rate = min; } min = pcm_params_get_min(params, PCM_PARAM_CHANNELS); max = pcm_params_get_max(params, PCM_PARAM_CHANNELS); ALOGI("hw supported Channels:\tmin=%u\t\tmax=%u\n", min, max); if((in->pcm_config.channels < min) || (in->pcm_config.channels > max)) { in->pcm_config.channels = min; } min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS); max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS); ALOGI("hw supported Sample bits:\tmin=%u\t\tmax=%u\n", min, max); unsigned int bits_per_sample = format_to_bits(in->pcm_config.format); if((bits_per_sample < min) || (bits_per_sample > max)) { bits_per_sample = min; } in->pcm_config.format = bits_to_format(bits_per_sample); min = pcm_params_get_min(params, PCM_PARAM_PERIODS); max = pcm_params_get_max(params, PCM_PARAM_PERIODS); ALOGI("hw supported period_count:\tmin=%u\t\tmax=%u\n", min, max); if((in->pcm_config.period_count < min) || (in->pcm_config.period_count > max)) { in->pcm_config.period_count = min; } min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE); max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE); ALOGI("hw supported period_size:\tmin=%u\t\tmax=%u\n", min, max); if((in->pcm_config.period_size < min) || (in->pcm_config.period_size > max)) { in->pcm_config.period_size = min; } ALOGV("%s :: Exit supported params \ \r \t channels = %d, \ \r \t rate = %d, \ \r \t period_size = %d, \ \r \t period_count = %d, \ \r \t format = %d", __func__, in->pcm_config.channels,in->pcm_config.rate, in->pcm_config.period_size,in->pcm_config.period_count, in->pcm_config.format); pcm_params_free(params); return 0; }