static int voice_test() { int rtn = 0; char* name; fd_set rfds, wfds; Audio_t hPcm_Mic; Audio_t hPcm_Spk; snd_pcm_channel_params_t params; bool bQuit = false; /************************ CAPTURE **************************/ // configuring capture (mic) name = "voice"; // get audioman handle rtn = audio_manager_get_handle(AUDIO_TYPE_VIDEO_CHAT, getpid(), (bool)false, &hPcm_Mic.hAudioman); if(rtn < 0) { cli_print("audio_manager_get_handle (mic) failed %s", strerror(-rtn)); return -1; } cli_print("Opening %s - for capture", name); rtn = snd_pcm_open_name(&hPcm_Mic.pDs, name, SND_PCM_OPEN_CAPTURE); if (rtn < 0) { (void)audio_manager_free_handle(hPcm_Mic.hAudioman); cli_print("snd_pcm_open_name (mic) failed %s", snd_strerror(rtn)); return -1; // snd_pcm calls return negative values; make positive } rtn = snd_pcm_set_audioman_handle(hPcm_Mic.pDs, hPcm_Mic.hAudioman); if (rtn < 0) { (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); cli_print("snd_pcm_set_audioman_handle (mic) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); return -1; } // disable mmap (void)snd_pcm_plugin_set_disable(hPcm_Mic.pDs, (unsigned int)PLUGIN_DISABLE_MMAP); // set parameters memset(¶ms, 0, sizeof(params)); params.mode = SND_PCM_MODE_BLOCK; params.channel = SND_PCM_CHANNEL_CAPTURE; params.start_mode = SND_PCM_START_GO; params.stop_mode = SND_PCM_STOP_ROLLOVER; params.buf.block.frag_size = fragsize; params.buf.block.frags_max = 1; params.buf.block.frags_min = 1; params.format.rate = 8000; //samplerate; params.format.interleave = 1; params.format.voices = channels; params.format.format = SND_PCM_SFMT_S16_LE; rtn = snd_pcm_plugin_params(hPcm_Mic.pDs, ¶ms); if (rtn < 0) { cli_print("snd_pcm_plugin_params (mic) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); return -1; } // get file descriptor for use with the select() call hPcm_Mic.hFD = snd_pcm_file_descriptor(hPcm_Mic.pDs, SND_PCM_CHANNEL_CAPTURE); if (hPcm_Mic.hFD < 0) { cli_print("snd_pcm_file_descriptor (mic) failed %s", snd_strerror(hPcm_Mic.hFD)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); return -1; } // Signal the driver to ready the capture channel rtn = snd_pcm_plugin_prepare(hPcm_Mic.pDs, SND_PCM_CHANNEL_CAPTURE); if (rtn < 0) { cli_print("snd_pcm_plugin_prepare (mic) failed %s", snd_strerror(errno)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); return -1; } fragsize = params.buf.block.frag_size; /************************ PLAYBACK **************************/ name = "voice"; // get and set audioman handle rtn = audio_manager_get_handle(AUDIO_TYPE_VIDEO_CHAT, getpid(), (bool)false, &hPcm_Spk.hAudioman); if (rtn < 0) { cli_print("audioman audio_manager_get_handle (spk) failed %s", strerror(-rtn) ); (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); return -1; } #ifdef HANDSET // set audio manager handle type rtn = audio_manager_set_handle_type(hPcm_Spk.hAudioman, AUDIO_TYPE_VIDEO_CHAT, device_type, device_type); if (rtn < 0) { (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); cli_print("audio_manager_set_handle_type (spk) failed %s", strerror(-rtn)); return -1; } #endif // Create a handle and open a connection to an audio interface specified by name cli_print("Opening %s - for playback", name); rtn = snd_pcm_open_name(&hPcm_Spk.pDs, name, SND_PCM_OPEN_PLAYBACK); if (rtn < 0) { cli_print("snd_pcm_open_name (spk) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } rtn = snd_pcm_set_audioman_handle(hPcm_Spk.pDs, hPcm_Spk.hAudioman); if (rtn < 0) { cli_print("snd_pcm_set_audioman_handle (spk) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } // disable mmap (void)snd_pcm_plugin_set_disable(hPcm_Spk.pDs, (unsigned int)PLUGIN_DISABLE_MMAP); // set parameters memset(¶ms, 0, sizeof(params)); params.mode = SND_PCM_MODE_BLOCK; params.channel = SND_PCM_CHANNEL_PLAYBACK; params.start_mode = SND_PCM_START_GO; params.stop_mode = SND_PCM_STOP_ROLLOVER; params.buf.block.frag_size = fragsize; params.buf.block.frags_max = 1; params.buf.block.frags_min = 1; params.format.rate = samplerate; params.format.interleave = 1; params.format.voices = channels; params.format.format = SND_PCM_SFMT_S16_LE; // Set the configurable parameters for a PCM channel rtn = snd_pcm_plugin_params(hPcm_Spk.pDs, ¶ms); if (rtn < 0) { cli_print("snd_pcm_plugin_params (spk) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } // get file descriptor for use with the select() call hPcm_Spk.hFD = snd_pcm_file_descriptor(hPcm_Spk.pDs, SND_PCM_CHANNEL_PLAYBACK); if (hPcm_Spk.hFD < 0) { cli_print("snd_pcm_file_descriptor (spk) failed %s", snd_strerror(hPcm_Spk.hFD)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } // Signal the driver to ready the playback channel rtn = snd_pcm_plugin_prepare(hPcm_Spk.pDs, SND_PCM_CHANNEL_PLAYBACK); if (rtn < 0) { cli_print("snd_pcm_plugin_prepare (spk) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } fragsize = params.buf.block.frag_size; rtn = snd_pcm_capture_go(hPcm_Mic.pDs); if( rtn < 0) { cli_print("snd_pcm_capture_go (mic) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } rtn = snd_pcm_playback_go(hPcm_Spk.pDs); if (rtn < 0) { cli_print("snd_pcm_playback_go (spk) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } /******************* PLAYBACK/RECORD LOOP **************************/ while(!bQuit) { int width; struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 350000; // 350 ms FD_ZERO(&rfds); FD_ZERO(&wfds); FD_SET(hPcm_Mic.hFD, &rfds); FD_SET(hPcm_Spk.hFD, &wfds); width = ((hPcm_Spk.hFD > hPcm_Mic.hFD) ? hPcm_Spk.hFD : hPcm_Mic.hFD) + 1; rtn = select(width, &rfds, &wfds, NULL, &timeout); if (rtn > 0) { if (FD_ISSET(hPcm_Spk.hFD, &wfds)) { bQuit = process_write(hPcm_Spk.pDs); } if (FD_ISSET(hPcm_Mic.hFD, &rfds)) { bQuit = process_read(hPcm_Mic.pDs); } } else if (rtn == 0){ cli_print("select: timed out"); bQuit = true; } else { // (rtn < 0) cli_print("select: %s", strerror(errno)); bQuit = true; } } // Ensure audio processing is stopped if ((rtn = snd_pcm_plugin_playback_drain(hPcm_Spk.pDs)) < 0) { cli_print("snd_pcm_plugin_playback_drain (spk) failed %s", snd_strerror(rtn)); } if ((rtn = snd_pcm_plugin_flush(hPcm_Mic.pDs, SND_PCM_CHANNEL_CAPTURE)) < 0) { cli_print("snd_pcm_plugin_flush (mic) failed %s", snd_strerror(rtn)); } if ((rtn = snd_pcm_close(hPcm_Spk.pDs)) < 0) { cli_print("snd_pcm_close (spk) failed %s", snd_strerror(rtn)); } if ((rtn = snd_pcm_close(hPcm_Mic.pDs)) < 0) { cli_print("snd_pcm_close (mic) failed %s", snd_strerror(rtn)); } if (hPcm_Spk.hAudioman) { (void)audio_manager_free_handle(hPcm_Spk.hAudioman); } if (hPcm_Mic.hAudioman) { (void)audio_manager_free_handle(hPcm_Mic.hAudioman); } return 0; }
/* * General setup of the libasound audio mixer and pcm components. * Some of the settings are based on the format of the wav data. */ int setup_snd(const char * name) { int fragsize = -1; int num_frags = -1; int rtn; char *dev_name; if (NULL == name) { dev_name = "pcmPreferred"; } else { dev_name = (char *) name; } if ((rtn = snd_pcm_open_name(&pcm_handle, dev_name, SND_PCM_OPEN_PLAYBACK)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_open_name failed: %s\n", snd_strerror(rtn)); show_dialog_message(msg); return FAILURE; } if ((rtn = snd_pcm_info(pcm_handle, &info)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_info failed: %s\n", snd_strerror(rtn)); goto setup_failure; } card = info.card; /* disabling mmap is not actually required in this example but it is included to * demonstrate how it is used when it is required. */ if ((rtn = snd_pcm_plugin_set_disable(pcm_handle, PLUGIN_DISABLE_MMAP)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rtn)); goto setup_failure; } memset(&pi, 0, sizeof(pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_info(pcm_handle, &pi)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_plugin_info failed: %s\n", snd_strerror(rtn)); goto setup_failure; } memset(&pp, 0, sizeof(pp)); pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_PLAYBACK; pp.start_mode = SND_PCM_START_FULL; pp.stop_mode = SND_PCM_STOP_STOP; pp.buf.block.frag_size = pi.max_fragment_size; if (fragsize != -1) { pp.buf.block.frag_size = fragsize; } pp.buf.block.frags_max = num_frags; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = sample_rate; pp.format.voices = sample_channels; if (ENDIAN_LE16(wav_header.format_tag) == 6) pp.format.format = SND_PCM_SFMT_A_LAW; else if (ENDIAN_LE16(wav_header.format_tag) == 7) pp.format.format = SND_PCM_SFMT_MU_LAW; else if (sample_bits == 8) pp.format.format = SND_PCM_SFMT_U8; else if (sample_bits == 24) pp.format.format = SND_PCM_SFMT_S24; else pp.format.format = SND_PCM_SFMT_S16_LE; strcpy(pp.sw_mixer_subchn_name, "Wave playback channel"); if ((rtn = snd_pcm_plugin_params(pcm_handle, &pp)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_plugin_params failed: %s\n", snd_strerror(rtn)); goto setup_failure; } if ((rtn = snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rtn)); goto setup_failure; } memset(&setup, 0, sizeof(setup)); memset(&group, 0, sizeof(group)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mixer_gid = &group.gid; if ((rtn = snd_pcm_plugin_setup(pcm_handle, &setup)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_plugin_setup failed: %s\n", snd_strerror(rtn)); goto setup_failure; } if (group.gid.name[0] == 0) { snprintf(msg, MSG_SIZE, "Mixer Pcm Group [%s] Not Set \n", group.gid.name); goto setup_failure; } if ((rtn = snd_mixer_open(&mixer_handle, card, setup.mixer_device)) < 0) { snprintf(msg, MSG_SIZE, "snd_mixer_open failed: %s\n", snd_strerror(rtn)); goto setup_failure; } char tmp[MSG_SIZE]; snprintf(msg, MSG_SIZE, "Format %s \n", snd_pcm_get_format_name(setup.format.format)); snprintf(tmp, MSG_SIZE, "Frag Size %d \n", setup.buf.block.frag_size); strlcat(msg, tmp, MSG_SIZE); snprintf(tmp, MSG_SIZE, "Total Frags %d \n", setup.buf.block.frags); strlcat(msg, tmp, MSG_SIZE); snprintf(tmp, MSG_SIZE, "Rate %d \n", setup.format.rate); strlcat(msg, tmp, MSG_SIZE); snprintf(tmp, MSG_SIZE, "Voices %d \n", setup.format.voices); strlcat(msg, tmp, MSG_SIZE); snprintf(tmp, MSG_SIZE, "Mixer Pcm Group [%s]\n", group.gid.name); strlcat(msg, tmp, MSG_SIZE); show_dialog_message(msg); return SUCCESS; setup_failure: show_dialog_message(msg); snd_pcm_close(pcm_handle); return FAILURE; }
Error AudioDriverBB10::init(const char *p_name) { active = false; thread_exited = false; exit_thread = false; pcm_open = false; samples_in = NULL; samples_out = NULL; mix_rate = 44100; speaker_mode = SPEAKER_MODE_STEREO; char *dev_name; if (p_name == NULL) { dev_name = "pcmPreferred"; } else { dev_name = (char *)p_name; } printf("******** reconnecting to device %s\n", dev_name); int ret = snd_pcm_open_name(&pcm_handle, dev_name, SND_PCM_OPEN_PLAYBACK); ERR_FAIL_COND_V(ret < 0, FAILED); pcm_open = true; snd_pcm_channel_info_t cinfo; zeromem(&cinfo, sizeof(cinfo)); cinfo.channel = SND_PCM_CHANNEL_PLAYBACK; snd_pcm_plugin_info(pcm_handle, &cinfo); printf("rates %i, %i, %i, %i, %i\n", cinfo.rates, cinfo.rates & SND_PCM_RATE_44100, cinfo.rates & SND_PCM_RATE_32000, cinfo.rates & SND_PCM_RATE_22050, cinfo.max_rate); mix_rate = cinfo.max_rate; printf("formats %i, %i, %i\n", cinfo.formats, cinfo.formats & SND_PCM_FMT_S16_BE, cinfo.formats & SND_PCM_FMT_S16_LE); ERR_FAIL_COND_V(!(cinfo.formats & SND_PCM_FMT_S16_LE), FAILED); printf("voices %i\n", cinfo.max_voices); speaker_mode = SPEAKER_MODE_STEREO; snd_pcm_channel_params_t cp; zeromem(&cp, sizeof(cp)); cp.mode = SND_PCM_MODE_BLOCK; cp.channel = SND_PCM_CHANNEL_PLAYBACK; cp.start_mode = SND_PCM_START_DATA; cp.stop_mode = SND_PCM_STOP_STOP; //cp.buf.block.frag_size = cinfo.max_fragment_size; cp.buf.block.frag_size = 512; cp.buf.block.frags_max = 1; cp.buf.block.frags_min = 1; cp.format.interleave = 1; cp.format.rate = mix_rate; cp.format.voices = speaker_mode; cp.format.format = SND_PCM_SFMT_S16_LE; ret = snd_pcm_plugin_params(pcm_handle, &cp); printf("ret is %i, %i\n", ret, cp.why_failed); ERR_FAIL_COND_V(ret < 0, FAILED); ret = snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK); ERR_FAIL_COND_V(ret < 0, FAILED); snd_mixer_group_t group; zeromem(&group, sizeof(group)); snd_pcm_channel_setup_t setup; zeromem(&setup, sizeof(setup)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mode = SND_PCM_MODE_BLOCK; setup.mixer_gid = &group.gid; ret = snd_pcm_plugin_setup(pcm_handle, &setup); ERR_FAIL_COND_V(ret < 0, FAILED); pcm_frag_size = setup.buf.block.frag_size; pcm_max_frags = 1; sample_buf_count = pcm_frag_size * pcm_max_frags / 2; printf("sample count %i, %i, %i\n", sample_buf_count, pcm_frag_size, pcm_max_frags); samples_in = memnew_arr(int32_t, sample_buf_count); samples_out = memnew_arr(int16_t, sample_buf_count); thread = Thread::create(AudioDriverBB10::thread_func, this); return OK; };
// Initialize audio and report back a few parameters of the channel int setupAudio( ) { int error; snd_pcm_channel_info_t pi; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t ps; //if ((error = snd_pcm_open_name (&playback_handle, "pcmPreferred", SND_PCM_OPEN_PLAYBACK)) < 0) { if ((error = snd_pcm_open_name (&playback_handle, "tones", SND_PCM_OPEN_PLAYBACK)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to open preferred audio driver\n"); return -error; } sample_handle = snd_pcm_file_descriptor( playback_handle, SND_PCM_CHANNEL_PLAYBACK ); if ((error = snd_pcm_plugin_set_disable (playback_handle, PLUGIN_DISABLE_MMAP)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to disable mmap\n"); snd_pcm_close(playback_handle); return -error; } if ((error = snd_pcm_plugin_set_enable (playback_handle, PLUGIN_ROUTING)) < 0) { slogf ( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "snd_pcm_plugin_set_enable failed: %s\n", snd_strerror (error)); snd_pcm_close(playback_handle); return -error; } // Find what sample rate and format to use memset( &pi, 0, sizeof(pi) ); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((error = snd_pcm_channel_info (playback_handle, &pi)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to get plugin info\n"); snd_pcm_close(playback_handle); return -error; } // Initialize the playback channel memset(&pp, 0, sizeof(pp) ); pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_PLAYBACK; pp.start_mode = SND_PCM_START_FULL; pp.stop_mode = SND_PCM_STOP_STOP; pp.buf.block.frag_size = pi.max_fragment_size; pp.buf.block.frags_max = 3; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.format = SND_PCM_SFMT_S16_LE; pp.format.rate = 48000; pp.format.voices = 2; memset( &ps, 0, sizeof( ps ) ); memset( &group, 0, sizeof( group ) ); ps.channel = SND_PCM_CHANNEL_PLAYBACK; ps.mixer_gid = &group.gid; //strcpy(pp.sw_mixer_subchn_name, "Wave playback channel"); strcpy(pp.sw_mixer_subchn_name, "voice_ringtone"); if ((error = snd_pcm_plugin_params( playback_handle, &pp)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to set plugin params\n"); snd_pcm_close(playback_handle); return -error; } if ((error = snd_pcm_plugin_prepare (playback_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to set prepare plugin\n"); snd_pcm_close(playback_handle); return -error; } if ((error = snd_pcm_plugin_setup (playback_handle, &ps)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to setup plugin\n"); snd_pcm_close(playback_handle); return -error; } card = ps.mixer_card; device = ps.mixer_device; if( audioman_handle ) { if ((error = snd_pcm_set_audioman_handle (playback_handle, audioman_handle)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to set audioman handle \n"); snd_pcm_close(playback_handle); return -error; } } sample_frequency = ps.format.rate; frag_samples = ps.buf.block.frag_size / 4; frame_size = ps.buf.block.frag_size; format = pp.format.format; /* // Only support 16-bit samples for now frag_buffer = malloc( ps.buf.block.frag_size * 2 ); if( frag_buffer == NULL ) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to alloc frag buffer\n"); snd_pcm_close(playback_handle); return ENOMEM; } */ fprintf (stderr,"Playback Format %s card = %d\n", snd_pcm_get_format_name (ps.format.format),card); fprintf (stderr,"Playback preferred frame_size %d \n", pi.max_fragment_size); fprintf (stderr,"Playback frame_size %d \n", ps.buf.block.frag_size); fprintf (stderr,"Playback frame_samples %d \n", frag_samples); fprintf (stderr,"Playback Rate %d \n", ps.format.rate); if (group.gid.name[0] == 0) { fprintf (stderr,"Playback Mixer Pcm Group [%s] Not Set \n", group.gid.name); return -1; } fprintf (stderr, "Playback Mixer Pcm Group [%s]\n", group.gid.name); return EOK; }