int main (int argc, char **argv) { int card = -1; int dev = 0; snd_pcm_t *pcm_handle; FILE *file; wave_hdr wav_header; int samples; int sample_rate; int sample_channels; int sample_bits; char *sample_buffer; int fragsize = -1; int verbose = 0; int rtn; int final_return_code = -1; snd_pcm_channel_info_t pi; snd_mixer_t *mixer_handle; snd_mixer_group_t group; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; int bsize, bytes_read, total_written = 0; fd_set rfds, wfds; uint32_t voice_mask[] = { 0, 0, 0, 0 }; snd_pcm_voice_conversion_t voice_conversion; int voice_override = 0; int num_frags = -1; char input_file[PATH_MAX]; char cwd[PATH_MAX]; screen_context_t screen_cxt; screen_window_t screen_win; screen_buffer_t screen_buf; int screen_fill_attribs[] = { SCREEN_BLIT_COLOR, COLOR_PURPLE, SCREEN_BLIT_END }; int screen_dirty[4] = { 0, 0, 1024, 600 }; //start with sane default values int idle_mode = SCREEN_IDLE_MODE_KEEP_AWAKE; int usage = SCREEN_USAGE_NATIVE; if (screen_create_context(&screen_cxt, 0) != 0) { return err("failed to create context"); } if (screen_create_window(&screen_win, screen_cxt) != 0) { err("failed to create window"); goto fail1; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage) != 0) { err("failed to set native usage mode"); goto fail2; } if (screen_create_window_buffers(screen_win, 1) != 0) { err("failed to set native usage mode"); goto fail2; } if(screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf) != 0) { err("failed to get screen buffer"); goto fail2; } if (screen_fill(screen_cxt, screen_buf, screen_fill_attribs) != 0) { err("failed to fill the screen"); goto fail3; } if (screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, screen_dirty+2) != 0) { err("failed to get window size"); goto fail3; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_IDLE_MODE, &idle_mode) != 0) { err("failed to set idle mode"); goto fail3; } if (screen_post_window(screen_win, screen_buf, 1, screen_dirty, 0) != 0) { err("failed to post the window"); goto fail3; } if ((rtn = snd_pcm_open_preferred (&pcm_handle, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0) { err ("device open"); goto fail3; } getcwd(cwd, PATH_MAX); rtn = snprintf(input_file, PATH_MAX, "%s%s", cwd, WAV_RELATIVE_PATH); if (rtn > PATH_MAX - 1) { err ("File name and path too long"); goto fail4; } if ((file = fopen (input_file, "r")) == 0) { err ("File open failed"); goto fail4; } if (check_hdr (file) == -1) { err ("check_hdr failed"); goto fail5; } samples = find_tag (file, "fmt "); fread (&wav_header, sizeof (wav_header), 1, file); fseek (file, (samples - sizeof (wave_hdr)), SEEK_CUR); sample_rate = ENDIAN_LE32 (wav_header.samples_per_sec); sample_channels = ENDIAN_LE16 (wav_header.channels); sample_bits = ENDIAN_LE16 (wav_header.bits_per_sample); printf ("SampleRate = %d, channels = %d, SampleBits = %d\n", sample_rate, sample_channels, sample_bits); /* 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) { fprintf (stderr, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror (rtn)); goto fail5; } memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_info (pcm_handle, &pi)) < 0) { fprintf (stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror (rtn)); goto fail5; } 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) { fprintf (stderr, "snd_pcm_plugin_params failed: %s\n", snd_strerror (rtn)); goto fail5; } if ((rtn = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { fprintf (stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rtn)); goto fail5; } if (voice_override) { snd_pcm_plugin_get_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &voice_conversion); voice_conversion.matrix[0] = voice_mask[0]; voice_conversion.matrix[1] = voice_mask[1]; voice_conversion.matrix[2] = voice_mask[2]; voice_conversion.matrix[3] = voice_mask[3]; snd_pcm_plugin_set_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &voice_conversion); } 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) { fprintf (stderr, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (rtn)); goto fail5; } printf ("Format %s \n", snd_pcm_get_format_name (setup.format.format)); printf ("Frag Size %d \n", setup.buf.block.frag_size); printf ("Total Frags %d \n", setup.buf.block.frags); printf ("Rate %d \n", setup.format.rate); printf ("Voices %d \n", setup.format.voices); bsize = setup.buf.block.frag_size; if (group.gid.name[0] == 0) { fprintf (stderr, "Mixer Pcm Group [%s] Not Set \n", group.gid.name); goto fail5; } printf ("Mixer Pcm Group [%s]\n", group.gid.name); if ((rtn = snd_mixer_open (&mixer_handle, card, setup.mixer_device)) < 0) { fprintf (stderr, "snd_mixer_open failed: %s\n", snd_strerror (rtn)); goto fail5; } samples = find_tag (file, "data"); sample_buffer = malloc (bsize); FD_ZERO (&rfds); FD_ZERO (&wfds); bytes_read = 1; while (total_written < samples && bytes_read > 0) { if (tcgetpgrp (0) == getpid ()) FD_SET (STDIN_FILENO, &rfds); FD_SET (snd_mixer_file_descriptor (mixer_handle), &rfds); FD_SET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds); rtn = max (snd_mixer_file_descriptor (mixer_handle), snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)); if (select (rtn + 1, &rfds, &wfds, NULL, NULL) == -1) { err ("select"); goto fail6; } if (FD_ISSET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds)) { snd_pcm_channel_status_t status; int written = 0; if ((bytes_read = fread (sample_buffer, 1, min (samples - total_written, bsize), file)) <= 0) continue; written = snd_pcm_plugin_write (pcm_handle, sample_buffer, bytes_read); if (verbose) printf ("bytes written = %d \n", written); if (written < bytes_read) { memset (&status, 0, sizeof (status)); status.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_status (pcm_handle, &status) < 0) { fprintf (stderr, "underrun: playback channel status error\n"); goto fail6; } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_UNDERRUN) { if (snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0) { fprintf (stderr, "underrun: playback channel prepare error\n"); goto fail6; } } if (written < 0) written = 0; written += snd_pcm_plugin_write (pcm_handle, sample_buffer + written, bytes_read - written); } total_written += written; } } bytes_read = snd_pcm_plugin_flush (pcm_handle, SND_PCM_CHANNEL_PLAYBACK); final_return_code = 0; fail6: rtn = snd_mixer_close (mixer_handle); fail5: fclose (file); fail4: rtn = snd_pcm_close (pcm_handle); fail3: screen_destroy_buffer(screen_buf); fail2: screen_destroy_window(screen_win); fail1: screen_destroy_context(screen_cxt); return final_return_code; }
static void capturesetup() { snd_pcm_channel_setup_t setup; int ret; snd_pcm_channel_info_t pi; snd_mixer_group_t group; snd_pcm_channel_params_t pp; int card = setup.mixer_card; if ((ret = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT, &g_pcm_handle_c, &g_audio_manager_handle_c, (char*) "voice", SND_PCM_OPEN_CAPTURE)) < 0) { return; } snd_pcm_plugin_set_disable(g_pcm_handle_c, PLUGIN_DISABLE_MMAP); snd_pcm_plugin_set_enable(g_pcm_handle_c, PLUGIN_ROUTING); // sample reads the capabilities of the capture memset(&pi, 0, sizeof(pi)); pi.channel = SND_PCM_CHANNEL_CAPTURE; if ((ret = snd_pcm_plugin_info(g_pcm_handle_c, &pi)) < 0) { fprintf(stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror (ret)); return; } fprintf(stderr,"CAPTURE Minimum Rate = %d\n",pi.min_rate); // Request the VoIP parameters // These parameters are different to waverec sample memset(&pp, 0, sizeof(pp)); fprintf(stderr,"CAPTURE Minimum fragment size = %d\n",pi.min_fragment_size); // Blocking read pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_CAPTURE; //pp.start_mode = SND_PCM_START_DATA; // Auto-recover from errors pp.stop_mode = SND_PCM_STOP_ROLLOVER; pp.start_mode = SND_PCM_START_DATA; pp.buf.block.frag_size = PREFERRED_FRAME_SIZE; pp.buf.block.frags_max = 3; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = VOIP_SAMPLE_RATE; pp.format.voices = 1; pp.format.format = SND_PCM_SFMT_S16_LE; // make the request if ((ret = snd_pcm_plugin_params(g_pcm_handle_c, &pp)) < 0) { fprintf(stderr, "ca snd_pcm_plugin_params failed: %s\n", snd_strerror (ret)); return; } // Again based on the sample memset(&setup, 0, sizeof(setup)); memset(&group, 0, sizeof(group)); setup.channel = SND_PCM_CHANNEL_CAPTURE; setup.mixer_gid = &group.gid; if ((ret = snd_pcm_plugin_setup(g_pcm_handle_c, &setup)) < 0) { fprintf(stderr, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (ret)); return; } // On the simulator at least, our requested capabilities are accepted. fprintf(stderr,"CAPTURE Format %s card = %d\n", snd_pcm_get_format_name (setup.format.format),card); fprintf(stderr,"CAPTURE Rate %d \n", setup.format.rate); g_frame_size_c = setup.buf.block.frag_size; if (group.gid.name[0] == 0) { printf("Mixer Pcm Group [%s] Not Set \n", group.gid.name); printf("***>>>> Input Gain Controls Disabled <<<<*** \n"); } else { printf("Mixer Pcm Group [%s]\n", group.gid.name); } g_frame_size_c = setup.buf.block.frag_size; fprintf(stderr, "CAPTURE frame_size = %d\n", g_frame_size_c); // Sample calls prepare() if ((ret = snd_pcm_plugin_prepare(g_pcm_handle_c, SND_PCM_CHANNEL_CAPTURE)) < 0) { fprintf(stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (ret)); } }
/* * 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; }
/* open & setup audio device return: 1=success 0=fail */ static int init(int rate_hz, int channels, int format, int flags) { int err; int cards = -1; snd_pcm_channel_params_t params; snd_pcm_channel_setup_t setup; snd_pcm_info_t info; snd_pcm_channel_info_t chninfo; mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ALSA5_InitInfo, rate_hz, channels, af_fmt2str_short(format)); alsa_handler = NULL; mp_msg(MSGT_AO, MSGL_V, "alsa-init: compiled for ALSA-%s (%d)\n", SND_LIB_VERSION_STR, SND_LIB_VERSION); if ((cards = snd_cards()) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_SoundCardNotFound); return 0; } ao_data.format = format; ao_data.channels = channels; ao_data.samplerate = rate_hz; ao_data.bps = ao_data.samplerate*ao_data.channels; ao_data.outburst = OUTBURST; ao_data.buffersize = 16384; memset(&alsa_format, 0, sizeof(alsa_format)); switch (format) { case AF_FORMAT_S8: alsa_format.format = SND_PCM_SFMT_S8; break; case AF_FORMAT_U8: alsa_format.format = SND_PCM_SFMT_U8; break; case AF_FORMAT_U16_LE: alsa_format.format = SND_PCM_SFMT_U16_LE; break; case AF_FORMAT_U16_BE: alsa_format.format = SND_PCM_SFMT_U16_BE; break; case AF_FORMAT_AC3_LE: case AF_FORMAT_S16_LE: alsa_format.format = SND_PCM_SFMT_S16_LE; break; case AF_FORMAT_AC3_BE: case AF_FORMAT_S16_BE: alsa_format.format = SND_PCM_SFMT_S16_BE; break; default: alsa_format.format = SND_PCM_SFMT_MPEG; break; } switch(alsa_format.format) { case SND_PCM_SFMT_S16_LE: case SND_PCM_SFMT_U16_LE: ao_data.bps *= 2; break; case -1: mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_InvalidFormatReq,af_fmt2str_short(format)); return 0; default: break; } switch(rate_hz) { case 8000: alsa_rate = SND_PCM_RATE_8000; break; case 11025: alsa_rate = SND_PCM_RATE_11025; break; case 16000: alsa_rate = SND_PCM_RATE_16000; break; case 22050: alsa_rate = SND_PCM_RATE_22050; break; case 32000: alsa_rate = SND_PCM_RATE_32000; break; case 44100: alsa_rate = SND_PCM_RATE_44100; break; case 48000: alsa_rate = SND_PCM_RATE_48000; break; case 88200: alsa_rate = SND_PCM_RATE_88200; break; case 96000: alsa_rate = SND_PCM_RATE_96000; break; case 176400: alsa_rate = SND_PCM_RATE_176400; break; case 192000: alsa_rate = SND_PCM_RATE_192000; break; default: alsa_rate = SND_PCM_RATE_CONTINUOUS; break; } alsa_format.rate = ao_data.samplerate; alsa_format.voices = ao_data.channels; alsa_format.interleave = 1; if ((err = snd_pcm_open(&alsa_handler, 0, 0, SND_PCM_OPEN_PLAYBACK)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PlayBackError, snd_strerror(err)); return 0; } if ((err = snd_pcm_info(alsa_handler, &info)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PcmInfoError, snd_strerror(err)); return 0; } mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ALSA5_SoundcardsFound, cards, info.name); if (info.flags & SND_PCM_INFO_PLAYBACK) { memset(&chninfo, 0, sizeof(chninfo)); chninfo.channel = SND_PCM_CHANNEL_PLAYBACK; if ((err = snd_pcm_channel_info(alsa_handler, &chninfo)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PcmChanInfoError, snd_strerror(err)); return 0; } #ifndef __QNX__ if (chninfo.buffer_size) ao_data.buffersize = chninfo.buffer_size; #endif mp_msg(MSGT_AO, MSGL_V, "alsa-init: setting preferred buffer size from driver: %d bytes\n", ao_data.buffersize); } memset(¶ms, 0, sizeof(params)); params.channel = SND_PCM_CHANNEL_PLAYBACK; params.mode = SND_PCM_MODE_STREAM; params.format = alsa_format; params.start_mode = SND_PCM_START_DATA; params.stop_mode = SND_PCM_STOP_ROLLOVER; params.buf.stream.queue_size = ao_data.buffersize; params.buf.stream.fill = SND_PCM_FILL_NONE; if ((err = snd_pcm_channel_params(alsa_handler, ¶ms)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_CantSetParms, snd_strerror(err)); return 0; } memset(&setup, 0, sizeof(setup)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mode = SND_PCM_MODE_STREAM; setup.format = alsa_format; setup.buf.stream.queue_size = ao_data.buffersize; setup.msbits_per_sample = ao_data.bps; if ((err = snd_pcm_channel_setup(alsa_handler, &setup)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_CantSetChan, snd_strerror(err)); return 0; } if ((err = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_ChanPrepareError, snd_strerror(err)); return 0; } mp_msg(MSGT_AO, MSGL_INFO, "AUDIO: %d Hz/%d channels/%d bps/%d bytes buffer/%s\n", ao_data.samplerate, ao_data.channels, ao_data.bps, ao_data.buffersize, snd_pcm_get_format_name(alsa_format.format)); return 1; }
// 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; }