void* RunAudio() { while(true) { if (!paused) { memset(mixbuf, 0, mixlen); NativeMix((short *)mixbuf, mixlen / 4); fd_set rfds, wfds; int nflds; if (!paused && (FD_ISSET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds))) { snd_pcm_plugin_write(pcm_handle, mixbuf, mixlen); } FD_ZERO(&rfds); FD_ZERO(&wfds); FD_SET(snd_mixer_file_descriptor(mixer_handle), &rfds); FD_SET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds); nflds = std::max(snd_mixer_file_descriptor(mixer_handle), snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK)); select (nflds+1, &rfds, &wfds, NULL, NULL); } else delay((AUDIO_SAMPLES*1000)/AUDIO_FREQ); } }
static int audio_open(audiodevice_t *dev, chanfmt_t fmt) { audio_alsa05_t *alsa = (audio_alsa05_t *)dev->data_pcm; snd_pcm_channel_params_t p; snd_pcm_channel_setup_t s; if (0 > snd_pcm_open(&alsa->pcm_handle, alsa->card, alsa->pcm_dev, SND_PCM_OPEN_PLAYBACK)) { WARNING("Opening audio device %d failed\n", alsa->pcm_dev); goto _err_exit; } memset(&alsa->info, 0, sizeof(snd_pcm_channel_info_t)); if (0 > snd_pcm_channel_info(alsa->pcm_handle, &alsa->info)) { WARNING("param get failed\n"); goto _err_exit; } memset(&p, 0, sizeof(p)); p.mode = SND_PCM_MODE_BLOCK; p.start_mode = SND_PCM_START_DATA; p.channel = SND_PCM_CHANNEL_PLAYBACK; p.stop_mode = SND_PCM_STOP_STOP; p.buf.block.frag_size = 1536; p.buf.block.frags_max = 6; p.buf.block.frags_min = 1; p.format.rate = fmt.rate; p.format.format = fmt.bit == 8 ? SND_PCM_SFMT_U8 : SND_PCM_SFMT_S16; p.format.voices = fmt.ch; p.format.interleave = 1; alsa->silence = fmt.bit == 8 ? 0x80 : 0; if (0 > snd_pcm_channel_params(alsa->pcm_handle, &p)) { WARNING("Unable to set channel params\n"); goto _err_exit; } if (0 > snd_pcm_channel_prepare(alsa->pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) { WARNING("Unable to prepare channel\n"); goto _err_exit; } memset(&s, 0, sizeof(s)); s.mode = SND_PCM_MODE_BLOCK; s.channel = SND_PCM_CHANNEL_PLAYBACK; if (0 > snd_pcm_channel_setup(alsa->pcm_handle, &s)) { WARNING("Unable to obtain setup\n"); goto _err_exit; } dev->buf.len = s.buf.block.frag_size; dev->fd = snd_pcm_file_descriptor(alsa->pcm_handle, SND_PCM_CHANNEL_PLAYBACK); return OK; _err_exit: dev->fd = -1; return NG; }
static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName) { qsa_data *data; int card, dev; 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_PLAYBACK); else { const DevMap *iter; if(VECTOR_SIZE(DeviceNameMap) == 0) deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap); #define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0) VECTOR_FIND_IF(iter, const DevMap, DeviceNameMap, MATCH_DEVNAME); #undef MATCH_DEVNAME if(iter == VECTOR_ITER_END(DeviceNameMap)) { free(data); return ALC_INVALID_DEVICE; } status = snd_pcm_open(&data->pcmHandle, iter->card, iter->dev, SND_PCM_OPEN_PLAYBACK); } if(status < 0) { free(data); return ALC_INVALID_DEVICE; } data->audio_fd = snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK); 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; return ALC_NO_ERROR; }
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; }
int main (int argc, char **argv) { int card = -1; int dev = 0; snd_pcm_t *pcm_handle; FILE *file; wave_hdr wav_header; int samples; int sample_rate; int sample_channels; int sample_bits; char *sample_buffer; int fragsize = -1; int verbose = 0; int rtn; int final_return_code = -1; snd_pcm_channel_info_t pi; snd_mixer_t *mixer_handle; snd_mixer_group_t group; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; int bsize, bytes_read, total_written = 0; fd_set rfds, wfds; uint32_t voice_mask[] = { 0, 0, 0, 0 }; snd_pcm_voice_conversion_t voice_conversion; int voice_override = 0; int num_frags = -1; char input_file[PATH_MAX]; char cwd[PATH_MAX]; screen_context_t screen_cxt; screen_window_t screen_win; screen_buffer_t screen_buf; int screen_fill_attribs[] = { SCREEN_BLIT_COLOR, COLOR_PURPLE, SCREEN_BLIT_END }; int screen_dirty[4] = { 0, 0, 1024, 600 }; //start with sane default values int idle_mode = SCREEN_IDLE_MODE_KEEP_AWAKE; int usage = SCREEN_USAGE_NATIVE; if (screen_create_context(&screen_cxt, 0) != 0) { return err("failed to create context"); } if (screen_create_window(&screen_win, screen_cxt) != 0) { err("failed to create window"); goto fail1; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage) != 0) { err("failed to set native usage mode"); goto fail2; } if (screen_create_window_buffers(screen_win, 1) != 0) { err("failed to set native usage mode"); goto fail2; } if(screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf) != 0) { err("failed to get screen buffer"); goto fail2; } if (screen_fill(screen_cxt, screen_buf, screen_fill_attribs) != 0) { err("failed to fill the screen"); goto fail3; } if (screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, screen_dirty+2) != 0) { err("failed to get window size"); goto fail3; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_IDLE_MODE, &idle_mode) != 0) { err("failed to set idle mode"); goto fail3; } if (screen_post_window(screen_win, screen_buf, 1, screen_dirty, 0) != 0) { err("failed to post the window"); goto fail3; } if ((rtn = snd_pcm_open_preferred (&pcm_handle, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0) { err ("device open"); goto fail3; } getcwd(cwd, PATH_MAX); rtn = snprintf(input_file, PATH_MAX, "%s%s", cwd, WAV_RELATIVE_PATH); if (rtn > PATH_MAX - 1) { err ("File name and path too long"); goto fail4; } if ((file = fopen (input_file, "r")) == 0) { err ("File open failed"); goto fail4; } if (check_hdr (file) == -1) { err ("check_hdr failed"); goto fail5; } samples = find_tag (file, "fmt "); fread (&wav_header, sizeof (wav_header), 1, file); fseek (file, (samples - sizeof (wave_hdr)), SEEK_CUR); sample_rate = ENDIAN_LE32 (wav_header.samples_per_sec); sample_channels = ENDIAN_LE16 (wav_header.channels); sample_bits = ENDIAN_LE16 (wav_header.bits_per_sample); printf ("SampleRate = %d, channels = %d, SampleBits = %d\n", sample_rate, sample_channels, sample_bits); /* disabling mmap is not actually required in this example but it is included to * demonstrate how it is used when it is required. */ if ((rtn = snd_pcm_plugin_set_disable (pcm_handle, PLUGIN_DISABLE_MMAP)) < 0) { fprintf (stderr, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror (rtn)); goto fail5; } memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_info (pcm_handle, &pi)) < 0) { fprintf (stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror (rtn)); goto fail5; } memset (&pp, 0, sizeof (pp)); pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_PLAYBACK; pp.start_mode = SND_PCM_START_FULL; pp.stop_mode = SND_PCM_STOP_STOP; pp.buf.block.frag_size = pi.max_fragment_size; if (fragsize != -1) { pp.buf.block.frag_size = fragsize; } pp.buf.block.frags_max = num_frags; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = sample_rate; pp.format.voices = sample_channels; if (ENDIAN_LE16 (wav_header.format_tag) == 6) pp.format.format = SND_PCM_SFMT_A_LAW; else if (ENDIAN_LE16 (wav_header.format_tag) == 7) pp.format.format = SND_PCM_SFMT_MU_LAW; else if (sample_bits == 8) pp.format.format = SND_PCM_SFMT_U8; else if (sample_bits == 24) pp.format.format = SND_PCM_SFMT_S24; else pp.format.format = SND_PCM_SFMT_S16_LE; strcpy (pp.sw_mixer_subchn_name, "Wave playback channel"); if ((rtn = snd_pcm_plugin_params (pcm_handle, &pp)) < 0) { fprintf (stderr, "snd_pcm_plugin_params failed: %s\n", snd_strerror (rtn)); goto fail5; } if ((rtn = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { fprintf (stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rtn)); goto fail5; } if (voice_override) { snd_pcm_plugin_get_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &voice_conversion); voice_conversion.matrix[0] = voice_mask[0]; voice_conversion.matrix[1] = voice_mask[1]; voice_conversion.matrix[2] = voice_mask[2]; voice_conversion.matrix[3] = voice_mask[3]; snd_pcm_plugin_set_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &voice_conversion); } memset (&setup, 0, sizeof (setup)); memset (&group, 0, sizeof (group)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mixer_gid = &group.gid; if ((rtn = snd_pcm_plugin_setup (pcm_handle, &setup)) < 0) { fprintf (stderr, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (rtn)); goto fail5; } printf ("Format %s \n", snd_pcm_get_format_name (setup.format.format)); printf ("Frag Size %d \n", setup.buf.block.frag_size); printf ("Total Frags %d \n", setup.buf.block.frags); printf ("Rate %d \n", setup.format.rate); printf ("Voices %d \n", setup.format.voices); bsize = setup.buf.block.frag_size; if (group.gid.name[0] == 0) { fprintf (stderr, "Mixer Pcm Group [%s] Not Set \n", group.gid.name); goto fail5; } printf ("Mixer Pcm Group [%s]\n", group.gid.name); if ((rtn = snd_mixer_open (&mixer_handle, card, setup.mixer_device)) < 0) { fprintf (stderr, "snd_mixer_open failed: %s\n", snd_strerror (rtn)); goto fail5; } samples = find_tag (file, "data"); sample_buffer = malloc (bsize); FD_ZERO (&rfds); FD_ZERO (&wfds); bytes_read = 1; while (total_written < samples && bytes_read > 0) { if (tcgetpgrp (0) == getpid ()) FD_SET (STDIN_FILENO, &rfds); FD_SET (snd_mixer_file_descriptor (mixer_handle), &rfds); FD_SET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds); rtn = max (snd_mixer_file_descriptor (mixer_handle), snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)); if (select (rtn + 1, &rfds, &wfds, NULL, NULL) == -1) { err ("select"); goto fail6; } if (FD_ISSET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds)) { snd_pcm_channel_status_t status; int written = 0; if ((bytes_read = fread (sample_buffer, 1, min (samples - total_written, bsize), file)) <= 0) continue; written = snd_pcm_plugin_write (pcm_handle, sample_buffer, bytes_read); if (verbose) printf ("bytes written = %d \n", written); if (written < bytes_read) { memset (&status, 0, sizeof (status)); status.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_status (pcm_handle, &status) < 0) { fprintf (stderr, "underrun: playback channel status error\n"); goto fail6; } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_UNDERRUN) { if (snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0) { fprintf (stderr, "underrun: playback channel prepare error\n"); goto fail6; } } if (written < 0) written = 0; written += snd_pcm_plugin_write (pcm_handle, sample_buffer + written, bytes_read - written); } total_written += written; } } bytes_read = snd_pcm_plugin_flush (pcm_handle, SND_PCM_CHANNEL_PLAYBACK); final_return_code = 0; fail6: rtn = snd_mixer_close (mixer_handle); fail5: fclose (file); fail4: rtn = snd_pcm_close (pcm_handle); fail3: screen_destroy_buffer(screen_buf); fail2: screen_destroy_window(screen_win); fail1: screen_destroy_context(screen_cxt); return final_return_code; }
static 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); }
int writePcmData (PcmDevice *pcm, const unsigned char *buffer, int count) { return writeFile(snd_pcm_file_descriptor(pcm->handle, pcm->parameters.channel), buffer, count); }
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; }
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; }
static gboolean alsa_open (void *dp) { alsa_driver * const d = dp; int mf, err; snd_pcm_format_t pf; // snd_pcm_channel_info_t pcm_info; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; snd_pcm_channel_flush(d->soundfd, SND_PCM_CHANNEL_PLAYBACK); memset(&pp, 0, sizeof(pp)); err = snd_pcm_open(&(d->soundfd), d->card_number, d->device_number, SND_PCM_OPEN_PLAYBACK); if (err != 0) { char buf[256]; g_sprintf(buf, _("Couldn't open ALSA device for sound output (card:%d, device:%d):\n%s"), d->card_number, d->device_number, snd_strerror(err)); error_error(buf); goto out; } // --- // Set non-blocking mode. // --- // snd_pcm_nonblock_mode(d->soundfd, 1); d->outtime = 0; d->bits = 0; mf = 0; // -- // Set channel parameters // -- 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; // --- // Select audio format // --- memset(&pf, 0, sizeof(pf)); pf.interleave = 1; if (d->p_resolution == 16) { pf.format = SND_PCM_SFMT_S16_LE; d->bits = 16; mf = ST_MIXER_FORMAT_S16_LE; } else { pf.format = SND_PCM_SFMT_U8; d->bits = 8; mf = ST_MIXER_FORMAT_S8; } pf.rate = d->p_mixfreq; d->playrate = d->p_mixfreq; if(d->p_channels == 2) { d->stereo = 1; pf.voices = d->p_channels; mf |= ST_MIXER_FORMAT_STEREO; } else { pf.voices = d->p_channels; d->stereo = 0; } d->mf = mf; memcpy(&pp.format, &pf, sizeof(pf)); // pp.buf.block.frag_size = d->p_fragsize * pf.voices * (d->bits / 8); pp.buf.block.frag_size = d->p_fragsize; pp.buf.block.frags_max = -1; pp.buf.block.frags_min = 1; err = snd_pcm_channel_params(d->soundfd, &pp); if (err < 0) { error_error(_("Required output-channel parameters not supported.\n")); goto out; } if (snd_pcm_channel_prepare(d->soundfd, SND_PCM_CHANNEL_PLAYBACK) < 0) { error_error(_("Unable to prepare ALSA channel.\n")); goto out; } // --- // Get buffering parameters // --- memset(&setup, 0, sizeof(setup)); setup.mode = SND_PCM_MODE_BLOCK; setup.channel = SND_PCM_CHANNEL_PLAYBACK; err = snd_pcm_channel_setup(d->soundfd, &setup); if (err < 0) { error_error(_("Alsa setup error.\n")); goto out; } // snd_pcm_channel_status(d->soundfd, &pbstat); // d->fragsize = pbstat.fragment_size; d->numfrags = setup.buf.block.frags; d->fragsize = setup.buf.block.frag_size; /* fprintf(stderr, "Numfrags: %d\n", d->numfrags); fprintf(stderr, "Fragsize: %d\n", d->fragsize); */ d->sndbuf = calloc(1, d->fragsize); if(d->stereo == 1) { d->fragsize /= 2; } if(d->bits == 16) { d->fragsize /= 2; } d->polltag = audio_poll_add(snd_pcm_file_descriptor(d->soundfd, SND_PCM_CHANNEL_PLAYBACK), GDK_INPUT_WRITE, alsa_poll_ready_playing, d); /* d->firstpoll = TRUE; */ d->firstpoll = TRUE; d->playtime = 0; return TRUE; out: alsa_release(dp); return FALSE; }
int main(int argc, char **argv) { FILE *file; int samples; char *sample_buffer; int rtn, final_return_code = -1, exit_application = 0; int bsize, bytes_read, total_written = 0; fd_set rfds, wfds; char input_file[PATH_MAX]; char cwd[PATH_MAX]; /* * Before we can listen for events from the BlackBerry Tablet OS platform * services, we need to initialize the BPS infrastructure */ bps_initialize(); if (setup_screen() != EXIT_SUCCESS) { printf("Unable to set up the screen. Exiting."); exit(-1); } /* * Once the BPS infrastructure has been initialized we can register for * events from the various BlackBerry Tablet OS platform services. The * Navigator service manages and delivers application life cycle and * visibility events. * * For this sample, we request Navigator events so we can track when * the system is terminating the application (NAVIGATOR_EXIT event). * This allows us to clean up application resources. * * We request Audio Device events because we want to make sure that * we properly handle changes in audio output. * * We request dialog events to properly initialize the dialog * subsystem in order to display status and error messages. */ if (BPS_SUCCESS != navigator_request_events(0)) { fprintf(stderr, "Error requesting navigator events: %s", strerror(errno)); exit(-1); } if (BPS_SUCCESS != dialog_request_events(0)) { fprintf(stderr, "Error requesting dialog events: %s", strerror(errno)); exit(-1); } if (BPS_SUCCESS != audiodevice_request_events(0)) { fprintf(stderr, "Error requesting audio device events: %s", strerror(errno)); exit(-1); } /* * Create and display the dialog. */ create_dialog(); /* * Open and check the input file. */ 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 fail1; } if ((file = fopen(input_file, "r")) == 0) { err("File open failed"); goto fail1; } if (check_hdr(file) == -1) { err("check_hdr failed"); goto fail2; } /* * Parse the headers in the wav file to figure out what kind of data we * are dealing with in the file. */ 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); snprintf(msg, MSG_SIZE, "SampleRate = %d, channels = %d, SampleBits = %d\n", sample_rate, sample_channels, sample_bits); show_dialog_message(msg); if (setup_snd(NULL)) { goto fail2; } bsize = setup.buf.block.frag_size; samples = find_tag(file, "data"); sample_buffer = malloc(bsize); if (!sample_buffer) { goto fail3; } FD_ZERO(&rfds); FD_ZERO(&wfds); bytes_read = 1; while (total_written < samples && bytes_read > 0 ) { bps_event_t *event = NULL; while (BPS_SUCCESS == bps_get_event(&event, 0) && event) { /* * If it is a NAVIGATOR_EXIT event then we are done so stop * processing events, clean up and exit */ if (bps_event_get_domain(event) == navigator_get_domain()) { if (NAVIGATOR_EXIT == bps_event_get_code(event)) { exit_application = 1; goto success; } } if (bps_event_get_domain(event) == audiodevice_get_domain()) { /* * If it is a audio device event then it means a new audio device * has been enabled and a switch is required. We close the old, * open the new audio device using the path and get the card number so * that we can close and re-open the mixer with the new card * number. */ const char * audiodevice_path = audiodevice_event_get_path(event); if (NULL == audiodevice_path) { snprintf(msg, MSG_SIZE, "audiodevice_event_get_path failed: %s\n", snd_strerror(rtn)); show_dialog_message(msg); goto fail5; } if ((rtn = snd_mixer_close(mixer_handle)) < 0) { snprintf(msg, MSG_SIZE, "snd_mixer_close failed: %s\n", snd_strerror(rtn)); show_dialog_message(msg); goto fail4; } if ((rtn = snd_pcm_close(pcm_handle)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_close failed: %s\n", snd_strerror(rtn)); show_dialog_message(msg); goto fail3; } if (setup_snd(audiodevice_path)) { /* * setup_snd() closes pcm and mixer handles in the case of error so we * skip clean up of the handles in the case of failure. */ goto fail3; } } } 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 fail5; } 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 (written < bytes_read) { memset(&status, 0, sizeof(status)); status.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_status(pcm_handle, &status) < 0) { show_dialog_message("underrun: playback channel status error\n"); goto fail5; } 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) { show_dialog_message("underrun: playback channel prepare error\n"); goto fail5; } } if (written < 0) written = 0; written += snd_pcm_plugin_write(pcm_handle, sample_buffer + written, bytes_read - written); } total_written += written; } } success: bytes_read = snd_pcm_plugin_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK); final_return_code = 0; /* * there are return codes to these close calls, but we would do the same * thing regardless of error or success so we do not check the return codes. */ fail5: snd_mixer_close(mixer_handle); fail4: snd_pcm_close(pcm_handle); fail3: free(sample_buffer); sample_buffer = NULL; fail2: fclose(file); fail1: while (!exit_application) { /* * Something went wrong so there is probably an error message and * we don't want to exit right away because we want the user to see * the message in the dialog. * * Using a negative timeout (-1) in the call to bps_get_event(...) * ensures that we don't busy wait by blocking until an event is * available. */ bps_event_t *event = NULL; bps_get_event(&event, -1); if (event) { /* * If it is a NAVIGATOR_EXIT event then we are done so stop * processing events, clean up and exit */ if (bps_event_get_domain(event) == navigator_get_domain()) { if (NAVIGATOR_EXIT == bps_event_get_code(event)) { exit_application = 1; } } } } /* * Destroy the dialog, if it exists and cleanup screen resources. */ destroy_dialog(); cleanup_screen(); bps_shutdown(); return final_return_code; }
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; }
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 gboolean alsa_open (void *dp) { alsa_driver * const d = dp; int mf; snd_pcm_format_t pf; snd_pcm_capture_info_t pcm_info; snd_pcm_capture_params_t pp; snd_pcm_capture_status_t pbstat; // int err = snd_pcm_open(&(d->soundfd), d->card_number, d->device_number, // SND_PCM_OPEN_CAPTURE); int err = snd_pcm_open(&(d->soundfd), 0, 0, SND_PCM_OPEN_CAPTURE); if (err != 0) { char buf[256]; g_sprintf(buf, _("Couldn't open ALSA device for sound input (card:%d, device:%d):\n%s"), d->card_number, d->device_number, snd_strerror(err)); error_error(buf); goto out; } // --- // Set non-blocking mode. // --- snd_pcm_block_mode(d->soundfd, 1); // enable block mode d->bits = 0; mf = 0; // --- // Select audio format // --- memset(&pf, 0, sizeof(pf)); if (d->p_resolution == 16) { pf.format = SND_PCM_SFMT_S16_LE; d->bits = 16; mf = ST_MIXER_FORMAT_S16_LE; } else { pf.format = SND_PCM_SFMT_U8; d->bits = 8; mf = ST_MIXER_FORMAT_S8; } /* if(d->p_channels == 2) { */ /* d->stereo = 1; */ /* pf.channels = d->p_channels; */ /* mf |= ST_MIXER_FORMAT_STEREO; */ /* } */ /* else { */ /* pf.channels = d->p_channels; */ /* d->stereo = 0; */ /* } */ d->stereo = 0; pf.channels = 1; pf.rate = d->p_mixfreq; d->playrate = d->p_mixfreq; mf = ST_MIXER_FORMAT_S16_LE; d->mf = mf; err = snd_pcm_capture_format(d->soundfd, &pf); if (err < 0) { error_error(_("Required sound output format not supported.\n")); goto out; } snd_pcm_capture_info(d->soundfd, &pcm_info); memset(&pp, 0, sizeof(pp)); pp.fragment_size = d->p_fragsize * pf.channels * d->bits / 8; pp.fragments_min = 1; err = snd_pcm_capture_params(d->soundfd, &pp); if (err < 0) { error_error(_("Required sound output parameters not supported.\n")); goto out; } snd_pcm_capture_status(d->soundfd, &pbstat); /* d->numfrags = pbstat.fragments; */ d->numfrags = 1; d->fragsize = pbstat.fragment_size; d->sndbuf = calloc(1, d->fragsize); if(d->stereo == 1) { d->fragsize /= 2; } if(d->bits == 16) { d->fragsize /= 2; } d->polltag = gdk_input_add(snd_pcm_file_descriptor(d->soundfd), GDK_INPUT_READ, alsa_poll_ready_sampling, d); // d->firstpoll = TRUE; // d->playtime = 0; return TRUE; out: alsa_release(dp); return FALSE; }
static gboolean alsa_open (void *dp) { alsa_driver * const d = dp; int mf; snd_pcm_format_t pf; snd_pcm_playback_info_t pcm_info; snd_pcm_playback_params_t pp; snd_pcm_playback_status_t pbstat; int err = snd_pcm_open(&(d->soundfd), d->card_number, d->device_number, SND_PCM_OPEN_PLAYBACK); if (err != 0) { char buf[256]; g_sprintf(buf, _("Couldn't open ALSA device for sound output (card:%d, device:%d):\n%s"), d->card_number, d->device_number, snd_strerror(err)); error_error(buf); goto out; } // --- // Set non-blocking mode. // --- snd_pcm_block_mode(d->soundfd, 0); // enable block mode d->outtime = 0; d->bits = 0; mf = 0; // --- // Select audio format // --- memset(&pf, 0, sizeof(pf)); if (d->p_resolution == 16) { pf.format = SND_PCM_SFMT_S16_LE; d->bits = 16; mf = ST_MIXER_FORMAT_S16_LE; } else { pf.format = SND_PCM_SFMT_U8; d->bits = 8; mf = ST_MIXER_FORMAT_S8; } if(d->p_channels == 2) { d->stereo = 1; pf.channels = d->p_channels; mf |= ST_MIXER_FORMAT_STEREO; } else { pf.channels = d->p_channels; d->stereo = 0; } pf.rate = d->p_mixfreq; d->playrate = d->p_mixfreq; d->mf = mf; err = snd_pcm_playback_format(d->soundfd, &pf); if (err < 0) { error_error(_("Required sound output format not supported.\n")); goto out; } snd_pcm_playback_info(d->soundfd, &pcm_info); memset(&pp, 0, sizeof(pp)); pp.fragment_size = d->p_fragsize * pf.channels * (d->bits / 8); pp.fragments_max = 1; // pp.fragments_max = 16pcm_info.buffer_size / pp.fragment_size; pp.fragments_room = 1; err = snd_pcm_playback_params(d->soundfd, &pp); if (err < 0) { error_error(_("Required sound output parameters not supported.\n")); goto out; } snd_pcm_playback_status(d->soundfd, &pbstat); // d->numfrags = pbstat.fragments; // d->numfrags = 1; d->fragsize = pbstat.fragment_size; d->numfrags = 1; /* fprintf(stderr, "Numfrags: %d\n", d->numfrags); fprintf(stderr, "Fragsize: %d\n", d->fragsize); */ d->sndbuf = calloc(1, d->fragsize); if(d->stereo == 1) { d->fragsize /= 2; } if(d->bits == 16) { d->fragsize /= 2; } d->polltag = audio_poll_add(snd_pcm_file_descriptor(d->soundfd), GDK_INPUT_WRITE, alsa_poll_ready_playing, d); /* d->firstpoll = TRUE; */ d->firstpoll = TRUE; d->playtime = 0; return TRUE; out: alsa_release(dp); return FALSE; }
// 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; }