/**************************************************************************** * configurations */ static void systest_list_audio_devs() { unsigned i, dev_count; pj_size_t len=0; pj_status_t status; test_item_t *ti; enum gui_key key; const char *title = "Audio Device List"; ti = systest_alloc_test_item(title); if (!ti) return; PJ_LOG(3,(THIS_FILE, "Running %s", title)); dev_count = pjmedia_aud_dev_count(); if (dev_count == 0) { key = gui_msgbox(title, "No audio devices are found", WITH_OK); ti->success = PJ_FALSE; pj_ansi_strcpy(ti->reason, "No device found"); return; } pj_ansi_snprintf(ti->reason+len, sizeof(ti->reason)-len, "Found %u devices\r\n", dev_count); len = strlen(ti->reason); for (i=0; i<dev_count; ++i) { pjmedia_aud_dev_info info; status = pjmedia_aud_dev_get_info(i, &info); if (status != PJ_SUCCESS) { systest_perror("Error retrieving device info: ", status); ti->success = PJ_FALSE; pj_strerror(status, ti->reason, sizeof(ti->reason)); return; } pj_ansi_snprintf(ti->reason+len, sizeof(ti->reason)-len, " %2d: %s [%s] (%d/%d)\r\n", i, info.driver, info.name, info.input_count, info.output_count); len = strlen(ti->reason); } ti->reason[len] = '\0'; key = gui_msgbox(title, ti->reason, WITH_OK); PJ_UNUSED_ARG(key); ti->success = PJ_TRUE; }
PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index) { pjmedia_snd_dev_info *oi = &g_sys.info[g_sys.info_counter]; pjmedia_aud_dev_info di; g_sys.info_counter = (g_sys.info_counter+1) % PJ_ARRAY_SIZE(g_sys.info); if (pjmedia_aud_dev_get_info(index, &di) != PJ_SUCCESS) return NULL; pj_bzero(oi, sizeof(*oi)); pj_ansi_strncpy(oi->name, di.name, sizeof(oi->name)); oi->name[sizeof(oi->name)-1] = '\0'; oi->input_count = di.input_count; oi->output_count = di.output_count; oi->default_samples_per_sec = di.default_samples_per_sec; return oi; }
int main() { pj_init(); pjmedia_aud_dev_index dev_idx; pjmedia_endpt *ep; pj_caching_pool cp; pj_caching_pool_init(&cp, 0, 1024); pjmedia_endpt_create(&cp.factory, NULL, 1, &ep); int dev_cnt; dev_cnt = pjmedia_aud_dev_count(); printf("Got %d audio devices\n", dev_cnt); for (dev_idx=0; dev_idx < dev_cnt; ++dev_idx) { pjmedia_aud_dev_info info; CHECK(__FILE__, pjmedia_aud_dev_get_info(dev_idx, &info)); printf("%d. %s (in=%d, out=%d)\n", dev_idx, info.name, info.input_count, info.output_count); } return 0; }
static void list_devices(void) { unsigned i; pj_status_t status; dev_count = pjmedia_aud_dev_count(); if (dev_count == 0) { PJ_LOG(3,(THIS_FILE, "No devices found")); return; } PJ_LOG(3,(THIS_FILE, "Found %d devices:", dev_count)); for (i=0; i<dev_count; ++i) { pjmedia_aud_dev_info info; status = pjmedia_aud_dev_get_info(i, &info); if (status != PJ_SUCCESS) continue; PJ_LOG(3,(THIS_FILE," %2d: %s [%s] (%d/%d)", i, info.driver, info.name, info.input_count, info.output_count)); } }
/* * Start the sound stream. * This may be called even when the sound stream has already been started. */ static pj_status_t start_sound_device( pj_pool_t *pool, pjmedia_snd_port *snd_port ) { pjmedia_aud_rec_cb snd_rec_cb; pjmedia_aud_play_cb snd_play_cb; pjmedia_aud_param param_copy; pj_status_t status; /* Check if sound has been started. */ if (snd_port->aud_stream != NULL) return PJ_SUCCESS; PJ_ASSERT_RETURN(snd_port->dir == PJMEDIA_DIR_CAPTURE || snd_port->dir == PJMEDIA_DIR_PLAYBACK || snd_port->dir == PJMEDIA_DIR_CAPTURE_PLAYBACK, PJ_EBUG); /* Get device caps */ if (snd_port->aud_param.dir & PJMEDIA_DIR_CAPTURE) { pjmedia_aud_dev_info dev_info; status = pjmedia_aud_dev_get_info(snd_port->aud_param.rec_id, &dev_info); if (status != PJ_SUCCESS) return status; snd_port->aud_caps = dev_info.caps; } else { snd_port->aud_caps = 0; } /* Process EC settings */ pj_memcpy(¶m_copy, &snd_port->aud_param, sizeof(param_copy)); if (param_copy.flags & PJMEDIA_AUD_DEV_CAP_EC) { /* EC is wanted */ if ((snd_port->prm_ec_options & PJMEDIA_ECHO_USE_SW_ECHO) == 0 && (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC)) { /* Device supports EC */ /* Nothing to do */ } else { /* Application wants to use software EC or device * doesn't support EC, remove EC settings from * device parameters */ param_copy.flags &= ~(PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); } } /* Use different callback if format is not PCM */ if (snd_port->aud_param.ext_fmt.id == PJMEDIA_FORMAT_L16) { snd_rec_cb = &rec_cb; snd_play_cb = &play_cb; } else { snd_rec_cb = &rec_cb_ext; snd_play_cb = &play_cb_ext; } /* Open the device */ status = pjmedia_aud_stream_create(¶m_copy, snd_rec_cb, snd_play_cb, snd_port, &snd_port->aud_stream); if (status != PJ_SUCCESS) return status; /* Inactivity limit before EC is suspended. */ snd_port->ec_suspend_limit = AEC_SUSPEND_LIMIT * (snd_port->clock_rate / snd_port->samples_per_frame); /* Create software EC if parameter specifies EC and * (app specifically requests software EC or device * doesn't support EC). Only do this if the format is PCM! */ if ((snd_port->aud_param.flags & PJMEDIA_AUD_DEV_CAP_EC) && ((snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC)==0 || (snd_port->prm_ec_options & PJMEDIA_ECHO_USE_SW_ECHO) != 0) && param_copy.ext_fmt.id == PJMEDIA_FORMAT_PCM) { if ((snd_port->aud_param.flags & PJMEDIA_AUD_DEV_CAP_EC_TAIL)==0) { snd_port->aud_param.flags |= PJMEDIA_AUD_DEV_CAP_EC_TAIL; snd_port->aud_param.ec_tail_ms = AEC_TAIL; PJ_LOG(4,(THIS_FILE, "AEC tail is set to default %u ms", snd_port->aud_param.ec_tail_ms)); } status = pjmedia_snd_port_set_ec(snd_port, pool, snd_port->aud_param.ec_tail_ms, snd_port->prm_ec_options); if (status != PJ_SUCCESS) { pjmedia_aud_stream_destroy(snd_port->aud_stream); snd_port->aud_stream = NULL; return status; } } /* Start sound stream. */ if (!(snd_port->options & PJMEDIA_SND_PORT_NO_AUTO_START)) { status = pjmedia_aud_stream_start(snd_port->aud_stream); } if (status != PJ_SUCCESS) { pjmedia_aud_stream_destroy(snd_port->aud_stream); snd_port->aud_stream = NULL; return status; } return PJ_SUCCESS; }
static void systest_display_settings(void) { pjmedia_aud_dev_info di; pj_size_t len = 0; enum gui_key key; test_item_t *ti; const char *title = "Audio Settings"; pj_status_t status; ti = systest_alloc_test_item(title); if (!ti) return; PJ_LOG(3,(THIS_FILE, "Running %s", title)); pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Version: %s\r\n", pj_get_version()); len = strlen(textbuf); pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Test clock rate: %d\r\n", systest.media_cfg.clock_rate); len = strlen(textbuf); pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Device clock rate: %d\r\n", systest.media_cfg.snd_clock_rate); len = strlen(textbuf); pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Aud frame ptime: %d\r\n", systest.media_cfg.audio_frame_ptime); len = strlen(textbuf); pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Channel count: %d\r\n", systest.media_cfg.channel_count); len = strlen(textbuf); pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Audio switching: %s\r\n", (PJMEDIA_CONF_USE_SWITCH_BOARD ? "Switchboard" : "Conf bridge")); len = strlen(textbuf); pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Snd buff count: %d\r\n", PJMEDIA_SOUND_BUFFER_COUNT); len = strlen(textbuf); /* Capture device */ status = pjmedia_aud_dev_get_info(systest.rec_id, &di); if (status != PJ_SUCCESS) { systest_perror("Error querying device info", status); ti->success = PJ_FALSE; pj_strerror(status, ti->reason, sizeof(ti->reason)); return; } pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Rec dev : %d (%s) [%s]\r\n", systest.rec_id, di.name, di.driver); len = strlen(textbuf); pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Rec buf : %d msec\r\n", systest.media_cfg.snd_rec_latency); len = strlen(textbuf); /* Playback device */ status = pjmedia_aud_dev_get_info(systest.play_id, &di); if (status != PJ_SUCCESS) { systest_perror("Error querying device info", status); return; } pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Play dev: %d (%s) [%s]\r\n", systest.play_id, di.name, di.driver); len = strlen(textbuf); pj_ansi_snprintf(textbuf+len, sizeof(textbuf)-len, "Play buf: %d msec\r\n", systest.media_cfg.snd_play_latency); len = strlen(textbuf); ti->success = PJ_TRUE; pj_ansi_strncpy(ti->reason, textbuf, sizeof(ti->reason)); ti->reason[sizeof(ti->reason)-1] = '\0'; key = gui_msgbox(title, textbuf, WITH_OK); PJ_UNUSED_ARG(key); /* Warning about unused var */ }
/* Application init */ static pj_status_t app_init() { unsigned i, count; pj_status_t status; /* Redirect log */ pj_log_set_log_func((void (*)(int,const char*,int)) &log_writer); pj_log_set_decor(PJ_LOG_HAS_NEWLINE); pj_log_set_level(3); /* Init pjlib */ status = pj_init(); if (status != PJ_SUCCESS) { app_perror("pj_init()", status); return status; } pj_caching_pool_init(&cp, NULL, 0); /* Init sound subsystem */ status = pjmedia_aud_subsys_init(&cp.factory); if (status != PJ_SUCCESS) { app_perror("pjmedia_snd_init()", status); pj_caching_pool_destroy(&cp); pj_shutdown(); return status; } count = pjmedia_aud_dev_count(); PJ_LOG(3,(THIS_FILE, "Device count: %d", count)); for (i=0; i<count; ++i) { pjmedia_aud_dev_info info; pj_status_t status; status = pjmedia_aud_dev_get_info(i, &info); pj_assert(status == PJ_SUCCESS); PJ_LOG(3, (THIS_FILE, "%d: %s %d/%d %dHz", i, info.name, info.input_count, info.output_count, info.default_samples_per_sec)); unsigned j; /* Print extended formats supported by this audio device */ PJ_LOG(3, (THIS_FILE, " Extended formats supported:")); for (j = 0; j < info.ext_fmt_cnt; ++j) { const char *fmt_name = NULL; switch (info.ext_fmt[j].id) { case PJMEDIA_FORMAT_PCMA: fmt_name = "PCMA"; break; case PJMEDIA_FORMAT_PCMU: fmt_name = "PCMU"; break; case PJMEDIA_FORMAT_AMR: fmt_name = "AMR-NB"; break; case PJMEDIA_FORMAT_G729: fmt_name = "G729"; break; case PJMEDIA_FORMAT_ILBC: fmt_name = "ILBC"; break; case PJMEDIA_FORMAT_PCM: fmt_name = "PCM"; break; default: fmt_name = "Unknown"; break; } PJ_LOG(3, (THIS_FILE, " - %s", fmt_name)); } } /* Create pool */ pool = pj_pool_create(&cp.factory, THIS_FILE, 512, 512, NULL); if (pool == NULL) { app_perror("pj_pool_create()", status); pj_caching_pool_destroy(&cp); pj_shutdown(); return status; } /* Init delay buffer */ status = pjmedia_delay_buf_create(pool, THIS_FILE, CLOCK_RATE, SAMPLES_PER_FRAME, CHANNEL_COUNT, 0, 0, &delaybuf); if (status != PJ_SUCCESS) { app_perror("pjmedia_delay_buf_create()", status); //pj_caching_pool_destroy(&cp); //pj_shutdown(); //return status; } return PJ_SUCCESS; }
static void show_dev_info(unsigned index) { #define H "%-20s" pjmedia_aud_dev_info info; char formats[200]; pj_status_t status; if (index >= dev_count) { PJ_LOG(1,(THIS_FILE, "Error: invalid index %u", index)); return; } status = pjmedia_aud_dev_get_info(index, &info); if (status != PJ_SUCCESS) { app_perror("pjmedia_aud_dev_get_info() error", status); return; } PJ_LOG(3, (THIS_FILE, "Device at index %u:", index)); PJ_LOG(3, (THIS_FILE, "-------------------------")); PJ_LOG(3, (THIS_FILE, H": %u (0x%x)", "ID", index, index)); PJ_LOG(3, (THIS_FILE, H": %s", "Name", info.name)); PJ_LOG(3, (THIS_FILE, H": %s", "Driver", info.driver)); PJ_LOG(3, (THIS_FILE, H": %u", "Input channels", info.input_count)); PJ_LOG(3, (THIS_FILE, H": %u", "Output channels", info.output_count)); PJ_LOG(3, (THIS_FILE, H": %s", "Capabilities", decode_caps(info.caps))); formats[0] = '\0'; if (info.caps & PJMEDIA_AUD_DEV_CAP_EXT_FORMAT) { unsigned i; for (i=0; i<info.ext_fmt_cnt; ++i) { char bitrate[32]; switch (info.ext_fmt[i].id) { case PJMEDIA_FORMAT_L16: strcat(formats, "L16/"); break; case PJMEDIA_FORMAT_PCMA: strcat(formats, "PCMA/"); break; case PJMEDIA_FORMAT_PCMU: strcat(formats, "PCMU/"); break; case PJMEDIA_FORMAT_AMR: strcat(formats, "AMR/"); break; case PJMEDIA_FORMAT_G729: strcat(formats, "G729/"); break; case PJMEDIA_FORMAT_ILBC: strcat(formats, "ILBC/"); break; default: strcat(formats, "unknown/"); break; } sprintf(bitrate, "%u", info.ext_fmt[i].det.aud.avg_bps); strcat(formats, bitrate); strcat(formats, " "); } } PJ_LOG(3, (THIS_FILE, H": %s", "Extended formats", formats)); #undef H }
/* * Start the sound stream. * This may be called even when the sound stream has already been started. */ static pj_status_t start_sound_device( pj_pool_t *pool, pjmedia_snd_port *snd_port ) { int i;float f; pjmedia_aud_rec_cb snd_rec_cb; pjmedia_aud_play_cb snd_play_cb; pjmedia_aud_param param_copy; pj_status_t status; /* Check if sound has been started. */ if (snd_port->aud_stream != NULL) return PJ_SUCCESS; PJ_ASSERT_RETURN(snd_port->dir == PJMEDIA_DIR_CAPTURE || snd_port->dir == PJMEDIA_DIR_PLAYBACK || snd_port->dir == PJMEDIA_DIR_CAPTURE_PLAYBACK, PJ_EBUG); /* Get device caps */ if (snd_port->aud_param.dir & PJMEDIA_DIR_CAPTURE) { pjmedia_aud_dev_info dev_info; status = pjmedia_aud_dev_get_info(snd_port->aud_param.rec_id, &dev_info); if (status != PJ_SUCCESS) return status; snd_port->aud_caps = dev_info.caps; } else { snd_port->aud_caps = 0; } /* Process EC settings */ pj_memcpy(¶m_copy, &snd_port->aud_param, sizeof(param_copy)); if (param_copy.flags & PJMEDIA_AUD_DEV_CAP_EC) { /* EC is wanted */ if ((snd_port->prm_ec_options & PJMEDIA_ECHO_USE_SW_ECHO) == 0 && (snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC)) { /* Device supports EC */ /* Nothing to do */ } else { /* Application wants to use software EC or device * doesn't support EC, remove EC settings from * device parameters */ param_copy.flags &= ~(PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL); } } /* Use different callback if format is not PCM */ if (snd_port->aud_param.ext_fmt.id == PJMEDIA_FORMAT_L16) { snd_rec_cb = &rec_cb; snd_play_cb = &play_cb; } else { snd_rec_cb = &rec_cb_ext; snd_play_cb = &play_cb_ext; } /* Open the device */ status = pjmedia_aud_stream_create(¶m_copy, snd_rec_cb, snd_play_cb, snd_port, &snd_port->aud_stream); if (status != PJ_SUCCESS) return status; /* Inactivity limit before EC is suspended. */ snd_port->ec_suspend_limit = AEC_SUSPEND_LIMIT * (snd_port->clock_rate / snd_port->samples_per_frame); /* Create software EC if parameter specifies EC and * (app specifically requests software EC or device * doesn't support EC). Only do this if the format is PCM! */ if ((snd_port->aud_param.flags & PJMEDIA_AUD_DEV_CAP_EC) && ((snd_port->aud_caps & PJMEDIA_AUD_DEV_CAP_EC)==0 || (snd_port->prm_ec_options & PJMEDIA_ECHO_USE_SW_ECHO) != 0) && param_copy.ext_fmt.id == PJMEDIA_FORMAT_PCM) { if ((snd_port->aud_param.flags & PJMEDIA_AUD_DEV_CAP_EC_TAIL)==0) { snd_port->aud_param.flags |= PJMEDIA_AUD_DEV_CAP_EC_TAIL; snd_port->aud_param.ec_tail_ms = AEC_TAIL; PJ_LOG(4,(THIS_FILE, "AEC tail is set to default %u ms", snd_port->aud_param.ec_tail_ms)); } status = pjmedia_snd_port_set_ec(snd_port, pool, snd_port->aud_param.ec_tail_ms, snd_port->prm_ec_options); if (status != PJ_SUCCESS) { pjmedia_aud_stream_destroy(snd_port->aud_stream); snd_port->aud_stream = NULL; return status; } } /* Start sound stream. */ if (!(snd_port->options & PJMEDIA_SND_PORT_NO_AUTO_START)) { status = pjmedia_aud_stream_start(snd_port->aud_stream); } if (status != PJ_SUCCESS) { pjmedia_aud_stream_destroy(snd_port->aud_stream); snd_port->aud_stream = NULL; return status; } #ifdef MY_SAVE_FILE_SEND if (fd_save !=NULL) fclose(fd_save); fd_save = fopen("/sdcard/send_data.pcm","wb"); if (fd_save == NULL) PJ_LOG(1,(THIS_FILE, "open /sdcard/send_data.pcm failed!")); #endif #ifdef MY_SAVE_FILE_BEFORE_SPEEX if (fd_bfspeex != NULL) fclose(fd_bfspeex); fd_bfspeex = fopen("/sdcard/send_data_bfspeex.pcm","wb"); if (fd_bfspeex == NULL) PJ_LOG(1,(THIS_FILE, "open /sdcard/send_data_bfspeex.pcm failed!")); #endif if (pjmedia_audio_use_speex_ns == PJ_TRUE) PJ_LOG(4,(THIS_FILE,"pjmedia_audio_use_speex_ns:true")); else PJ_LOG(4,(THIS_FILE,"pjmedia_audio_use_speex_ns:false")); if (pjmedia_audio_use_speex_ns == PJ_TRUE){ if (snd_port->speex_st){ PJ_LOG(4,(THIS_FILE, "speex noise suppress destroy")); speex_preprocess_state_destroy(snd_port->speex_st); } PJ_LOG(4,(THIS_FILE, "speex noise suppress start")); snd_port->speex_st =speex_preprocess_state_init(snd_port->samples_per_frame,snd_port->clock_rate); i=1; speex_preprocess_ctl(snd_port->speex_st, SPEEX_PREPROCESS_SET_DENOISE, &i); i=0; speex_preprocess_ctl(snd_port->speex_st, SPEEX_PREPROCESS_SET_AGC, &i); i=8000; speex_preprocess_ctl(snd_port->speex_st, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i); i=0; speex_preprocess_ctl(snd_port->speex_st, SPEEX_PREPROCESS_SET_DEREVERB, &i); f=.0; speex_preprocess_ctl(snd_port->speex_st, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f); f=.0; speex_preprocess_ctl(snd_port->speex_st, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f); #if 0 int vad = 1; int vadProbStart = 80; int vadProbContinue = 65; speex_preprocess_ctl(snd_port->speex_st, SPEEX_PREPROCESS_SET_VAD, &vad); //静音检测 speex_preprocess_ctl(snd_port->speex_st, SPEEX_PREPROCESS_SET_PROB_START , &vadProbStart); //Set probability required for the VAD to go from silence to voice speex_preprocess_ctl(snd_port->speex_st, SPEEX_PREPROCESS_SET_PROB_CONTINUE, &vadProbContinue); #endif } return PJ_SUCCESS; }