static void record(unsigned rec_index, const char *filename) { pj_pool_t *pool = NULL; pjmedia_port *wav = NULL; pjmedia_aud_param param; pjmedia_aud_stream *strm = NULL; char line[10], *dummy; pj_status_t status; if (filename == NULL) filename = WAV_FILE; pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav", 1000, 1000, NULL); status = pjmedia_wav_writer_port_create(pool, filename, 16000, 1, 320, 16, 0, 0, &wav); if (status != PJ_SUCCESS) { app_perror("Error creating WAV file", status); goto on_return; } status = pjmedia_aud_dev_default_param(rec_index, ¶m); if (status != PJ_SUCCESS) { app_perror("pjmedia_aud_dev_default_param()", status); goto on_return; } param.dir = PJMEDIA_DIR_CAPTURE; param.clock_rate = PJMEDIA_PIA_SRATE(&wav->info); param.samples_per_frame = PJMEDIA_PIA_SPF(&wav->info); param.channel_count = PJMEDIA_PIA_CCNT(&wav->info); param.bits_per_sample = PJMEDIA_PIA_BITS(&wav->info); status = pjmedia_aud_stream_create(¶m, &wav_rec_cb, NULL, wav, &strm); if (status != PJ_SUCCESS) { app_perror("Error opening the sound device", status); goto on_return; } status = pjmedia_aud_stream_start(strm); if (status != PJ_SUCCESS) { app_perror("Error starting the sound device", status); goto on_return; } PJ_LOG(3,(THIS_FILE, "Recording started, press ENTER to stop")); dummy = fgets(line, sizeof(line), stdin); on_return: if (strm) { pjmedia_aud_stream_stop(strm); pjmedia_aud_stream_destroy(strm); } if (wav) pjmedia_port_destroy(wav); if (pool) pj_pool_release(pool); }
static void play_file(unsigned play_index, const char *filename) { pj_pool_t *pool = NULL; pjmedia_port *wav = NULL; pjmedia_aud_param param; pjmedia_aud_stream *strm = NULL; char line[10], *dummy; pj_status_t status; if (filename == NULL) filename = WAV_FILE; pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav", 1000, 1000, NULL); status = pjmedia_wav_player_port_create(pool, filename, 20, 0, 0, &wav); if (status != PJ_SUCCESS) { app_perror("Error opening WAV file", status); goto on_return; } status = pjmedia_aud_dev_default_param(play_index, ¶m); if (status != PJ_SUCCESS) { app_perror("pjmedia_aud_dev_default_param()", status); goto on_return; } param.dir = PJMEDIA_DIR_PLAYBACK; param.clock_rate = wav->info.clock_rate; param.samples_per_frame = wav->info.samples_per_frame; param.channel_count = wav->info.channel_count; param.bits_per_sample = wav->info.bits_per_sample; status = pjmedia_aud_stream_create(¶m, NULL, &wav_play_cb, wav, &strm); if (status != PJ_SUCCESS) { app_perror("Error opening the sound device", status); goto on_return; } status = pjmedia_aud_stream_start(strm); if (status != PJ_SUCCESS) { app_perror("Error starting the sound device", status); goto on_return; } PJ_LOG(3,(THIS_FILE, "Playback started, press ENTER to stop")); dummy = fgets(line, sizeof(line), stdin); on_return: if (strm) { pjmedia_aud_stream_stop(strm); pjmedia_aud_stream_destroy(strm); } if (wav) pjmedia_port_destroy(wav); if (pool) pj_pool_release(pool); }
static pj_status_t open_stream( pjmedia_dir dir, int rec_id, int play_id, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, pjmedia_snd_rec_cb rec_cb, pjmedia_snd_play_cb play_cb, void *user_data, pjmedia_snd_stream **p_snd_strm) { pj_pool_t *pool; pjmedia_snd_stream *snd_strm; pjmedia_aud_param param; pj_status_t status; /* Initialize parameters */ if (dir & PJMEDIA_DIR_CAPTURE) { status = pjmedia_aud_dev_default_param(rec_id, ¶m); } else { status = pjmedia_aud_dev_default_param(play_id, ¶m); } if (status != PJ_SUCCESS) return status; param.dir = dir; param.rec_id = rec_id; param.play_id = play_id; param.clock_rate = clock_rate; param.channel_count = channel_count; param.samples_per_frame = samples_per_frame; param.bits_per_sample = bits_per_sample; /* Latencies setting */ if ((dir & PJMEDIA_DIR_CAPTURE) && g_sys.user_rec_latency) { param.flags |= PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY; param.input_latency_ms = g_sys.user_rec_latency; } if ((dir & PJMEDIA_DIR_PLAYBACK) && g_sys.user_play_latency) { param.flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY; param.output_latency_ms = g_sys.user_play_latency; } /* Create sound wrapper */ pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "legacy-snd", 512, 512, NULL); snd_strm = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_stream); snd_strm->pool = pool; snd_strm->user_rec_cb = rec_cb; snd_strm->user_play_cb = play_cb; snd_strm->user_user_data = user_data; /* Create the stream */ status = pjmedia_aud_stream_create(¶m, &snd_rec_cb, &snd_play_cb, snd_strm, &snd_strm->aud_strm); if (status != PJ_SUCCESS) { pj_pool_release(pool); return status; } *p_snd_strm = snd_strm; return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pjmedia_aud_test( const pjmedia_aud_param *param, pjmedia_aud_test_results *result) { pj_status_t status = PJ_SUCCESS; pjmedia_aud_stream *strm; struct test_data test_data; unsigned ptime, tmp; /* * Init test parameters */ pj_bzero(&test_data, sizeof(test_data)); test_data.param = param; test_data.result = result; test_data.pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "audtest", 1000, 1000, NULL); pj_mutex_create_simple(test_data.pool, "sndtest", &test_data.mutex); /* * Open device. */ status = pjmedia_aud_stream_create(test_data.param, &rec_cb, &play_cb, &test_data, &strm); if (status != PJ_SUCCESS) { app_perror("Unable to open device", status); pj_pool_release(test_data.pool); return status; } /* Sleep for a while to let sound device "settles" */ pj_thread_sleep(200); /* * Start the stream. */ status = pjmedia_aud_stream_start(strm); if (status != PJ_SUCCESS) { app_perror("Unable to start capture stream", status); pjmedia_aud_stream_destroy(strm); pj_pool_release(test_data.pool); return status; } PJ_LOG(3,(THIS_FILE, " Please wait while test is in progress (~%d secs)..", (DURATION+SKIP_DURATION)/1000)); /* Let the stream runs for few msec/sec to get stable result. * (capture normally begins with frames available simultaneously). */ pj_thread_sleep(SKIP_DURATION); /* Begin gather data */ test_data.running = 1; /* * Let the test runs for a while. */ pj_thread_sleep(DURATION); /* * Close stream. */ test_data.running = 0; pjmedia_aud_stream_destroy(strm); pj_pool_release(test_data.pool); /* * Gather results */ ptime = param->samples_per_frame * 1000 / param->clock_rate; tmp = pj_math_stat_get_stddev(&test_data.capture_data.delay); result->rec.frame_cnt = test_data.capture_data.delay.n; result->rec.min_interval = DIV_ROUND(test_data.capture_data.delay.min, 1000); result->rec.max_interval = DIV_ROUND(test_data.capture_data.delay.max, 1000); result->rec.avg_interval = DIV_ROUND(test_data.capture_data.delay.mean, 1000); result->rec.dev_interval = DIV_ROUND(tmp, 1000); result->rec.max_burst = DIV_ROUND_UP(result->rec.max_interval, ptime); tmp = pj_math_stat_get_stddev(&test_data.playback_data.delay); result->play.frame_cnt = test_data.playback_data.delay.n; result->play.min_interval = DIV_ROUND(test_data.playback_data.delay.min, 1000); result->play.max_interval = DIV_ROUND(test_data.playback_data.delay.max, 1000); result->play.avg_interval = DIV_ROUND(test_data.capture_data.delay.mean, 1000); result->play.dev_interval = DIV_ROUND(tmp, 1000); result->play.max_burst = DIV_ROUND_UP(result->play.max_interval, ptime); /* Check drifting */ if (param->dir == PJMEDIA_DIR_CAPTURE_PLAYBACK) { int end_diff, start_diff, drift; end_diff = test_data.capture_data.last_timestamp - test_data.playback_data.last_timestamp; start_diff = test_data.capture_data.first_timestamp- test_data.playback_data.first_timestamp; drift = end_diff > start_diff? end_diff - start_diff : start_diff - end_diff; /* Allow one frame tolerance for clock drift detection */ if (drift < (int)param->samples_per_frame) { result->rec_drift_per_sec = 0; } else { unsigned msec_dur; msec_dur = (test_data.capture_data.last_timestamp - test_data.capture_data.first_timestamp) * 1000 / test_data.param->clock_rate; result->rec_drift_per_sec = drift * 1000 / msec_dur; } } return test_data.has_error? PJ_EUNKNOWN : PJ_SUCCESS; }