static int setparams(int32 sps, snd_pcm_t *handle) { int err; struct snd_pcm_channel_params params; memset(¶ms, 0, sizeof(params)); params.mode = SND_PCM_MODE_BLOCK; params.channel = SND_PCM_CHANNEL_PLAYBACK; params.format.format = SND_PCM_SFMT_MU_LAW; params.format.voices = 1; params.format.rate = 8000; if ((err = snd_pcm_plugin_params(handle, ¶ms)) < 0) { fprintf(stderr, "Playback parameters error: %s\n", snd_strerror(err)); return -1; } memset(¶ms, 0, sizeof(params)); params.mode = SND_PCM_MODE_BLOCK; params.channel = SND_PCM_CHANNEL_CAPTURE; params.format.format = SND_PCM_SFMT_S16_LE; params.format.voices = 1; params.format.rate = sps; if ((err = snd_pcm_plugin_params(handle, ¶ms)) < 0) { fprintf(stderr, "Record parameters error: %s\n", snd_strerror(err)); return -1; } return 0; }
static int get_formats_qsa(audio_output_t* ao) { qsa_internal_t* userptr; int status; int it=0; userptr=ao->userptr; if (userptr!=NULL); { userptr->cpars.format.rate=ao->rate; userptr->cpars.format.voices=ao->channels; it=0; do { if ((format_map[it].qsa_format==0) && (format_map[it].mp_format==0)) { break; } userptr->cpars.format.format=format_map[it].qsa_format; status=snd_pcm_plugin_params(userptr->audio_handle, &userptr->cpars); if (status<0) { it++; } else { return format_map[it].mp_format; } } while(1); } return 0; }
void OpenAudio() { int card = -1, dev = 0; snd_pcm_channel_info_t pi; snd_mixer_group_t group; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; mixbuf = (uint8_t*)malloc(mixlen); if (mixbuf == NULL) return; memset(mixbuf, 0, mixlen); if ((snd_pcm_open_preferred(&pcm_handle, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0) return; memset(&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((snd_pcm_plugin_info (pcm_handle, &pi)) < 0) return; 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 = -1; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = AUDIO_FREQ; pp.format.voices = AUDIO_CHANNELS; pp.format.format = SND_PCM_SFMT_S16_LE; if ((snd_pcm_plugin_params (pcm_handle, &pp)) < 0) return; snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK); memset (&setup, 0, sizeof(setup)); memset (&group, 0, sizeof(group)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mixer_gid = &group.gid; if ((snd_pcm_plugin_setup (pcm_handle, &setup)) < 0) return; setup.buf.block.frag_size; if ((snd_mixer_open(&mixer_handle, card, setup.mixer_device)) < 0) return; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_create(&thread_handle, &attr, &BlackberryAudio::staticThreadProc, this); }
static int alsa_init_sound (SINT16 *b) { snd_pcm_channel_params_t params; snd_pcm_channel_setup_t setup; int err; buffer = b; if ((err = snd_pcm_open (&pcm_handle, 0, 0, SND_PCM_OPEN_PLAYBACK)) < 0){ report ("sound_alsa: Error: %s\n", snd_strerror (err)); return -1; } report ("ALSA driver written by [email protected].\n"); memset (¶ms, 0, sizeof(snd_pcm_channel_params_t)); params.mode = SND_PCM_MODE_BLOCK; params.buf.block.frag_size = FRAGSIZE; params.buf.block.frags_min = 1; params.buf.block.frags_max = FRAGNUM; params.channel = SND_PCM_CHANNEL_PLAYBACK; params.start_mode = SND_PCM_START_FULL; params.stop_mode = SND_PCM_STOP_ROLLOVER; /* Set sound device to 16 bit, 22 kHz mono */ params.format.interleave = 1; params.format.format = SND_PCM_SFMT_S16_LE; params.format.rate = 22050; params.format.voices = 1; if ((err = snd_pcm_plugin_params (pcm_handle, ¶ms)) < 0) { report ("sound_alsa: Error: %s\n", snd_strerror (err)); return -1; } if (snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0) { report ("sound_alsa: can't prepare\n"); return -1; } memset (&setup, 0, sizeof (setup)); setup.mode = SND_PCM_MODE_STREAM; setup.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_channel_setup (pcm_handle, &setup) < 0) { report ("sound_alsa: can't setup\n"); return -1; } pthread_create (&thread, NULL, sound_thread, NULL); pthread_detach (thread); return 0; }
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; }
void *Audio_ALSA::open (AudioConfig &cfg, const char *) { AudioConfig tmpCfg; int mask, wantedFormat, format; int rtn; int card = -1, dev = 0; if (_audioHandle != NULL) { _errorString = "ERROR: Device already in use"; return NULL; } if ((rtn = snd_pcm_open_preferred (&_audioHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK))) { _errorString = "ERROR: Could not open audio device."; goto open_error; } // Transfer input parameters to this object. // May later be replaced with driver defaults. tmpCfg = cfg; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; snd_pcm_channel_info_t pi; memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_info (_audioHandle, &pi))) { _errorString = "ALSA: snd_pcm_plugin_info failed."; goto open_error; } 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 = 1; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = tmpCfg.frequency; pp.format.voices = tmpCfg.channels; // Set sample precision and type of encoding. if ( tmpCfg.precision == 8 ) { tmpCfg.encoding = AUDIO_UNSIGNED_PCM; pp.format.format = SND_PCM_SFMT_U8; } if ( tmpCfg.precision == 16 ) { tmpCfg.encoding = AUDIO_SIGNED_PCM; pp.format.format = SND_PCM_SFMT_S16_LE; } if ((rtn = snd_pcm_plugin_params (_audioHandle, &pp)) < 0) { _errorString = "ALSA: snd_pcm_plugin_params failed."; goto open_error; } if ((rtn = snd_pcm_plugin_prepare (_audioHandle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { _errorString = "ALSA: snd_pcm_plugin_prepare failed."; goto open_error; } memset (&setup, 0, sizeof (setup)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_setup (_audioHandle, &setup)) < 0) { _errorString = "ALSA: snd_pcm_plugin_setup failed."; goto open_error; } tmpCfg.bufSize = setup.buf.block.frag_size; #ifdef HAVE_EXCEPTIONS _sampleBuffer = new(std::nothrow) int_least8_t[tmpCfg.bufSize]; #else _sampleBuffer = new int_least8_t[tmpCfg.bufSize]; #endif if (!_sampleBuffer) { _errorString = "AUDIO: Unable to allocate memory for sample buffers."; goto open_error; } // Setup internal Config _settings = tmpCfg; // Update the users settings getConfig (cfg); return _sampleBuffer; open_error: if (_audioHandle != NULL) { close (); } perror ("ALSA"); return NULL; }
static pj_status_t bb10_open_capture (struct bb10_stream *stream, const pjmedia_aud_param *param) { int ret = 0; unsigned int rate; unsigned long tmp_buf_size; int frame_size; snd_pcm_channel_info_t pi; snd_mixer_group_t group; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; if (param->rec_id < 0 || param->rec_id >= stream->af->dev_cnt) return PJMEDIA_EAUD_INVDEV; PJ_ASSERT_RETURN(param->bits_per_sample == 16, PJMEDIA_EAUD_SAMPFORMAT); if ((ret=audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT, &stream->ca_pcm, &stream->ca_audio_manager_handle, (char*)"voice", SND_PCM_OPEN_CAPTURE)) < 0) { TRACE_((THIS_FILE, "audio_manager_snd_pcm_open_name ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } /* Required call from January 2013 gold OS release */ snd_pcm_plugin_set_disable (stream->ca_pcm, PLUGIN_DISABLE_MMAP); /* Required call from January 2013 gold OS release */ snd_pcm_plugin_set_enable(stream->ca_pcm, 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 (stream->ca_pcm, &pi)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_info ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } /* Request the VoIP parameters * These parameters are different to waverec sample */ memset (&pp, 0, sizeof (pp)); /* Blocking read */ pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_CAPTURE; pp.start_mode = SND_PCM_START_FULL; /* Auto-recover from errors */ pp.stop_mode = SND_PCM_STOP_ROLLOVER; pp.buf.block.frag_size = param->samples_per_frame * param->bits_per_sample / 8; /* From January 2013 gold OS release. RIM recommend these for capture */ pp.buf.block.frags_max = 3; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = param->clock_rate; pp.format.voices = param->channel_count; pp.format.format = get_alsa_pcm_fmt(param); /* make the request */ if ((ret = snd_pcm_plugin_params (stream->ca_pcm, &pp)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_params ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } /* 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 (stream->ca_pcm, &setup)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_setup ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } frame_size = setup.buf.block.frag_size; if (group.gid.name[0] == 0) { } else { } frame_size = setup.buf.block.frag_size; PJ_UNUSED_ARG(frame_size); /* Warning about unused var */ /* Set clock rate */ rate = param->clock_rate; stream->ca_frames = (unsigned long) param->samples_per_frame / param->channel_count; /* Set the sound device buffer size and latency */ if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) { tmp_buf_size = rate * param->input_latency_ms / 1000; } else { tmp_buf_size = rate * PJMEDIA_SND_DEFAULT_REC_LATENCY / 1000; } stream->param.input_latency_ms = tmp_buf_size * 1000 / rate; /* Set our buffer */ stream->ca_buf_size = stream->ca_frames * param->channel_count * param->bits_per_sample / 8; stream->ca_buf = (char *)pj_pool_alloc (stream->pool, stream->ca_buf_size); TRACE_((THIS_FILE, "bb10_open_capture: ca_frames = %d clock = %d", stream->ca_frames, param->clock_rate)); return PJ_SUCCESS; }
static void playsetup() { snd_pcm_channel_setup_t setup; //Enabling Echo canceller int ret; snd_pcm_channel_info_t pi; snd_mixer_group_t group; snd_pcm_channel_params_t pp; //audio routing enabled with AEC if ((ret = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VIDEO_CHAT, &g_pcm_handle_p, &g_audio_manager_handle_p, (char*) "voice", SND_PCM_OPEN_PLAYBACK)) < 0) { return; } snd_pcm_plugin_set_disable(g_pcm_handle_p, PLUGIN_DISABLE_MMAP); snd_pcm_plugin_set_enable(g_pcm_handle_p, PLUGIN_ROUTING); memset(&pi, 0, sizeof(pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((ret = snd_pcm_plugin_info(g_pcm_handle_p, &pi)) < 0) { fprintf(stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror (ret)); return; } fprintf(stderr,"PLAY Minimum Rate = %d\n",pi.min_rate); // Interestingly on the simulator this returns 4096 but in reality always 170 is the result fprintf(stderr,"PLAY Minimum fragment size = %d\n",pi.min_fragment_size); memset(&pp, 0, sizeof(pp)); // Request VoIP compatible capabilities // On simulator frag_size is always negotiated to 170 pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_PLAYBACK; //pp.start_mode = SND_PCM_START_DATA; pp.stop_mode = SND_PCM_STOP_ROLLOVER; pp.start_mode = SND_PCM_START_FULL; pp.buf.block.frag_size = PREFERRED_FRAME_SIZE; // Increasing this internal buffer count delays write failure in the loop pp.buf.block.frags_max = 5; 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 calls as per the wave sample if ((ret = snd_pcm_plugin_params(g_pcm_handle_p, &pp)) < 0) { fprintf(stderr, "pb snd_pcm_plugin_params failed: %s\n", snd_strerror (ret)); return; } memset(&setup, 0, sizeof(setup)); memset(&group, 0, sizeof(group)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mixer_gid = &group.gid; if ((ret = snd_pcm_plugin_setup(g_pcm_handle_p, &setup)) < 0) { fprintf(stderr, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (ret)); return; } fprintf(stderr,"PLAY frame_size %d \n", setup.buf.block.frag_size); fprintf(stderr,"PLAY Rate %d \n", setup.format.rate); g_frame_size_p = setup.buf.block.frag_size; if (group.gid.name[0] == 0) { fprintf(stderr,"FATAL Mixer Pcm Group [%s] Not Set \n", group.gid.name); exit (-1); } printf("Mixer Pcm Group [%s]\n", group.gid.name); if ((ret = snd_pcm_plugin_prepare(g_pcm_handle_p, SND_PCM_CHANNEL_PLAYBACK)) < 0) { fprintf(stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (ret)); } }
static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) { qsa_data *data; int card, dev; int format=-1; int status; data=(qsa_data*)calloc(1, sizeof(qsa_data)); if (data==NULL) { return ALC_OUT_OF_MEMORY; } if(!deviceName) deviceName = qsaDevice; if(strcmp(deviceName, qsaDevice) == 0) status = snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_CAPTURE); else { const DevMap *iter; if(VECTOR_SIZE(CaptureNameMap) == 0) deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap); #define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0) VECTOR_FIND_IF(iter, const DevMap, CaptureNameMap, MATCH_DEVNAME); #undef MATCH_DEVNAME if(iter == VECTOR_ITER_END(CaptureNameMap)) { free(data); return ALC_INVALID_DEVICE; } status = snd_pcm_open(&data->pcmHandle, iter->card, iter->dev, SND_PCM_OPEN_CAPTURE); } if(status < 0) { free(data); return ALC_INVALID_DEVICE; } data->audio_fd = snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE); if(data->audio_fd < 0) { snd_pcm_close(data->pcmHandle); free(data); return ALC_INVALID_DEVICE; } al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; switch (device->FmtType) { case DevFmtByte: format=SND_PCM_SFMT_S8; break; case DevFmtUByte: format=SND_PCM_SFMT_U8; break; case DevFmtShort: format=SND_PCM_SFMT_S16_LE; break; case DevFmtUShort: format=SND_PCM_SFMT_U16_LE; break; case DevFmtInt: format=SND_PCM_SFMT_S32_LE; break; case DevFmtUInt: format=SND_PCM_SFMT_U32_LE; break; case DevFmtFloat: format=SND_PCM_SFMT_FLOAT_LE; break; } /* we actually don't want to block on reads */ snd_pcm_nonblock_mode(data->pcmHandle, 1); /* Disable mmap to control data transfer to the audio device */ snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP); /* configure a sound channel */ memset(&data->cparams, 0, sizeof(data->cparams)); data->cparams.mode=SND_PCM_MODE_BLOCK; data->cparams.channel=SND_PCM_CHANNEL_CAPTURE; data->cparams.start_mode=SND_PCM_START_GO; data->cparams.stop_mode=SND_PCM_STOP_STOP; data->cparams.buf.block.frag_size=device->UpdateSize* ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType); data->cparams.buf.block.frags_max=device->NumUpdates; data->cparams.buf.block.frags_min=device->NumUpdates; data->cparams.format.interleave=1; data->cparams.format.rate=device->Frequency; data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans); data->cparams.format.format=format; if(snd_pcm_plugin_params(data->pcmHandle, &data->cparams) < 0) { snd_pcm_close(data->pcmHandle); free(data); device->ExtraData=NULL; return ALC_INVALID_VALUE; } return ALC_NO_ERROR; }
bool QnxAudioInput::open() { if (!m_format.isValid() || m_format.sampleRate() <= 0) { if (!m_format.isValid()) qWarning("QnxAudioInput: open error, invalid format."); else qWarning("QnxAudioInput: open error, invalid sample rate (%d).", m_format.sampleRate()); return false; } int errorCode = 0; int card = 0; int device = 0; if ((errorCode = snd_pcm_open_preferred(&m_pcmHandle, &card, &device, SND_PCM_OPEN_CAPTURE)) < 0) { qWarning("QnxAudioInput: open error, couldn't open card (0x%x)", -errorCode); return false; } // Necessary so that bytesFree() which uses the "free" member of the status struct works snd_pcm_plugin_set_disable(m_pcmHandle, PLUGIN_DISABLE_MMAP); snd_pcm_channel_info_t info; memset(&info, 0, sizeof(info)); info.channel = SND_PCM_CHANNEL_CAPTURE; if ((errorCode = snd_pcm_plugin_info(m_pcmHandle, &info)) < 0) { qWarning("QnxAudioInput: open error, couldn't get channel info (0x%x)", -errorCode); close(); return false; } snd_pcm_channel_params_t params = QnxAudioUtils::formatToChannelParams(m_format, QAudio::AudioInput, info.max_fragment_size); if ((errorCode = snd_pcm_plugin_params(m_pcmHandle, ¶ms)) < 0) { qWarning("QnxAudioInput: open error, couldn't set channel params (0x%x)", -errorCode); close(); return false; } if ((errorCode = snd_pcm_plugin_prepare(m_pcmHandle, SND_PCM_CHANNEL_CAPTURE)) < 0) { qWarning("QnxAudioInput: open error, couldn't prepare channel (0x%x)", -errorCode); close(); return false; } snd_pcm_channel_setup_t setup; memset(&setup, 0, sizeof(setup)); setup.channel = SND_PCM_CHANNEL_CAPTURE; if ((errorCode = snd_pcm_plugin_setup(m_pcmHandle, &setup)) < 0) { qWarning("QnxAudioInput: open error, couldn't get channel setup (0x%x)", -errorCode); close(); return false; } m_periodSize = qMin(2048, setup.buf.block.frag_size); m_clockStamp.restart(); m_timeStamp.restart(); m_elapsedTimeOffset = 0; m_totalTimeValue = 0; m_bytesRead = 0; m_pcmNotifier = new QSocketNotifier(snd_pcm_file_descriptor(m_pcmHandle, SND_PCM_CHANNEL_CAPTURE), QSocketNotifier::Read, this); connect(m_pcmNotifier, SIGNAL(activated(int)), SLOT(userFeed())); return true; }
/* Plays a sound with the Advanced Linux Sound Architecture, ALSA. Returns 0 on successful playback, nonzero on error. */ int PlayerALSA(u_int8_t *samples, unsigned int bits, unsigned int channels, unsigned int rate, unsigned int bytes) { int i; /* ALSA is a bit verbose, and it tends to require lots of structures. */ unsigned int alsa_device = 0, alsa_card = 0; char *alsa_card_name; snd_ctl_t *alsa_ctl; snd_ctl_hw_info_t alsa_hw_info; snd_pcm_t *alsa_pcm; snd_pcm_channel_params_t alsa_params; /* Playback status variables. */ unsigned int position; /* Scan for ALSA cards and devices. Each card has an integer ID less than snd_cards(). We scan for the first available card in order to demonstrate ALSA's organization, but we could find the default card and PCM device numbers immediately with the snd_defaults_pcm_card(), snd_defaults_pcm_device() functions. */ alsa_pcm = NULL; for (alsa_card = 0; alsa_card < (unsigned)snd_cards(); alsa_card++) { /* Try to open this card. */ if (snd_ctl_open(&alsa_ctl,alsa_card) < 0) continue; /* Retrieve card info. */ if (snd_ctl_hw_info(alsa_ctl,&alsa_hw_info) < 0) { snd_ctl_close(alsa_ctl); continue; } snd_ctl_close(alsa_ctl); /* Find a suitable device on this card. */ alsa_pcm = NULL; for (alsa_device = 0; alsa_device < alsa_hw_info.pcmdevs; alsa_device++) { if (snd_pcm_open(&alsa_pcm,alsa_card, alsa_device,SND_PCM_OPEN_PLAYBACK) < 0) continue; /* Device successfully opened. */ break; } if (alsa_pcm != NULL) break; } /* Were we able to open a device? */ if (alsa_card == (unsigned)snd_cards()) { printf("ALSA player: unable to find a configured device.\n"); return -1; } /* Print info about the device. */ if (snd_card_get_longname(alsa_card,&alsa_card_name) < 0) alsa_card_name = "(unknown)"; printf("ALSA player: using device %i:%i (%s)\n", alsa_card, alsa_device, alsa_card_name); /* Configure the device for the loaded sound data. */ memset(&alsa_params,0,sizeof (alsa_params)); alsa_params.channel = SND_PCM_CHANNEL_PLAYBACK; /* Use stream mode. In this mode, we don't have to give ALSA complete blocks; we can send it data as we get it. Block mode is needed for mmap() functionality. Unlike OSS, ALSA's mmap() functionality is quite reliable, and easily accessible through library functions. We won't use it here, though; there's no need. */ alsa_params.mode = SND_PCM_MODE_STREAM; alsa_params.format.interleave = 1; /* We'll assume little endian samples. You may wish to use the data in the GNU C Library's endian.h to support other endiannesses. We're ignoring that case for simplicity. */ if (bits == 8) alsa_params.format.format = SND_PCM_SFMT_U8; else if (bits == 16) alsa_params.format.format = SND_PCM_SFMT_S16_LE; else { printf("ALSA player: invalid sample size.\n"); return -1; } alsa_params.format.rate = rate; alsa_params.format.voices = channels; alsa_params.start_mode = SND_PCM_START_DATA; alsa_params.stop_mode = SND_PCM_STOP_ROLLOVER; alsa_params.buf.block.frag_size = 4096; alsa_params.buf.block.frags_min = 1; alsa_params.buf.block.frags_max = 2; if ((i = snd_pcm_plugin_params(alsa_pcm,&alsa_params)) < 0) { printf("ALSA player: unable to set parameters.\n"); snd_pcm_close(alsa_pcm); return -1; } if (snd_pcm_plugin_prepare(alsa_pcm, SND_PCM_CHANNEL_PLAYBACK) < 0) { printf("ALSA player: unable to prepare playback.\n"); snd_pcm_close(alsa_pcm); return -1; } /* Feed the sound data to ALSA. */ position = 0; while (position < bytes) { int written, blocksize; if (bytes-position < 4096) blocksize = bytes-position; else blocksize = 4096; /* Write to the sound device. */ written = snd_pcm_plugin_write(alsa_pcm, &samples[position], blocksize); /* If ALSA can't take any more data right now, it'll return -EAGAIN. If this were sound code for a game, we'd probably just contine the game loop and try to write data the next time around. In a game, you'd probably also want to put the device in nonblocking mode (see the snd_pcm_nonblock_mode() function). */ if (written == -EAGAIN) { /* Waste some time. This keeps us from using 100% CPU. */ usleep(1000); written = 0; } else { if (written < 0) { perror("\nALSA player: error writing to sound device"); snd_pcm_close(alsa_pcm); return -1; } } /* Update the position. */ position += written; /* Print some information. */ WritePlaybackStatus(position, bytes, channels, bits, rate); printf("\r"); fflush(stdout); } printf("\n"); /* Wait until ALSA's internal buffers are empty, then stop playback. This will make sure that the entire sound clip has played. */ snd_pcm_channel_flush(alsa_pcm, SND_PCM_CHANNEL_PLAYBACK); snd_pcm_close(alsa_pcm); return 0; }
static int NTO_OpenAudio(_THIS, SDL_AudioSpec* spec) { int rval; int format; Uint16 test_format; int found; audio_handle = NULL; this->enabled = 0; if (pcm_buf != NULL) { SDL_FreeAudioMem(pcm_buf); pcm_buf = NULL; } /* initialize channel transfer parameters to default */ NTO_InitAudioParams(&cparams); /* Open the audio device */ rval = snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, OPEN_FLAGS); if (rval < 0) { SDL_SetError("NTO_OpenAudio(): snd_pcm_open failed: %s\n", snd_strerror(rval)); return (-1); } if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) { /* enable count status parameter */ if ((rval = snd_pcm_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP)) < 0) { SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rval)); return (-1); } } /* Try for a closest match on audio format */ format = 0; /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */ found = 0; for (test_format=SDL_FirstAudioFormat(spec->format); !found ;) { /* if match found set format to equivalent ALSA format */ switch (test_format) { case AUDIO_U8: format = SND_PCM_SFMT_U8; found = 1; break; case AUDIO_S8: format = SND_PCM_SFMT_S8; found = 1; break; case AUDIO_S16LSB: format = SND_PCM_SFMT_S16_LE; found = 1; break; case AUDIO_S16MSB: format = SND_PCM_SFMT_S16_BE; found = 1; break; case AUDIO_U16LSB: format = SND_PCM_SFMT_U16_LE; found = 1; break; case AUDIO_U16MSB: format = SND_PCM_SFMT_U16_BE; found = 1; break; default: break; } if (!found) { test_format = SDL_NextAudioFormat(); } } /* assumes test_format not 0 on success */ if (test_format == 0) { SDL_SetError("NTO_OpenAudio(): Couldn't find any hardware audio formats"); return (-1); } spec->format = test_format; /* Set the audio format */ cparams.format.format = format; /* Set mono or stereo audio (currently only two channels supported) */ cparams.format.voices = spec->channels; /* Set rate */ cparams.format.rate = spec->freq; /* Setup the transfer parameters according to cparams */ rval = snd_pcm_plugin_params(audio_handle, &cparams); if (rval < 0) { SDL_SetError("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n", snd_strerror(rval)); return (-1); } /* Make sure channel is setup right one last time */ SDL_memset(&csetup, 0x00, sizeof(csetup)); csetup.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_setup(audio_handle, &csetup) < 0) { SDL_SetError("NTO_OpenAudio(): Unable to setup playback channel\n"); return -1; } /* Calculate the final parameters for this audio specification */ SDL_CalculateAudioSpec(spec); pcm_len = spec->size; if (pcm_len==0) { pcm_len = csetup.buf.block.frag_size * spec->channels * (snd_pcm_format_width(format)/8); } /* Allocate memory to the audio buffer and initialize with silence (Note that buffer size must be a multiple of fragment size, so find closest multiple) */ pcm_buf = (Uint8*)SDL_AllocAudioMem(pcm_len); if (pcm_buf == NULL) { SDL_SetError("NTO_OpenAudio(): pcm buffer allocation failed\n"); return (-1); } SDL_memset(pcm_buf, spec->silence, pcm_len); /* get the file descriptor */ if ((audio_fd = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { SDL_SetError("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n", snd_strerror(rval)); return (-1); } /* Trigger audio playback */ rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK); if (rval < 0) { SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rval)); return (-1); } this->enabled = 1; /* Get the parent process id (we're the parent of the audio thread) */ parent = getpid(); /* We're really ready to rock and roll. :-) */ return (0); }
static int init(struct xmp_context *ctx) { struct xmp_options *o = &ctx->o; snd_pcm_channel_params_t params; snd_pcm_channel_setup_t setup; int card = 0; int dev = 0; int rc; char *token, **parm; parm_init(); chkparm2("frag", "%d,%d", &frag_num, &frag_size); if (frag_num > 8) frag_num = 8; if (frag_num < 4) frag_num = 4; if (frag_size > 65536) frag_size = 65536; if (frag_size < 16) frag_size = 16; chkparm1("card", card_name = token); // card = snd_card_name(card_name); /* ? */ // dev = snd_defaults_pcm_device(); /* ? */ parm_end(); mybuffer = malloc(frag_size); if (mybuffer) { mybuffer_nextfree = mybuffer; } else { printf("Unable to allocate memory for mixer buffer\n"); return XMP_ERR_DINIT; } if ((rc = snd_pcm_open(&pcm_handle, card, dev, SND_PCM_OPEN_PLAYBACK)) < 0) { printf("Unable to initialize pcm device: %s\n", snd_strerror(rc)); return XMP_ERR_DINIT; } memset(¶ms, 0, sizeof(snd_pcm_channel_params_t)); params.mode = SND_PCM_MODE_BLOCK; params.buf.block.frag_size = frag_size; params.buf.block.frags_min = 1; params.buf.block.frags_max = frag_num; //params.mode = SND_PCM_MODE_STREAM; //params.buf.stream.queue_size = 16384; //params.buf.stream.fill = SND_PCM_FILL_NONE; //params.buf.stream.max_fill = 0; params.channel = SND_PCM_CHANNEL_PLAYBACK; params.start_mode = SND_PCM_START_FULL; params.stop_mode = SND_PCM_STOP_ROLLOVER; params.format.interleave = 1; params.format.format = to_fmt(o); params.format.rate = o->freq; params.format.voices = (o->outfmt & XMP_FMT_MONO) ? 1 : 2; if ((rc = snd_pcm_plugin_params(pcm_handle, ¶ms)) < 0) { printf("Unable to set output parameters: %s\n", snd_strerror(rc)); return XMP_ERR_DINIT; } if (prepare_driver() < 0) return XMP_ERR_DINIT; memset(&setup, 0, sizeof(setup)); setup.mode = SND_PCM_MODE_STREAM; setup.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rc = snd_pcm_channel_setup(pcm_handle, &setup)) < 0) { printf("Unable to setup channel: %s\n", snd_strerror(rc)); return XMP_ERR_DINIT; } return xmp_smix_on(ctx); }
static int open_qsa(audio_output_t* ao) { int status; int cardno; int deviceno; int it; snd_pcm_t* audio_handle; qsa_internal_t* userptr; ao->userptr=NULL; status=snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, SND_PCM_OPEN_PLAYBACK); if (status<0) { return FALSE; } status=snd_pcm_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP); if (status<0) { return FALSE; } userptr=calloc(1, sizeof(qsa_internal_t)); if (userptr==NULL) { return FALSE; } ao->userptr=userptr; userptr->audio_handle=audio_handle; userptr->cardno=cardno; userptr->deviceno=deviceno; memset(&userptr->cpars, 0, sizeof(userptr->cpars)); userptr->cpars.channel=SND_PCM_CHANNEL_PLAYBACK; userptr->cpars.mode=SND_PCM_MODE_BLOCK; userptr->cpars.start_mode=SND_PCM_START_DATA; userptr->cpars.stop_mode=SND_PCM_STOP_STOP; userptr->cpars.format.format=0; it=0; do { if ((format_map[it].qsa_format==0) && (format_map[it].mp_format==0)) { break; } if (ao->format==format_map[it].mp_format) { userptr->cpars.format.format=format_map[it].qsa_format; break; } it++; } while(1); userptr->cpars.format.interleave=1; userptr->cpars.format.rate=ao->rate; userptr->cpars.format.voices=ao->channels; userptr->cpars.buf.block.frag_size=4096; userptr->cpars.buf.block.frags_min=8; userptr->cpars.buf.block.frags_max=16; if ((ao->channels!=-1) && (ao->rate!=-1)) { status=snd_pcm_plugin_params(userptr->audio_handle, &userptr->cpars); if (status<0) { return FALSE; } status=snd_pcm_plugin_prepare(userptr->audio_handle, SND_PCM_CHANNEL_PLAYBACK); if (status<0) { return FALSE; } } return TRUE; }
void *Audio_ALSA::open (AudioConfig &cfg, const char *) { AudioConfig tmpCfg; if (_audioHandle != NULL) { _errorString = "ERROR: Device already in use"; return NULL; } #ifdef HAVE_ALSA_ASOUNDLIB_H snd_pcm_uframes_t buffer_frames; snd_pcm_hw_params_t *hw_params = 0; if (snd_pcm_open (&_audioHandle, "default", SND_PCM_STREAM_PLAYBACK, 0)) { _errorString = "ERROR: Could not open audio device."; goto open_error; } // May later be replaced with driver defaults. tmpCfg = cfg; if (snd_pcm_hw_params_malloc (&hw_params)) { _errorString = "ERROR: could not malloc hwparams."; goto open_error; } if (snd_pcm_hw_params_any (_audioHandle, hw_params)) { _errorString = "ERROR: could not initialize hw params"; goto open_error; } if (snd_pcm_hw_params_set_access (_audioHandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) { _errorString = "ERROR: could not set access type"; goto open_error; } snd_pcm_format_t alsamode; switch (tmpCfg.precision) { case 8: tmpCfg.encoding = AUDIO_UNSIGNED_PCM; alsamode = SND_PCM_FORMAT_U8; break; case 16: tmpCfg.encoding = AUDIO_SIGNED_PCM; alsamode = SND_PCM_FORMAT_S16; break; default: _errorString = "ERROR: set desired number of bits for audio device."; goto open_error; } if (snd_pcm_hw_params_set_format (_audioHandle, hw_params, alsamode)) { _errorString = "ERROR: could not set sample format"; goto open_error; } if (snd_pcm_hw_params_set_channels (_audioHandle, hw_params, tmpCfg.channels)) { _errorString = "ERROR: could not set channel count"; goto open_error; } { // Gentoo bug #98769, comment 4 unsigned int rate = tmpCfg.frequency; if (snd_pcm_hw_params_set_rate_near (_audioHandle, hw_params, &rate, 0)) { _errorString = "ERROR: could not set sample rate"; goto open_error; } } _alsa_to_frames_divisor = tmpCfg.channels * tmpCfg.precision / 8; buffer_frames = 4096; snd_pcm_hw_params_set_period_size_near(_audioHandle, hw_params, &buffer_frames, 0); if (snd_pcm_hw_params (_audioHandle, hw_params)) { _errorString = "ERROR: could not set hw parameters"; goto open_error; } snd_pcm_hw_params_free (hw_params); hw_params = 0; if (snd_pcm_prepare (_audioHandle)) { _errorString = "ERROR: could not prepare audio interface for use"; goto open_error; } tmpCfg.bufSize = buffer_frames * _alsa_to_frames_divisor; #else // HAVE_ALSA_ASOUNDLIB_H // Obsolete interface int mask, wantedFormat, format; int rtn; int card = -1, dev = 0; if ((rtn = snd_pcm_open_preferred (&_audioHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK))) { _errorString = "ERROR: Could not open audio device."; goto open_error; } // Transfer input parameters to this object. // May later be replaced with driver defaults. tmpCfg = cfg; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; snd_pcm_channel_info_t pi; memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_info (_audioHandle, &pi))) { _errorString = "ALSA: snd_pcm_plugin_info failed."; goto open_error; } 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 = 1; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = tmpCfg.frequency; pp.format.voices = tmpCfg.channels; // Set sample precision and type of encoding. if ( tmpCfg.precision == 8 ) { tmpCfg.encoding = AUDIO_UNSIGNED_PCM; pp.format.format = SND_PCM_SFMT_U8; } if ( tmpCfg.precision == 16 ) { tmpCfg.encoding = AUDIO_SIGNED_PCM; pp.format.format = SND_PCM_SFMT_S16_LE; } if ((rtn = snd_pcm_plugin_params (_audioHandle, &pp)) < 0) { _errorString = "ALSA: snd_pcm_plugin_params failed."; goto open_error; } if ((rtn = snd_pcm_plugin_prepare (_audioHandle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { _errorString = "ALSA: snd_pcm_plugin_prepare failed."; goto open_error; } memset (&setup, 0, sizeof (setup)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_setup (_audioHandle, &setup)) < 0) { _errorString = "ALSA: snd_pcm_plugin_setup failed."; goto open_error; } tmpCfg.bufSize = setup.buf.block.frag_size; #endif #ifdef HAVE_EXCEPTIONS _sampleBuffer = new(std::nothrow) int_least8_t[tmpCfg.bufSize]; #else _sampleBuffer = new int_least8_t[tmpCfg.bufSize]; #endif if (!_sampleBuffer) { _errorString = "AUDIO: Unable to allocate memory for sample buffers."; goto open_error; } // Setup internal Config _settings = tmpCfg; // Update the users settings getConfig (cfg); return _sampleBuffer; open_error: #ifdef HAVE_ALSA_ASOUNDLIB_H if (hw_params) snd_pcm_hw_params_free (hw_params); #endif if (_audioHandle != NULL) close (); perror ("ALSA"); return NULL; }
static ALCboolean qsa_reset_playback(ALCdevice* device) { qsa_data* data=(qsa_data*)device->ExtraData; int32_t format=-1; switch(device->FmtType) { case DevFmtByte: format=SND_PCM_SFMT_S8; break; case DevFmtUByte: format=SND_PCM_SFMT_U8; break; case DevFmtShort: format=SND_PCM_SFMT_S16_LE; break; case DevFmtUShort: format=SND_PCM_SFMT_U16_LE; break; case DevFmtInt: format=SND_PCM_SFMT_S32_LE; break; case DevFmtUInt: format=SND_PCM_SFMT_U32_LE; break; case DevFmtFloat: format=SND_PCM_SFMT_FLOAT_LE; break; } /* we actually don't want to block on writes */ snd_pcm_nonblock_mode(data->pcmHandle, 1); /* Disable mmap to control data transfer to the audio device */ snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP); snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_BUFFER_PARTIAL_BLOCKS); // configure a sound channel memset(&data->cparams, 0, sizeof(data->cparams)); data->cparams.channel=SND_PCM_CHANNEL_PLAYBACK; data->cparams.mode=SND_PCM_MODE_BLOCK; data->cparams.start_mode=SND_PCM_START_FULL; data->cparams.stop_mode=SND_PCM_STOP_STOP; data->cparams.buf.block.frag_size=device->UpdateSize* ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType); data->cparams.buf.block.frags_max=device->NumUpdates; data->cparams.buf.block.frags_min=device->NumUpdates; data->cparams.format.interleave=1; data->cparams.format.rate=device->Frequency; data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans); data->cparams.format.format=format; if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0) { int original_rate=data->cparams.format.rate; int original_voices=data->cparams.format.voices; int original_format=data->cparams.format.format; int it; int jt; for (it=0; it<1; it++) { /* Check for second pass */ if (it==1) { original_rate=ratelist[0].rate; original_voices=channellist[0].channels; original_format=formatlist[0].format; } do { /* At first downgrade sample format */ jt=0; do { if (formatlist[jt].format==data->cparams.format.format) { data->cparams.format.format=formatlist[jt+1].format; break; } if (formatlist[jt].format==0) { data->cparams.format.format=0; break; } jt++; } while(1); if (data->cparams.format.format==0) { data->cparams.format.format=original_format; /* At secod downgrade sample rate */ jt=0; do { if (ratelist[jt].rate==data->cparams.format.rate) { data->cparams.format.rate=ratelist[jt+1].rate; break; } if (ratelist[jt].rate==0) { data->cparams.format.rate=0; break; } jt++; } while(1); if (data->cparams.format.rate==0) { data->cparams.format.rate=original_rate; data->cparams.format.format=original_format; /* At third downgrade channels number */ jt=0; do { if(channellist[jt].channels==data->cparams.format.voices) { data->cparams.format.voices=channellist[jt+1].channels; break; } if (channellist[jt].channels==0) { data->cparams.format.voices=0; break; } jt++; } while(1); } if (data->cparams.format.voices==0) { break; } } data->cparams.buf.block.frag_size=device->UpdateSize* data->cparams.format.voices* snd_pcm_format_width(data->cparams.format.format)/8; data->cparams.buf.block.frags_max=device->NumUpdates; data->cparams.buf.block.frags_min=device->NumUpdates; if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0) { continue; } else { break; } } while(1); if (data->cparams.format.voices!=0) { break; } } if (data->cparams.format.voices==0) { return ALC_FALSE; } } if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0) { return ALC_FALSE; } memset(&data->csetup, 0, sizeof(data->csetup)); data->csetup.channel=SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_setup(data->pcmHandle, &data->csetup)<0) { return ALC_FALSE; } /* now fill back to the our AL device */ device->Frequency=data->cparams.format.rate; switch (data->cparams.format.voices) { case 1: device->FmtChans=DevFmtMono; break; case 2: device->FmtChans=DevFmtStereo; break; case 4: device->FmtChans=DevFmtQuad; break; case 6: device->FmtChans=DevFmtX51; break; case 7: device->FmtChans=DevFmtX61; break; case 8: device->FmtChans=DevFmtX71; break; default: device->FmtChans=DevFmtMono; break; } switch (data->cparams.format.format) { case SND_PCM_SFMT_S8: device->FmtType=DevFmtByte; break; case SND_PCM_SFMT_U8: device->FmtType=DevFmtUByte; break; case SND_PCM_SFMT_S16_LE: device->FmtType=DevFmtShort; break; case SND_PCM_SFMT_U16_LE: device->FmtType=DevFmtUShort; break; case SND_PCM_SFMT_S32_LE: device->FmtType=DevFmtInt; break; case SND_PCM_SFMT_U32_LE: device->FmtType=DevFmtUInt; break; case SND_PCM_SFMT_FLOAT_LE: device->FmtType=DevFmtFloat; break; default: device->FmtType=DevFmtShort; break; } SetDefaultChannelOrder(device); device->UpdateSize=data->csetup.buf.block.frag_size/ (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType)); device->NumUpdates=data->csetup.buf.block.frags; data->size=data->csetup.buf.block.frag_size; data->buffer=malloc(data->size); if (!data->buffer) { return ALC_FALSE; } return ALC_TRUE; }
/* public methods (static but exported through the sysdep_dsp or plugin struct) */ static void *alsa_dsp_create(const void *flags) { int i, j; // audio_buf_info info; struct alsa_dsp_priv_data *priv = NULL; struct sysdep_dsp_struct *dsp = NULL; const struct sysdep_dsp_create_params *params = flags; const char *device = params->device; int err; int bytespersample; fprintf(stderr,"info: dsp_create called\n"); /* allocate the dsp struct */ if (!(dsp = calloc(1, sizeof(struct sysdep_dsp_struct)))) { fprintf(stderr, "error: malloc failed for struct sysdep_dsp_struct\n"); return NULL; } /* alloc private data */ if(!(priv = calloc(1, sizeof(struct alsa_dsp_priv_data)))) { fprintf(stderr, "error: malloc failed for struct dsp_priv_data\n"); alsa_dsp_destroy(dsp); return NULL; } /* fill in the functions and some data */ dsp->_priv = priv; dsp->get_freespace = alsa_dsp_get_freespace; dsp->write = alsa_dsp_write; dsp->destroy = alsa_dsp_destroy; dsp->hw_info.type = params->type; dsp->hw_info.samplerate = params->samplerate; priv->audio_dev.bMute = 0; priv->audio_dev.m_AudioHandle = NULL; priv->audio_dev.m_MixerHandle = NULL; priv->audio_dev.m_Acard = 0; priv->audio_dev.m_Adevice = 0; if (preferred_device) { if((err = snd_pcm_open_preferred(&(priv->audio_dev.m_AudioHandle), &priv->audio_dev.m_Acard, &priv->audio_dev.m_Adevice, SND_PCM_OPEN_PLAYBACK)) < 0) { fprintf(stderr,"info: snd_pcm_open_preferred failed: %s \n", snd_strerror(err)); alsa_dsp_destroy(dsp); return NULL; } } else { fprintf(stderr,"info: audio is using primary device\n"); if((err = snd_pcm_open(&(priv->audio_dev.m_AudioHandle), 0, 0, SND_PCM_OPEN_PLAYBACK)) < 0) { fprintf(stderr,"info: snd_pcm_open failed: %s \n", snd_strerror(err)); alsa_dsp_destroy(dsp); return NULL; } } memset (&(priv->audio_dev.m_Achaninfo), 0, sizeof (priv->audio_dev.m_Achaninfo)); priv->audio_dev.m_Achaninfo.channel = SND_PCM_CHANNEL_PLAYBACK; if ((err = snd_pcm_plugin_info (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Achaninfo))) < 0) { fprintf (stderr, "info: snd_pcm_plugin_info failed: %s\n", snd_strerror (err)); alsa_dsp_destroy(dsp); return NULL; } //needed to enable the count status parameter, mmap plugin disables this if((err = snd_plugin_set_disable(priv->audio_dev.m_AudioHandle, PLUGIN_DISABLE_MMAP)) < 0) { fprintf (stderr, "info: snd_plugin_set_disable failed: %s\n", snd_strerror (err)); alsa_dsp_destroy(dsp); return NULL; } /* calculate and set the fragsize & number of frags */ /* fragsize (as power of 2) */ i = 8; if (dsp->hw_info.type & SYSDEP_DSP_16BIT) i++; if (dsp->hw_info.type & SYSDEP_DSP_STEREO) i++; i += dsp->hw_info.samplerate / 22000; /* number of frags */ j = ((dsp->hw_info.samplerate * alsa_dsp_bytes_per_sample[dsp->hw_info.type] * params->bufsize) / (0x01 << i)) + 1; bytespersample=1; // dsp->hw_info.type &= ~SYSDEP_DSP_16BIT; // dsp->hw_info.type &= ~SYSDEP_DSP_STEREO; if (dsp->hw_info.type & SYSDEP_DSP_16BIT) bytespersample++; if (dsp->hw_info.type & SYSDEP_DSP_STEREO) bytespersample <<= 1; memset( &(priv->audio_dev.m_Aparams), 0, sizeof(priv->audio_dev.m_Aparams)); priv->audio_dev.m_Aparams.mode = SND_PCM_MODE_BLOCK; priv->audio_dev.m_Aparams.channel = SND_PCM_CHANNEL_PLAYBACK; priv->audio_dev.m_Aparams.start_mode = SND_PCM_START_FULL; priv->audio_dev.m_Aparams.stop_mode = SND_PCM_STOP_ROLLOVER; #if 0 priv->audio_dev.m_Aparams.buf.stream.queue_size = 512 * bytespersample; priv->audio_dev.m_Aparams.buf.stream.fill = SND_PCM_FILL_SILENCE; priv->audio_dev.m_Aparams.buf.stream.max_fill = 512 * bytespersample; #endif priv->audio_dev.m_Aparams.format.interleave = 1; priv->audio_dev.m_Aparams.format.rate = dsp->hw_info.samplerate; priv->audio_dev.m_Aparams.format.voices = (dsp->hw_info.type & SYSDEP_DSP_STEREO) ? 2 : 1; priv->audio_dev.m_Aparams.buf.block.frag_size = 1000; priv->audio_dev.m_Aparams.buf.block.frags_min = 1; priv->audio_dev.m_Aparams.buf.block.frags_max = 5; priv->audio_dev.m_BytesPerSample = bytespersample; priv->audio_dev.m_Aparams.format.format = #ifdef LSB_FIRST (dsp->hw_info.type & SYSDEP_DSP_16BIT) ? SND_PCM_SFMT_S16_LE : SND_PCM_SFMT_U8; #else (dsp->hw_info.type & SYSDEP_DSP_16BIT) ? SND_PCM_SFMT_S16_BE : SND_PCM_SFMT_U8; #endif if ((err = snd_pcm_plugin_params (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Aparams))) < 0) { fprintf (stderr, "info: snd_pcm_plugin_params failed: %s\n", snd_strerror (err)); alsa_dsp_destroy(dsp); return NULL; } if ((err = snd_pcm_plugin_prepare (priv->audio_dev.m_AudioHandle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { fprintf (stderr, "warning: snd_pcm_plugin_prepare failed: %s\n", snd_strerror (err)); } memset (&(priv->audio_dev.m_Asetup), 0, sizeof (priv->audio_dev.m_Asetup)); priv->audio_dev.m_Asetup.channel = SND_PCM_CHANNEL_PLAYBACK; if ((err = snd_pcm_plugin_setup (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Asetup))) < 0) { fprintf (stderr, "warning: snd_pcm_plugin_setup failed: %s\n", snd_strerror (err)); alsa_dsp_destroy(dsp); return NULL; } memset (&(priv->audio_dev.m_Astatus), 0, sizeof (priv->audio_dev.m_Astatus)); priv->audio_dev.m_Astatus.channel = SND_PCM_CHANNEL_PLAYBACK; if ((err = snd_pcm_plugin_status (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Astatus))) < 0) { fprintf (stderr, "warning: snd_pcm_plugin_status failed: %s\n", snd_strerror (err)); } dsp->hw_info.bufsize = priv->audio_dev.m_Asetup.buf.stream.queue_size / alsa_dsp_bytes_per_sample[dsp->hw_info.type]; #if 0 if ((err=snd_pcm_nonblock_mode(priv->audio_dev.m_AudioHandle, 1))<0) { fprintf(stderr, "error: error with non block mode: %s\n", snd_strerror (err)); } #endif return dsp; }
static int QSA_OpenDevice(_THIS, const char *devname, int iscapture) { int status = 0; int format = 0; SDL_AudioFormat test_format = 0; int found = 0; snd_pcm_channel_setup_t csetup; snd_pcm_channel_params_t cparams; /* Initialize all variables that we clean on shutdown */ this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof (struct SDL_PrivateAudioData))); if (this->hidden == NULL) { return SDL_OutOfMemory(); } SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData)); /* Initialize channel transfer parameters to default */ QSA_InitAudioParams(&cparams); /* Initialize channel direction: capture or playback */ this->hidden->iscapture = iscapture; /* Find deviceid and cardid by device name for playback */ if ((!this->hidden->iscapture) && (devname != NULL)) { uint32_t device; int32_t status; /* Search in the playback devices */ device = 0; do { status = SDL_strcmp(qsa_playback_device[device].name, devname); if (status == 0) { /* Found requested device */ this->hidden->deviceno = qsa_playback_device[device].deviceno; this->hidden->cardno = qsa_playback_device[device].cardno; break; } device++; if (device >= qsa_playback_devices) { QSA_CloseDevice(this); return SDL_SetError("No such playback device"); } } while (1); } /* Find deviceid and cardid by device name for capture */ if ((this->hidden->iscapture) && (devname != NULL)) { /* Search in the capture devices */ uint32_t device; int32_t status; /* Searching in the playback devices */ device = 0; do { status = SDL_strcmp(qsa_capture_device[device].name, devname); if (status == 0) { /* Found requested device */ this->hidden->deviceno = qsa_capture_device[device].deviceno; this->hidden->cardno = qsa_capture_device[device].cardno; break; } device++; if (device >= qsa_capture_devices) { QSA_CloseDevice(this); return SDL_SetError("No such capture device"); } } while (1); } /* Check if SDL requested default audio device */ if (devname == NULL) { /* Open system default audio device */ if (!this->hidden->iscapture) { status = snd_pcm_open_preferred(&this->hidden->audio_handle, &this->hidden->cardno, &this->hidden->deviceno, SND_PCM_OPEN_PLAYBACK); } else { status = snd_pcm_open_preferred(&this->hidden->audio_handle, &this->hidden->cardno, &this->hidden->deviceno, SND_PCM_OPEN_CAPTURE); } } else { /* Open requested audio device */ if (!this->hidden->iscapture) { status = snd_pcm_open(&this->hidden->audio_handle, this->hidden->cardno, this->hidden->deviceno, SND_PCM_OPEN_PLAYBACK); } else { status = snd_pcm_open(&this->hidden->audio_handle, this->hidden->cardno, this->hidden->deviceno, SND_PCM_OPEN_CAPTURE); } } /* Check if requested device is opened */ if (status < 0) { this->hidden->audio_handle = NULL; QSA_CloseDevice(this); return QSA_SetError("snd_pcm_open", status); } if (!QSA_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) { /* Disable QSA MMAP plugin for buggy audio drivers */ status = snd_pcm_plugin_set_disable(this->hidden->audio_handle, PLUGIN_DISABLE_MMAP); if (status < 0) { QSA_CloseDevice(this); return QSA_SetError("snd_pcm_plugin_set_disable", status); } } /* Try for a closest match on audio format */ format = 0; /* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */ found = 0; for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) { /* if match found set format to equivalent QSA format */ switch (test_format) { case AUDIO_U8: { format = SND_PCM_SFMT_U8; found = 1; } break; case AUDIO_S8: { format = SND_PCM_SFMT_S8; found = 1; } break; case AUDIO_S16LSB: { format = SND_PCM_SFMT_S16_LE; found = 1; } break; case AUDIO_S16MSB: { format = SND_PCM_SFMT_S16_BE; found = 1; } break; case AUDIO_U16LSB: { format = SND_PCM_SFMT_U16_LE; found = 1; } break; case AUDIO_U16MSB: { format = SND_PCM_SFMT_U16_BE; found = 1; } break; case AUDIO_S32LSB: { format = SND_PCM_SFMT_S32_LE; found = 1; } break; case AUDIO_S32MSB: { format = SND_PCM_SFMT_S32_BE; found = 1; } break; case AUDIO_F32LSB: { format = SND_PCM_SFMT_FLOAT_LE; found = 1; } break; case AUDIO_F32MSB: { format = SND_PCM_SFMT_FLOAT_BE; found = 1; } break; default: { break; } } if (!found) { test_format = SDL_NextAudioFormat(); } } /* assumes test_format not 0 on success */ if (test_format == 0) { QSA_CloseDevice(this); return SDL_SetError("QSA: Couldn't find any hardware audio formats"); } this->spec.format = test_format; /* Set the audio format */ cparams.format.format = format; /* Set mono/stereo/4ch/6ch/8ch audio */ cparams.format.voices = this->spec.channels; /* Set rate */ cparams.format.rate = this->spec.freq; /* Setup the transfer parameters according to cparams */ status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams); if (status < 0) { QSA_CloseDevice(this); return QSA_SetError("snd_pcm_channel_params", status); } /* Make sure channel is setup right one last time */ SDL_memset(&csetup, 0, sizeof(csetup)); if (!this->hidden->iscapture) { csetup.channel = SND_PCM_CHANNEL_PLAYBACK; } else { csetup.channel = SND_PCM_CHANNEL_CAPTURE; } /* Setup an audio channel */ if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) { QSA_CloseDevice(this); return SDL_SetError("QSA: Unable to setup channel"); } /* Calculate the final parameters for this audio specification */ SDL_CalculateAudioSpec(&this->spec); this->hidden->pcm_len = this->spec.size; if (this->hidden->pcm_len == 0) { this->hidden->pcm_len = csetup.buf.block.frag_size * this->spec.channels * (snd_pcm_format_width(format) / 8); } /* * Allocate memory to the audio buffer and initialize with silence * (Note that buffer size must be a multiple of fragment size, so find * closest multiple) */ this->hidden->pcm_buf = (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len); if (this->hidden->pcm_buf == NULL) { QSA_CloseDevice(this); return SDL_OutOfMemory(); } SDL_memset(this->hidden->pcm_buf, this->spec.silence, this->hidden->pcm_len); /* get the file descriptor */ if (!this->hidden->iscapture) { this->hidden->audio_fd = snd_pcm_file_descriptor(this->hidden->audio_handle, SND_PCM_CHANNEL_PLAYBACK); } else { this->hidden->audio_fd = snd_pcm_file_descriptor(this->hidden->audio_handle, SND_PCM_CHANNEL_CAPTURE); } if (this->hidden->audio_fd < 0) { QSA_CloseDevice(this); return QSA_SetError("snd_pcm_file_descriptor", status); } /* Prepare an audio channel */ if (!this->hidden->iscapture) { /* Prepare audio playback */ status = snd_pcm_plugin_prepare(this->hidden->audio_handle, SND_PCM_CHANNEL_PLAYBACK); } else { /* Prepare audio capture */ status = snd_pcm_plugin_prepare(this->hidden->audio_handle, SND_PCM_CHANNEL_CAPTURE); } if (status < 0) { QSA_CloseDevice(this); return QSA_SetError("snd_pcm_plugin_prepare", status); } /* We're really ready to rock and roll. :-) */ 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; }
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)); } }
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; };
static pj_status_t bb10_open_playback (struct bb10_stream *stream, const pjmedia_aud_param *param) { int ret = 0; snd_pcm_channel_info_t pi; snd_pcm_channel_setup_t setup; snd_mixer_group_t group; snd_pcm_channel_params_t pp; unsigned int rate; unsigned long tmp_buf_size; if (param->play_id < 0 || param->play_id >= stream->af->dev_cnt) { return PJMEDIA_EAUD_INVDEV; } PJ_ASSERT_RETURN(param->bits_per_sample == 16, PJMEDIA_EAUD_SAMPFORMAT); /* Use the bb10 audio manager API to open as opposed to QNX core audio * Echo cancellation built in */ if ((ret = audio_manager_snd_pcm_open_name( AUDIO_TYPE_VIDEO_CHAT, &stream->pb_pcm, &stream->pb_audio_manager_handle, (char*)"voice", SND_PCM_OPEN_PLAYBACK)) < 0) { TRACE_((THIS_FILE, "audio_manager_snd_pcm_open_name ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } /* Required call from January 2013 gold OS release */ snd_pcm_plugin_set_disable(stream->pb_pcm, PLUGIN_DISABLE_MMAP); /* Required call from January 2013 gold OS release */ snd_pcm_plugin_set_enable(stream->pb_pcm, PLUGIN_ROUTING); memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((ret = snd_pcm_plugin_info (stream->pb_pcm, &pi)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_info ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } memset (&pp, 0, sizeof (pp)); /* Request VoIP compatible capabilities */ 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_ROLLOVER; pp.buf.block.frag_size = param->samples_per_frame * param->bits_per_sample / 8; /* RIM recommends maximum of 5 */ pp.buf.block.frags_max = 5; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = param->clock_rate; pp.format.voices = param->channel_count; pp.format.format = get_alsa_pcm_fmt(param); /* Make the calls as per the wave sample */ if ((ret = snd_pcm_plugin_params (stream->pb_pcm, &pp)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_params ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } memset (&setup, 0, sizeof (setup)); memset (&group, 0, sizeof (group)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mixer_gid = &group.gid; if ((ret = snd_pcm_plugin_setup (stream->pb_pcm, &setup)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_setup ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } if (group.gid.name[0] == 0) { return PJMEDIA_EAUD_SYSERR; } rate = param->clock_rate; /* Set the sound device buffer size and latency */ if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY) { tmp_buf_size = rate * param->output_latency_ms / 1000; } else { tmp_buf_size = rate * PJMEDIA_SND_DEFAULT_PLAY_LATENCY / 1000; } /* Set period size to samples_per_frame frames. */ stream->pb_frames = param->samples_per_frame / param->channel_count; stream->param.output_latency_ms = tmp_buf_size * 1000 / rate; /* Set our buffer */ stream->pb_buf_size = stream->pb_frames * param->channel_count * param->bits_per_sample / 8; stream->pb_buf = (char *) pj_pool_alloc(stream->pool, stream->pb_buf_size); TRACE_((THIS_FILE, "bb10_open_playback: pb_frames = %d clock = %d", stream->pb_frames, param->clock_rate)); return PJ_SUCCESS; }
static pj_status_t bb10_open_playback (struct bb10_stream *stream, const pjmedia_aud_param *param) { int card = -1; int dev = 0; int ret = 0; snd_pcm_channel_info_t pi; snd_pcm_channel_setup_t setup; snd_mixer_group_t group; snd_pcm_channel_params_t pp; unsigned int rate; unsigned long tmp_buf_size; unsigned int handle; if (param->play_id < 0 || param->play_id >= stream->af->dev_cnt) { return PJMEDIA_EAUD_INVDEV; } #if PJ_BBSDK_VER >= 0x100006 if ((ret = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VOICE, &stream->pb_pcm, &handle, "/dev/snd/voicep", SND_PCM_OPEN_PLAYBACK)) < 0) { TRACE_((THIS_FILE, "audio_manager_snd_pcm_open_name ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } #else if ((ret = snd_pcm_open_preferred (&stream->pb_pcm, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0) { TRACE_((THIS_FILE, "snd_pcm_open_preferred ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } #endif /* TODO PJ_ZERO */ memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((ret = snd_pcm_plugin_info (stream->pb_pcm, &pi)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_info ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } memset (&pp, 0, sizeof (pp)); /* Request VoIP compatible capabilities * On simulator frag_size is always negotiated to 170 */ pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_PLAYBACK; pp.start_mode = SND_PCM_START_DATA; pp.stop_mode = SND_PCM_STOP_ROLLOVER; /* HARD CODE for the time being PJMEDIA expects 640 for 16khz */ pp.buf.block.frag_size = PREFERRED_FRAME_SIZE*2; /* Increasing this internal buffer count delays write failure in the loop */ pp.buf.block.frags_max = 4; pp.buf.block.frags_min = 1; pp.format.interleave = 1; /* HARD CODE for the time being PJMEDIA expects 16khz */ PJ_TODO(REMOVE_SAMPLE_RATE_HARD_CODE); pj_assert(param->clock_rate == VOIP_SAMPLE_RATE * 2); pp.format.rate = VOIP_SAMPLE_RATE*2; pp.format.voices = 1; pp.format.format = SND_PCM_SFMT_S16_LE; /* Make the calls as per the wave sample */ if ((ret = snd_pcm_plugin_params (stream->pb_pcm, &pp)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_params ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } memset (&setup, 0, sizeof (setup)); memset (&group, 0, sizeof (group)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mixer_gid = &group.gid; if ((ret = snd_pcm_plugin_setup (stream->pb_pcm, &setup)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_setup ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } if (group.gid.name[0] == 0) { return PJMEDIA_EAUD_SYSERR; } rate = param->clock_rate; /* Set the sound device buffer size and latency */ if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY) { tmp_buf_size = (rate / 1000) * param->output_latency_ms; } else { tmp_buf_size = (rate / 1000) * PJMEDIA_SND_DEFAULT_PLAY_LATENCY; } /* Set period size to samples_per_frame frames. */ stream->pb_frames = param->samples_per_frame; stream->param.output_latency_ms = tmp_buf_size / (rate / 1000); /* Set our buffer */ stream->pb_buf_size = stream->pb_frames * param->channel_count * (param->bits_per_sample/8); stream->pb_buf = (char *) pj_pool_alloc(stream->pool, stream->pb_buf_size); TRACE_((THIS_FILE, "bb10_open_playback: pb_frames = %d clock = %d", stream->pb_frames, param->clock_rate)); return PJ_SUCCESS; }
cst_audiodev *audio_open_alsa(int sps, int channels, cst_audiofmt fmt) { snd_pcm_channel_info_t pinfo; snd_pcm_channel_params_t params; snd_pcm_channel_setup_t setup; snd_pcm_t *pcm; cst_audiodev *ad; int err; #ifdef __QNXNTO__ if (snd_pcm_open_preferred(&pcm,&alsa_card,&alsa_device,SND_PCM_OPEN_PLAYBACK) < 0) { cst_errmsg("alsa_audio: failed to open audio device\n"); cst_error(); } if (snd_pcm_plugin_set_disable(pcm,PLUGIN_DISABLE_MMAP) < 0) { cst_errmsg("alsa_audio: failed to disable mmap\n"); snd_pcm_close(pcm); cst_error(); } #else if (snd_pcm_open(&pcm,alsa_card,alsa_device,SND_PCM_OPEN_PLAYBACK) < 0) { cst_errmsg("alsa_audio: failed to open audio device\n"); cst_error(); } #endif memset(&pinfo, 0, sizeof(pinfo)); memset(¶ms, 0, sizeof(params)); memset(&setup, 0, sizeof(setup)); pinfo.channel = SND_PCM_CHANNEL_PLAYBACK; snd_pcm_plugin_info(pcm,&pinfo); params.mode = SND_PCM_MODE_BLOCK; params.channel = SND_PCM_CHANNEL_PLAYBACK; params.start_mode = SND_PCM_START_DATA; params.stop_mode = SND_PCM_STOP_STOP; params.buf.block.frag_size = pinfo.max_fragment_size; params.buf.block.frags_max = 1; params.buf.block.frags_min = 1; params.format.interleave = 1; params.format.rate = sps; params.format.voices = channels; switch (fmt) { case CST_AUDIO_LINEAR16: if (CST_LITTLE_ENDIAN) params.format.format = SND_PCM_SFMT_S16_LE; else params.format.format = SND_PCM_SFMT_S16_BE; break; case CST_AUDIO_LINEAR8: params.format.format = SND_PCM_SFMT_U8; break; case CST_AUDIO_MULAW: params.format.format = SND_PCM_SFMT_MU_LAW; break; } if((err = snd_pcm_plugin_params(pcm,¶ms)) < 0) { cst_errmsg("alsa_audio params setting failed: %s\n",snd_strerror(err)); snd_pcm_close(pcm); cst_error(); } if((err = snd_pcm_plugin_setup(pcm,SND_PCM_CHANNEL_PLAYBACK)) > 0) { cst_errmsg("alsa_audio sound prepare setting failed: %s\n",snd_strerror(err)); snd_pcm_close(pcm); cst_error(); } if((err = snd_pcm_plugin_prepare(pcm,SND_PCM_CHANNEL_PLAYBACK)) > 0) { cst_errmsg("alsa_audio sound prepare setting failed: %s\n",snd_strerror(err)); snd_pcm_close(pcm); cst_error(); } pinfo.channel = SND_PCM_CHANNEL_PLAYBACK; snd_pcm_plugin_info(pcm,&pinfo); ad = cst_alloc(cst_audiodev, 1); ad->platform_data = pcm; ad->sps = ad->real_sps = sps; ad->channels = ad->real_channels = channels; ad->fmt = ad->real_fmt = fmt; return ad; }
static pj_status_t bb10_open_capture (struct bb10_stream *stream, const pjmedia_aud_param *param) { int ret = 0; unsigned int rate; unsigned long tmp_buf_size; int card = -1; int dev = 0; int frame_size; snd_pcm_channel_info_t pi; snd_mixer_group_t group; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; unsigned int handle; if (param->rec_id < 0 || param->rec_id >= stream->af->dev_cnt) return PJMEDIA_EAUD_INVDEV; #if PJ_BBSDK_VER >= 0x100006 if ((ret = audio_manager_snd_pcm_open_name(AUDIO_TYPE_VOICE, &stream->ca_pcm, &handle, "/dev/snd/voicec", SND_PCM_OPEN_CAPTURE)) < 0) { TRACE_((THIS_FILE, "audio_manager_snd_pcm_open_name ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } #else /* BB10 Audio init here (not prepare) */ PJ_UNUSED_ARG(handle); if ((ret = snd_pcm_open_preferred (&stream->ca_pcm, &card, &dev, SND_PCM_OPEN_CAPTURE)) < 0) { TRACE_((THIS_FILE, "snd_pcm_open_preferred ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } #endif /* sample reads the capabilities of the capture */ memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_CAPTURE; if ((ret = snd_pcm_plugin_info (stream->ca_pcm, &pi)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_info ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } /* Request the VoIP parameters * These parameters are different to waverec sample */ memset (&pp, 0, sizeof (pp)); /* 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; /* HARD CODE for the time being PJMEDIA expects 640 for 16khz */ pp.buf.block.frag_size = PREFERRED_FRAME_SIZE*2; /* Not applicable for capture hence -1 */ pp.buf.block.frags_max = -1; pp.buf.block.frags_min = 1; pp.format.interleave = 1; /* HARD CODE for the time being PJMEDIA expects 16khz */ PJ_TODO(REMOVE_SAMPLE_RATE_HARD_CODE); pj_assert(param->clock_rate == VOIP_SAMPLE_RATE * 2); pp.format.rate = VOIP_SAMPLE_RATE*2; pp.format.voices = 1; pp.format.format = SND_PCM_SFMT_S16_LE; /* make the request */ if ((ret = snd_pcm_plugin_params (stream->ca_pcm, &pp)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_params ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } /* 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 (stream->ca_pcm, &setup)) < 0) { TRACE_((THIS_FILE, "snd_pcm_plugin_setup ret = %d", ret)); return PJMEDIA_EAUD_SYSERR; } frame_size = setup.buf.block.frag_size; if (group.gid.name[0] == 0) { } else { } /* frag_size should be 160 */ frame_size = setup.buf.block.frag_size; /* END BB10 init */ /* Set clock rate */ rate = param->clock_rate; stream->ca_frames = (unsigned long) param->samples_per_frame / param->channel_count; /* Set the sound device buffer size and latency */ if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) { tmp_buf_size = (rate / 1000) * param->input_latency_ms; } else { tmp_buf_size = (rate / 1000) * PJMEDIA_SND_DEFAULT_REC_LATENCY; } stream->param.input_latency_ms = tmp_buf_size / (rate / 1000); /* Set our buffer */ stream->ca_buf_size = stream->ca_frames * param->channel_count * (param->bits_per_sample/8); stream->ca_buf = (char *)pj_pool_alloc (stream->pool, stream->ca_buf_size); TRACE_((THIS_FILE, "bb10_open_capture: ca_frames = %d clock = %d", stream->ca_frames, param->clock_rate)); return PJ_SUCCESS; }
static int NTO_OpenAudio(_THIS, SDL_AudioSpec *spec) { int rval; int format; Uint16 test_format; int twidth; int found; #ifdef DEBUG_AUDIO fprintf(stderr, "NTO_OpenAudio\n"); #endif audio_handle = NULL; this->enabled = 0; if ( pcm_buf != NULL ) { free((Uint8 *)pcm_buf); pcm_buf = NULL; } /* initialize channel transfer parameters to default */ init_pcm_cparams(&cparams); /* Open the audio device */ rval = snd_pcm_open_preferred(&audio_handle, &card_no, &device_no, OPEN_FLAGS); if ( rval < 0 ) { SDL_SetError("snd_pcm_open failed: %s\n", snd_strerror(rval)); return(-1); } /* set to nonblocking mode */ if ((rval = snd_pcm_nonblock_mode(audio_handle, 1))<0) //I assume 1 means on { SDL_SetError("snd_pcm_nonblock_mode failed: %s\n", snd_strerror(rval)); return(-1); } /* enable count status parameter */ if ((rval = snd_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP))<0) { SDL_SetError("snd_plugin_set_disable failed: %s\n", snd_strerror(rval)); return(-1); } /* Try for a closest match on audio format */ format = 0; found = 0; // can't use format as SND_PCM_SFMT_U8 = 0 in nto for ( test_format = SDL_FirstAudioFormat(spec->format); !found ; ) { #ifdef DEBUG_AUDIO fprintf(stderr, "Trying format 0x%4.4x spec->samples %d\n", test_format,spec->samples); #endif /* if match found set format to equivalent ALSA format */ switch ( test_format ) { case AUDIO_U8: format = SND_PCM_SFMT_U8; cparams.buf.block.frag_size = spec->samples * spec->channels; found = 1; break; case AUDIO_S8: format = SND_PCM_SFMT_S8; cparams.buf.block.frag_size = spec->samples * spec->channels; found = 1; break; case AUDIO_S16LSB: format = SND_PCM_SFMT_S16_LE; cparams.buf.block.frag_size = spec->samples*2 * spec->channels; found = 1; break; case AUDIO_S16MSB: format = SND_PCM_SFMT_S16_BE; cparams.buf.block.frag_size = spec->samples*2 * spec->channels; found = 1; break; case AUDIO_U16LSB: format = SND_PCM_SFMT_U16_LE; cparams.buf.block.frag_size = spec->samples*2 * spec->channels; found = 1; break; case AUDIO_U16MSB: format = SND_PCM_SFMT_U16_BE; cparams.buf.block.frag_size = spec->samples*2 * spec->channels; found = 1; break; default: break; } if ( ! found ) { test_format = SDL_NextAudioFormat(); } } /* assumes test_format not 0 on success */ if ( test_format == 0 ) { SDL_SetError("Couldn't find any hardware audio formats"); return(-1); } spec->format = test_format; /* Set the audio format */ cparams.format.format = format; /* Set mono or stereo audio (currently only two channels supported) */ cparams.format.voices = spec->channels; #ifdef DEBUG_AUDIO fprintf(stderr,"intializing channels %d\n", cparams.format.voices); #endif /* Set rate */ cparams.format.rate = spec->freq ; /* Setup the transfer parameters according to cparams */ rval = snd_pcm_plugin_params(audio_handle, &cparams); if (rval < 0) { SDL_SetError("snd_pcm_channel_params failed: %s\n", snd_strerror (rval)); return(-1); } /* Make sure channel is setup right one last time */ memset( &csetup, 0, sizeof( csetup ) ); csetup.channel = SND_PCM_CHANNEL_PLAYBACK; if ( snd_pcm_plugin_setup( audio_handle, &csetup ) < 0 ) { SDL_SetError("Unable to setup playback channel\n" ); return(-1); } else { #ifdef DEBUG_AUDIO fprintf(stderr,"requested format: %d\n",cparams.format.format); fprintf(stderr,"requested frag size: %d\n",cparams.buf.block.frag_size); fprintf(stderr,"requested max frags: %d\n\n",cparams.buf.block.frags_max); fprintf(stderr,"real format: %d\n", csetup.format.format ); fprintf(stderr,"real frag size : %d\n", csetup.buf.block.frag_size ); fprintf(stderr,"real max frags : %d\n", csetup.buf.block.frags_max ); #endif // DEBUG_AUDIO } /* Allocate memory to the audio buffer and initialize with silence (Note that buffer size must be a multiple of fragment size, so find closest multiple) */ twidth = snd_pcm_format_width(format); if (twidth < 0) { printf("snd_pcm_format_width failed\n"); twidth = 0; } #ifdef DEBUG_AUDIO fprintf(stderr,"format is %d bits wide\n",twidth); #endif pcm_len = spec->size ; #ifdef DEBUG_AUDIO fprintf(stderr,"pcm_len set to %d\n", pcm_len); #endif if (pcm_len == 0) { pcm_len = csetup.buf.block.frag_size; } pcm_buf = (Uint8*)malloc(pcm_len); if (pcm_buf == NULL) { SDL_SetError("pcm_buf malloc failed\n"); return(-1); } memset(pcm_buf,spec->silence,pcm_len); #ifdef DEBUG_AUDIO fprintf(stderr,"pcm_buf malloced and silenced.\n"); #endif /* get the file descriptor */ if( (audio_fd = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { fprintf(stderr, "snd_pcm_file_descriptor failed with error code: %d\n", audio_fd); } /* Trigger audio playback */ rval = snd_pcm_plugin_prepare( audio_handle, SND_PCM_CHANNEL_PLAYBACK); if (rval < 0) { SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rval)); return(-1); } this->enabled = 1; /* Get the parent process id (we're the parent of the audio thread) */ parent = getpid(); /* We're ready to rock and roll. :-) */ return(0); }
/***************************************************************************** * Open : creates a handle and opens an alsa device ***************************************************************************** * This function opens an alsa device, through the alsa API *****************************************************************************/ int E_(OpenAudio)( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; int i_ret; int i_bytes_per_sample; int i_nb_channels; snd_pcm_channel_info_t pi; snd_pcm_channel_params_t pp; aout_instance_t *p_aout = (aout_instance_t *)p_this; /* allocate structure */ p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) ); if( p_aout->output.p_sys == NULL ) { msg_Err( p_aout, "out of memory" ); return -1; } /* open audio device */ if( ( i_ret = snd_pcm_open_preferred( &p_aout->output.p_sys->p_pcm_handle, &p_aout->output.p_sys->i_card, &p_aout->output.p_sys->i_device, SND_PCM_OPEN_PLAYBACK ) ) < 0 ) { msg_Err( p_aout, "unable to open audio device (%s)", snd_strerror( i_ret ) ); free( p_aout->output.p_sys ); return -1; } /* disable mmap */ if( ( i_ret = snd_pcm_plugin_set_disable( p_aout->output.p_sys->p_pcm_handle, PLUGIN_DISABLE_MMAP ) ) < 0 ) { msg_Err( p_aout, "unable to disable mmap (%s)", snd_strerror(i_ret) ); E_(CloseAudio)( p_this ); free( p_aout->output.p_sys ); return -1; } p_aout->output.p_sys->p_silent_buffer = malloc( DEFAULT_FRAME_SIZE * 4 ); p_aout->output.pf_play = Play; aout_VolumeSoftInit( p_aout ); memset( &pi, 0, sizeof(pi) ); memset( &pp, 0, sizeof(pp) ); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if( ( i_ret = snd_pcm_plugin_info( p_aout->output.p_sys->p_pcm_handle, &pi ) ) < 0 ) { msg_Err( p_aout, "unable to get plugin info (%s)", snd_strerror( i_ret ) ); E_(CloseAudio)( p_this ); free( p_aout->output.p_sys ); return -1; } 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.frags_max = 3; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = p_aout->output.output.i_rate; i_nb_channels = aout_FormatNbChannels( &p_aout->output.output ); if ( i_nb_channels > 2 ) { /* I don't know if QNX supports more than two channels. */ i_nb_channels = 2; p_aout->output.output.i_channels = AOUT_CHAN_STEREO; } pp.format.voices = i_nb_channels; p_aout->output.output.i_format = AOUT_FMT_S16_NE; p_aout->output.i_nb_samples = DEFAULT_FRAME_SIZE; pp.format.format = SND_PCM_SFMT_S16; i_bytes_per_sample = 2; pp.buf.block.frag_size = p_aout->output.i_nb_samples * p_aout->output.output.i_channels * i_bytes_per_sample; /* set parameters */ if( ( i_ret = snd_pcm_plugin_params( p_aout->output.p_sys->p_pcm_handle, &pp ) ) < 0 ) { msg_Err( p_aout, "unable to set parameters (%s)", snd_strerror(i_ret) ); E_(CloseAudio)( p_this ); free( p_aout->output.p_sys ); return -1; } /* prepare channel */ if( ( i_ret = snd_pcm_plugin_prepare( p_aout->output.p_sys->p_pcm_handle, SND_PCM_CHANNEL_PLAYBACK ) ) < 0 ) { msg_Err( p_aout, "unable to prepare channel (%s)", snd_strerror( i_ret ) ); E_(CloseAudio)( p_this ); free( p_aout->output.p_sys ); return -1; } /* Create audio thread and wait for its readiness. */ if( vlc_thread_create( p_aout, "aout", QNXaoutThread, VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) ) { msg_Err( p_aout, "cannot create QNX audio thread (%s)", strerror(errno) ); E_(CloseAudio)( p_this ); free( p_aout->output.p_sys ); return -1; } return( 0 ); }
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; }
// 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; }