/***************************************************************************** * GetBufInfo: buffer status query ***************************************************************************** * This function returns the number of used byte in the queue. * It also deals with errors : indeed if the device comes to run out * of data to play, it switches to the "underrun" status. It has to * be flushed and re-prepared *****************************************************************************/ static int GetBufInfo( aout_instance_t *p_aout ) { int i_ret; snd_pcm_channel_status_t status; /* get current pcm status */ memset( &status, 0, sizeof(status) ); if( ( i_ret = snd_pcm_plugin_status( p_aout->output.p_sys->p_pcm_handle, &status ) ) < 0 ) { msg_Err( p_aout, "unable to get device status (%s)", snd_strerror( i_ret ) ); return( -1 ); } /* check for underrun */ switch( status.status ) { case SND_PCM_STATUS_READY: case SND_PCM_STATUS_UNDERRUN: 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 ) ); } break; } return( status.count ); }
static ALCuint qsa_available_samples(ALCdevice* device) { qsa_data* data=(qsa_data*)device->ExtraData; snd_pcm_channel_status_t status; ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); ALint free_size; int rstatus; memset(&status, 0, sizeof (status)); status.channel=SND_PCM_CHANNEL_CAPTURE; snd_pcm_plugin_status(data->pcmHandle, &status); if ((status.status==SND_PCM_STATUS_OVERRUN) || (status.status==SND_PCM_STATUS_READY)) { if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) { ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); aluHandleDisconnect(device); return 0; } snd_pcm_capture_go(data->pcmHandle); return 0; } free_size=data->csetup.buf.block.frag_size*data->csetup.buf.block.frags; free_size-=status.free; return free_size/frame_size; }
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; }
/** * Set up capture based on the audio sample waverec except we use VoIP parameters */ static int capture(circular_buffer_t* circular_buffer) { // Re-usable buffer for capture char *record_buffer; record_buffer = (char*) malloc(g_frame_size_c); // Some diagnostic variables int failed = 0; int totalRead = 0; snd_pcm_channel_status_t status; status.channel = SND_PCM_CHANNEL_CAPTURE; // Loop until stopAudio() flags us while (g_execute_audio) { // This blocking read appears to take much longer than 20ms on the simulator // but it never fails and always returns 160 bytes int read = snd_pcm_plugin_read(g_pcm_handle_c, record_buffer, g_frame_size_c); if (read < 0 || read != g_frame_size_c) { failed++; fprintf(stderr,"CAPTURE FAILURE: snd_pcm_plugin_read: %d requested = %d\n",read,g_frame_size_c); if (snd_pcm_plugin_status(g_pcm_handle_c, &status) < 0) { fprintf(stderr, "Capture channel status error: %d\n",status.status); } else { if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_OVERRUN || status.status == SND_PCM_STATUS_CHANGE || status.status == SND_PCM_STATUS_ERROR) { fprintf(stderr, "CAPTURE FAILURE:snd_pcm_plugin_status: = %d \n",status.status); if (snd_pcm_plugin_prepare (g_pcm_handle_c, SND_PCM_CHANNEL_CAPTURE) < 0) { fprintf (stderr, "Capture channel prepare error 1 %d\n",status.status); exit (1); } } } } else { totalRead += read; // On simulator always room in the circular buffer if (!writeToCircularBuffer(circular_buffer, record_buffer, g_frame_size_c)) { failed++; } } capture_ready = true; } fprintf(stderr,"CAPTURE EXIT BEGIN\n"); (void) snd_pcm_plugin_flush(g_pcm_handle_c, SND_PCM_CHANNEL_CAPTURE); //(void)snd_mixer_close (mixer_handle); (void) snd_pcm_close(g_pcm_handle_c); audio_manager_free_handle(g_audio_manager_handle_c); // IMPORTANT NB: You only get failed on capture if the play loop has exited hence the circular buffer fills. This is with the simulator fprintf(stderr, "CAPTURE EXIT Total Bytes read = %d failed = %d\n",totalRead,failed); free(record_buffer); return 0; }
static int prepare_driver(void) { int rc; rc = snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK); if (rc < 0) { printf("Unable to prepare plugin: %s\n", snd_strerror(rc)); return rc; } return 0; }
qint64 QnxAudioInput::read(char *data, qint64 len) { int errorCode = 0; QByteArray tempBuffer(m_periodSize, 0); const int actualRead = snd_pcm_plugin_read(m_pcmHandle, tempBuffer.data(), m_periodSize); if (actualRead < 1) { snd_pcm_channel_status_t status; memset(&status, 0, sizeof(status)); status.channel = SND_PCM_CHANNEL_CAPTURE; if ((errorCode = snd_pcm_plugin_status(m_pcmHandle, &status)) < 0) { qWarning("QnxAudioInput: read error, couldn't get plugin status (0x%x)", -errorCode); close(); setError(QAudio::FatalError); setState(QAudio::StoppedState); return -1; } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_OVERRUN) { if ((errorCode = snd_pcm_plugin_prepare(m_pcmHandle, SND_PCM_CHANNEL_CAPTURE)) < 0) { qWarning("QnxAudioInput: read error, couldn't prepare plugin (0x%x)", -errorCode); close(); setError(QAudio::FatalError); setState(QAudio::StoppedState); return -1; } } } else { setError(QAudio::NoError); setState(QAudio::ActiveState); } if (m_volume < 1.0f) QAudioHelperInternal::qMultiplySamples(m_volume, m_format, tempBuffer.data(), tempBuffer.data(), actualRead); m_bytesRead += actualRead; if (m_pullMode) { m_audioSource->write(tempBuffer.data(), actualRead); } else { memcpy(data, tempBuffer.data(), qMin(static_cast<qint64>(actualRead), len)); } m_bytesAvailable = 0; return actualRead; }
static void resetPlay() { snd_pcm_channel_status_t status; status.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_status(g_pcm_handle_p, &status) < 0) { fprintf(stderr, "FATAL Playback channel status error %d\n", status.status); exit (1); } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_UNDERRUN || status.status == SND_PCM_STATUS_CHANGE || status.status == SND_PCM_STATUS_ERROR) { fprintf(stderr, "PLAYBACK FAILURE:snd_pcm_plugin_status: = %d \n",status.status); if (snd_pcm_plugin_prepare (g_pcm_handle_p, SND_PCM_CHANNEL_PLAYBACK) < 0) { fprintf (stderr, "FATAL Playback channel prepare error %d\n", status.status); exit (1); } } }
static int write_qsa(audio_output_t* ao, unsigned char* buf, int bytes) { int written; int status; snd_pcm_channel_status_t cstatus; qsa_internal_t* userptr; userptr=ao->userptr; if (userptr!=NULL); { written=snd_pcm_plugin_write(userptr->audio_handle, buf, bytes); if (written!=bytes) { /* Check if samples playback got stuck somewhere in hardware or in */ /* the audio device driver */ if ((errno==EAGAIN) && (written==0)) { return 0; } if ((errno==EINVAL) || (errno==EIO)) { memset(&cstatus, 0, sizeof(cstatus)); cstatus.channel=SND_PCM_CHANNEL_PLAYBACK; status=snd_pcm_plugin_status(userptr->audio_handle, &cstatus); if (status>0) { return 0; } if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY)) { status=snd_pcm_plugin_prepare(userptr->audio_handle, SND_PCM_CHANNEL_PLAYBACK); if (status<0) { return 0; } } } } } return written; }
static void qsa_start_capture(ALCdevice* device) { qsa_data* data=(qsa_data*)device->ExtraData; int rstatus; if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) { ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); return; } memset(&data->csetup, 0, sizeof(data->csetup)); data->csetup.channel=SND_PCM_CHANNEL_CAPTURE; if ((rstatus=snd_pcm_plugin_setup(data->pcmHandle, &data->csetup))<0) { ERR("capture setup failed: %s\n", snd_strerror(rstatus)); return; } snd_pcm_capture_go(data->pcmHandle); }
/* SNDDMA_Submit Send sound to device if buffer isn't really the dma buffer */ void SNDDMA_Submit (void) { int count = paintedtime - soundtime; int i, s, e; int rc; count += setup.buf.block.frag_size - 1; count /= setup.buf.block.frag_size; s = soundtime / setup.buf.block.frag_size; e = s + count; for (i = s; i < e; i++) mmap_control->fragments[i % setup.buf.block.frags].data = 1; switch (mmap_control->status.status) { case SND_PCM_STATUS_PREPARED: if ((rc = snd_pcm_channel_go (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { fprintf (stderr, "unable to start playback. %s\n", snd_strerror (rc)); exit (1); } break; case SND_PCM_STATUS_RUNNING: break; case SND_PCM_STATUS_UNDERRUN: if ( (rc = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { fprintf (stderr, "underrun: playback channel prepare error. %s\n", snd_strerror (rc)); exit (1); } break; default: break; } }
static int ca_thread_func (void *arg) { struct bb10_stream* stream = (struct bb10_stream *) arg; int size = stream->ca_buf_size; unsigned long nframes = stream->ca_frames; void *user_data = stream->user_data; /* Buffer to fill for PJMEDIA */ char *buf = stream->ca_buf; pj_timestamp tstamp; int result; int policy; struct sched_param param; TRACE_((THIS_FILE, "ca_thread_func: size = %d ", size)); if (pthread_getschedparam(pthread_self(), &policy, ¶m) == 0) { param.sched_priority = 18; pthread_setschedparam (pthread_self(), policy, ¶m); } pj_bzero (buf, size); tstamp.u64 = 0; /* Final init now the thread has started */ if ((result = snd_pcm_plugin_prepare (stream->ca_pcm, SND_PCM_CHANNEL_CAPTURE)) < 0) { TRACE_((THIS_FILE, "ca_thread_func failed prepare = %d", result)); return PJ_SUCCESS; } while (!stream->quit) { pjmedia_frame frame; //pj_bzero (buf, size); /* read the input device */ result = snd_pcm_plugin_read(stream->ca_pcm, buf,size); if(result <0 || result != size) { /* We expect result to be size (640) * It's not so we have to read the status error and "prepare" * the channel. This usually happens when output audio routing * has been changed by another thread. * We won't "continue", instead just do what we can and leave * the end of the loop to write what's in the buffer. Not entirely * correct but saves a potential underrun in PJMEDIA */ PJ_LOG (4,(THIS_FILE, "snd_pcm_plugin_read ERROR read = %d required = %d", result,size)); snd_pcm_channel_status_t status; status.channel = SND_PCM_CHANNEL_CAPTURE; if ((result = snd_pcm_plugin_status (stream->ca_pcm, &status)) < 0) { /* Should not fail but all we can do is continue */ PJ_LOG(4,(THIS_FILE, "capture: snd_pcm_plugin_status ret = %d", result)); } else { /* RIM say these are the errors that we should "prepare" * after */ if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_OVERRUN || status.status == SND_PCM_STATUS_ERROR) { if (snd_pcm_plugin_prepare (stream->ca_pcm, SND_PCM_CHANNEL_CAPTURE) < 0) { PJ_LOG (4,(THIS_FILE, "overrun: capture channel prepare error")); } } } } if (stream->quit) break; /* Write the capture audio data to PJMEDIA */ frame.type = PJMEDIA_FRAME_TYPE_AUDIO; frame.buf = (void *) buf; frame.size = size; frame.timestamp.u64 = tstamp.u64; frame.bit_info = 0; result = stream->ca_cb (user_data, &frame); if (result != PJ_SUCCESS || stream->quit) break; tstamp.u64 += nframes; } flush_capture(stream); TRACE_((THIS_FILE, "ca_thread_func: Stopped")); return PJ_SUCCESS; }
/** * Play audio received from PJMEDIA */ static int pb_thread_func (void *arg) { struct bb10_stream* stream = (struct bb10_stream *) arg; int size = stream->pb_buf_size; unsigned long nframes = stream->pb_frames; void *user_data = stream->user_data; char *buf = stream->pb_buf; pj_timestamp tstamp; int result = 0; int policy; struct sched_param param; TRACE_((THIS_FILE, "pb_thread_func: size = %d ", size)); if (pthread_getschedparam(pthread_self(), &policy, ¶m) == 0) { param.sched_priority = 18; pthread_setschedparam (pthread_self(), policy, ¶m); } pj_bzero (buf, size); tstamp.u64 = 0; /* Do the final initialization now the thread has started. */ if ((result = snd_pcm_plugin_prepare(stream->pb_pcm, SND_PCM_CHANNEL_PLAYBACK)) < 0) { TRACE_((THIS_FILE, "pb_thread_func failed prepare = %d", result)); return PJ_SUCCESS; } while (!stream->quit) { pjmedia_frame frame; frame.type = PJMEDIA_FRAME_TYPE_AUDIO; /* pointer to buffer filled by PJMEDIA */ frame.buf = buf; frame.size = size; frame.timestamp.u64 = tstamp.u64; frame.bit_info = 0; /* Read the audio from pjmedia */ result = stream->pb_cb (user_data, &frame); if (result != PJ_SUCCESS || stream->quit) break; if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO) pj_bzero (buf, size); /* Write 640 to play unit */ result = snd_pcm_plugin_write(stream->pb_pcm,buf,size); if (result != size || result < 0) { /* either the write to output device has failed or not the * full amount of bytes have been written. This usually happens * when audio routing is being changed by another thread * Use a status variable for reading the error */ snd_pcm_channel_status_t status; status.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_status (stream->pb_pcm, &status) < 0) { /* Call has failed nothing we can do except log and * continue */ PJ_LOG(4,(THIS_FILE, "underrun: playback channel status error")); } else { /* The status of the error has been read * RIM say these are expected so we can "re-prepare" the stream */ PJ_LOG(4,(THIS_FILE,"PLAY thread ERROR status = %d", status.status)); if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_UNDERRUN || status.status == SND_PCM_STATUS_ERROR ) { if (snd_pcm_plugin_prepare (stream->pb_pcm, SND_PCM_CHANNEL_PLAYBACK) < 0) { PJ_LOG(4,(THIS_FILE, "underrun: playback channel prepare error")); } } } } tstamp.u64 += nframes; } flush_play(stream); TRACE_((THIS_FILE, "pb_thread_func: Stopped")); return PJ_SUCCESS; }
/** * Play audio received from PJMEDIA */ static int pb_thread_func (void *arg) { struct bb10_stream* stream = (struct bb10_stream *) arg; /* Handle from bb10_open_playback */ /* Will be 640 */ int size = stream->pb_buf_size; /* 160 frames for 20ms */ unsigned long nframes = stream->pb_frames; void *user_data = stream->user_data; char *buf = stream->pb_buf; pj_timestamp tstamp; int result = 0; pj_bzero (buf, size); tstamp.u64 = 0; TRACE_((THIS_FILE, "pb_thread_func: size = %d ", size)); /* Do the final initialization now the thread has started. */ if ((result = snd_pcm_plugin_prepare(stream->pb_pcm, SND_PCM_CHANNEL_PLAYBACK)) < 0) { close_play_pcm(stream); TRACE_((THIS_FILE, "pb_thread_func failed prepare = %d", result)); return PJ_SUCCESS; } while (!stream->quit) { pjmedia_frame frame; frame.type = PJMEDIA_FRAME_TYPE_AUDIO; /* pointer to buffer filled by PJMEDIA */ frame.buf = buf; frame.size = size; frame.timestamp.u64 = tstamp.u64; frame.bit_info = 0; result = stream->pb_cb (user_data, &frame); if (result != PJ_SUCCESS || stream->quit) break; if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO) pj_bzero (buf, size); /* Write 640 to play unit */ result = snd_pcm_plugin_write(stream->pb_pcm,buf,size); if (result != size || result < 0) { snd_pcm_channel_status_t status; if (snd_pcm_plugin_status (stream->pb_pcm, &status) < 0) { PJ_LOG(4,(THIS_FILE, "underrun: playback channel status error")); continue; } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_UNDERRUN) { if (snd_pcm_plugin_prepare (stream->pb_pcm, SND_PCM_CHANNEL_PLAYBACK) < 0) { PJ_LOG(4,(THIS_FILE, "underrun: playback channel prepare error")); continue; } } TRACE_((THIS_FILE, "pb_thread_func failed write = %d", result)); } tstamp.u64 += nframes; } flush_play(stream); close_play_pcm(stream); TRACE_((THIS_FILE, "pb_thread_func: Stopped")); 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 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)); } }
FORCE_ALIGN static int qsa_proc_playback(void* ptr) { ALCdevice* device=(ALCdevice*)ptr; qsa_data* data=(qsa_data*)device->ExtraData; char* write_ptr; int avail; snd_pcm_channel_status_t status; struct sched_param param; fd_set wfds; int selectret; struct timeval timeout; SetRTPriority(); althrd_setname(althrd_current(), MIXER_THREAD_NAME); /* Increase default 10 priority to 11 to avoid jerky sound */ SchedGet(0, 0, ¶m); param.sched_priority=param.sched_curpriority+1; SchedSet(0, 0, SCHED_NOCHANGE, ¶m); ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); while (!data->killNow) { ALint len=data->size; write_ptr=data->buffer; avail=len/frame_size; aluMixData(device, write_ptr, avail); while (len>0 && !data->killNow) { FD_ZERO(&wfds); FD_SET(data->audio_fd, &wfds); timeout.tv_sec=2; timeout.tv_usec=0; /* Select also works like time slice to OS */ selectret=select(data->audio_fd+1, NULL, &wfds, NULL, &timeout); switch (selectret) { case -1: aluHandleDisconnect(device); return 1; case 0: break; default: if (FD_ISSET(data->audio_fd, &wfds)) { break; } break; } int wrote=snd_pcm_plugin_write(data->pcmHandle, write_ptr, len); if (wrote<=0) { if ((errno==EAGAIN) || (errno==EWOULDBLOCK)) { continue; } memset(&status, 0, sizeof (status)); status.channel=SND_PCM_CHANNEL_PLAYBACK; snd_pcm_plugin_status(data->pcmHandle, &status); /* we need to reinitialize the sound channel if we've underrun the buffer */ if ((status.status==SND_PCM_STATUS_UNDERRUN) || (status.status==SND_PCM_STATUS_READY)) { if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0) { aluHandleDisconnect(device); break; } } } else { write_ptr+=wrote; len-=wrote; } } } return 0; }
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; }
/***************************************************************************** * 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 ); }
int main (int argc, char **argv) { int card = -1; int dev = 0; snd_pcm_t *pcm_handle; FILE *file; wave_hdr wav_header; int samples; int sample_rate; int sample_channels; int sample_bits; char *sample_buffer; int fragsize = -1; int verbose = 0; int rtn; int final_return_code = -1; snd_pcm_channel_info_t pi; snd_mixer_t *mixer_handle; snd_mixer_group_t group; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; int bsize, bytes_read, total_written = 0; fd_set rfds, wfds; uint32_t voice_mask[] = { 0, 0, 0, 0 }; snd_pcm_voice_conversion_t voice_conversion; int voice_override = 0; int num_frags = -1; char input_file[PATH_MAX]; char cwd[PATH_MAX]; screen_context_t screen_cxt; screen_window_t screen_win; screen_buffer_t screen_buf; int screen_fill_attribs[] = { SCREEN_BLIT_COLOR, COLOR_PURPLE, SCREEN_BLIT_END }; int screen_dirty[4] = { 0, 0, 1024, 600 }; //start with sane default values int idle_mode = SCREEN_IDLE_MODE_KEEP_AWAKE; int usage = SCREEN_USAGE_NATIVE; if (screen_create_context(&screen_cxt, 0) != 0) { return err("failed to create context"); } if (screen_create_window(&screen_win, screen_cxt) != 0) { err("failed to create window"); goto fail1; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage) != 0) { err("failed to set native usage mode"); goto fail2; } if (screen_create_window_buffers(screen_win, 1) != 0) { err("failed to set native usage mode"); goto fail2; } if(screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf) != 0) { err("failed to get screen buffer"); goto fail2; } if (screen_fill(screen_cxt, screen_buf, screen_fill_attribs) != 0) { err("failed to fill the screen"); goto fail3; } if (screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, screen_dirty+2) != 0) { err("failed to get window size"); goto fail3; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_IDLE_MODE, &idle_mode) != 0) { err("failed to set idle mode"); goto fail3; } if (screen_post_window(screen_win, screen_buf, 1, screen_dirty, 0) != 0) { err("failed to post the window"); goto fail3; } if ((rtn = snd_pcm_open_preferred (&pcm_handle, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0) { err ("device open"); goto fail3; } getcwd(cwd, PATH_MAX); rtn = snprintf(input_file, PATH_MAX, "%s%s", cwd, WAV_RELATIVE_PATH); if (rtn > PATH_MAX - 1) { err ("File name and path too long"); goto fail4; } if ((file = fopen (input_file, "r")) == 0) { err ("File open failed"); goto fail4; } if (check_hdr (file) == -1) { err ("check_hdr failed"); goto fail5; } samples = find_tag (file, "fmt "); fread (&wav_header, sizeof (wav_header), 1, file); fseek (file, (samples - sizeof (wave_hdr)), SEEK_CUR); sample_rate = ENDIAN_LE32 (wav_header.samples_per_sec); sample_channels = ENDIAN_LE16 (wav_header.channels); sample_bits = ENDIAN_LE16 (wav_header.bits_per_sample); printf ("SampleRate = %d, channels = %d, SampleBits = %d\n", sample_rate, sample_channels, sample_bits); /* disabling mmap is not actually required in this example but it is included to * demonstrate how it is used when it is required. */ if ((rtn = snd_pcm_plugin_set_disable (pcm_handle, PLUGIN_DISABLE_MMAP)) < 0) { fprintf (stderr, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror (rtn)); goto fail5; } memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_info (pcm_handle, &pi)) < 0) { fprintf (stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror (rtn)); goto fail5; } memset (&pp, 0, sizeof (pp)); pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_PLAYBACK; pp.start_mode = SND_PCM_START_FULL; pp.stop_mode = SND_PCM_STOP_STOP; pp.buf.block.frag_size = pi.max_fragment_size; if (fragsize != -1) { pp.buf.block.frag_size = fragsize; } pp.buf.block.frags_max = num_frags; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = sample_rate; pp.format.voices = sample_channels; if (ENDIAN_LE16 (wav_header.format_tag) == 6) pp.format.format = SND_PCM_SFMT_A_LAW; else if (ENDIAN_LE16 (wav_header.format_tag) == 7) pp.format.format = SND_PCM_SFMT_MU_LAW; else if (sample_bits == 8) pp.format.format = SND_PCM_SFMT_U8; else if (sample_bits == 24) pp.format.format = SND_PCM_SFMT_S24; else pp.format.format = SND_PCM_SFMT_S16_LE; strcpy (pp.sw_mixer_subchn_name, "Wave playback channel"); if ((rtn = snd_pcm_plugin_params (pcm_handle, &pp)) < 0) { fprintf (stderr, "snd_pcm_plugin_params failed: %s\n", snd_strerror (rtn)); goto fail5; } if ((rtn = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { fprintf (stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rtn)); goto fail5; } if (voice_override) { snd_pcm_plugin_get_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &voice_conversion); voice_conversion.matrix[0] = voice_mask[0]; voice_conversion.matrix[1] = voice_mask[1]; voice_conversion.matrix[2] = voice_mask[2]; voice_conversion.matrix[3] = voice_mask[3]; snd_pcm_plugin_set_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &voice_conversion); } memset (&setup, 0, sizeof (setup)); memset (&group, 0, sizeof (group)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; setup.mixer_gid = &group.gid; if ((rtn = snd_pcm_plugin_setup (pcm_handle, &setup)) < 0) { fprintf (stderr, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (rtn)); goto fail5; } printf ("Format %s \n", snd_pcm_get_format_name (setup.format.format)); printf ("Frag Size %d \n", setup.buf.block.frag_size); printf ("Total Frags %d \n", setup.buf.block.frags); printf ("Rate %d \n", setup.format.rate); printf ("Voices %d \n", setup.format.voices); bsize = setup.buf.block.frag_size; if (group.gid.name[0] == 0) { fprintf (stderr, "Mixer Pcm Group [%s] Not Set \n", group.gid.name); goto fail5; } printf ("Mixer Pcm Group [%s]\n", group.gid.name); if ((rtn = snd_mixer_open (&mixer_handle, card, setup.mixer_device)) < 0) { fprintf (stderr, "snd_mixer_open failed: %s\n", snd_strerror (rtn)); goto fail5; } samples = find_tag (file, "data"); sample_buffer = malloc (bsize); FD_ZERO (&rfds); FD_ZERO (&wfds); bytes_read = 1; while (total_written < samples && bytes_read > 0) { if (tcgetpgrp (0) == getpid ()) FD_SET (STDIN_FILENO, &rfds); FD_SET (snd_mixer_file_descriptor (mixer_handle), &rfds); FD_SET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds); rtn = max (snd_mixer_file_descriptor (mixer_handle), snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)); if (select (rtn + 1, &rfds, &wfds, NULL, NULL) == -1) { err ("select"); goto fail6; } if (FD_ISSET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds)) { snd_pcm_channel_status_t status; int written = 0; if ((bytes_read = fread (sample_buffer, 1, min (samples - total_written, bsize), file)) <= 0) continue; written = snd_pcm_plugin_write (pcm_handle, sample_buffer, bytes_read); if (verbose) printf ("bytes written = %d \n", written); if (written < bytes_read) { memset (&status, 0, sizeof (status)); status.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_status (pcm_handle, &status) < 0) { fprintf (stderr, "underrun: playback channel status error\n"); goto fail6; } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_UNDERRUN) { if (snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0) { fprintf (stderr, "underrun: playback channel prepare error\n"); goto fail6; } } if (written < 0) written = 0; written += snd_pcm_plugin_write (pcm_handle, sample_buffer + written, bytes_read - written); } total_written += written; } } bytes_read = snd_pcm_plugin_flush (pcm_handle, SND_PCM_CHANNEL_PLAYBACK); final_return_code = 0; fail6: rtn = snd_mixer_close (mixer_handle); fail5: fclose (file); fail4: rtn = snd_pcm_close (pcm_handle); fail3: screen_destroy_buffer(screen_buf); fail2: screen_destroy_window(screen_win); fail1: screen_destroy_context(screen_cxt); return final_return_code; }
static void NTO_PlayAudio(_THIS) { int written, rval; int towrite; #ifdef DEBUG_AUDIO fprintf(stderr, "NTO_PlayAudio\n"); #endif if( !this->enabled) return; towrite = pcm_len; /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ do { written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite); #ifdef DEBUG_AUDIO fprintf(stderr, "NTO_PlayAudio: written = %d towrite = %d\n",written,towrite); #endif if (written != towrite) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { SDL_Delay(1); /* Let a little CPU time go by and try to write again */ #ifdef DEBUG_AUDIO fprintf(stderr, "errno == EAGAIN written %d\n", written); towrite -= written; //we wrote some data #endif continue; } else if((errno == EINVAL) || (errno == EIO)) { #ifdef DEBUG_AUDIO if(errno == EIO) fprintf(stderr,"snd_pcm_plugin_write failed EIO: %s\n", snd_strerror(written)); if(errno == EINVAL) fprintf(stderr,"snd_pcm_plugin_write failed EINVAL: %s\n", snd_strerror(written)); #endif memset(&cstatus, 0, sizeof(cstatus)); if( (rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0 ) { #ifdef DEBUG_AUDIO fprintf(stderr, "snd_pcm_plugin_status failed %s\n",snd_strerror(rval)); #endif SDL_SetError("snd_pcm_plugin_status failed: %s\n", snd_strerror(rval)); return; } if ( (cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY) ) { #ifdef DEBUG_AUDIO fprintf(stderr, "buffer underrun\n"); #endif if ( (rval = snd_pcm_plugin_prepare (audio_handle,SND_PCM_CHANNEL_PLAYBACK)) < 0 ) { #ifdef DEBUG_AUDIO fprintf(stderr, "NTO_PlayAudio: prepare failed %s\n",snd_strerror(rval)); #endif SDL_SetError("snd_pcm_plugin_prepare failed: %s\n",snd_strerror(rval) ); return; } } continue; } else { #ifdef DEBUG_AUDIO fprintf(stderr, "NTO_PlayAudio: snd_pcm_plugin_write failed unknown errno %d %s\n",errno, snd_strerror(rval)); #endif return; } } else { towrite -= written; //we wrote all remaining data } } while ( (towrite > 0) && (this->enabled) ); /* If we couldn't write, assume fatal error for now */ if ( towrite != 0 ) { this->enabled = 0; } return; }
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; }
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 int ca_thread_func (void *arg) { struct bb10_stream* stream = (struct bb10_stream *) arg; int size = stream->ca_buf_size; unsigned long nframes = stream->ca_frames; void *user_data = stream->user_data; /* Buffer to fill for PJMEDIA */ char *buf = stream->ca_buf; pj_timestamp tstamp; int result; struct sched_param param; pthread_t *thid; TRACE_((THIS_FILE, "ca_thread_func: size = %d ", size)); thid = (pthread_t*) pj_thread_get_os_handle (pj_thread_this()); param.sched_priority = sched_get_priority_max (SCHED_RR); result = pthread_setschedparam (*thid, SCHED_RR, ¶m); if (result) { if (result == EPERM) { PJ_LOG (4,(THIS_FILE, "Unable to increase thread priority, " "root access needed.")); } else { PJ_LOG (4,(THIS_FILE, "Unable to increase thread priority, " "error: %d", result)); } } pj_bzero (buf, size); tstamp.u64 = 0; /* Final init now the thread has started */ if ((result = snd_pcm_plugin_prepare (stream->ca_pcm, SND_PCM_CHANNEL_CAPTURE)) < 0) { close_capture_pcm(stream); TRACE_((THIS_FILE, "ca_thread_func failed prepare = %d", result)); return PJ_SUCCESS; } while (!stream->quit) { pjmedia_frame frame; pj_bzero (buf, size); result = snd_pcm_plugin_read(stream->ca_pcm, buf,size); if(result <0 || result != size) { snd_pcm_channel_status_t status; if (snd_pcm_plugin_status (stream->ca_pcm, &status) < 0) { PJ_LOG (4,(THIS_FILE, "overrun: capture channel status " "error")); continue; } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_OVERRUN) { if (snd_pcm_plugin_prepare (stream->ca_pcm, SND_PCM_CHANNEL_CAPTURE) < 0) { PJ_LOG (4,(THIS_FILE, "overrun: capture channel prepare " "error")); continue; } } } if (stream->quit) break; frame.type = PJMEDIA_FRAME_TYPE_AUDIO; frame.buf = (void *) buf; frame.size = size; frame.timestamp.u64 = tstamp.u64; frame.bit_info = 0; result = stream->ca_cb (user_data, &frame); if (result != PJ_SUCCESS || stream->quit) break; tstamp.u64 += nframes; } flush_capture(stream); close_capture_pcm(stream); TRACE_((THIS_FILE, "ca_thread_func: Stopped")); return PJ_SUCCESS; }
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; }
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 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); }
static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) { qsa_data* data=(qsa_data*)device->ExtraData; char* read_ptr; snd_pcm_channel_status_t status; fd_set rfds; int selectret; struct timeval timeout; int bytes_read; ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); ALint len=samples*frame_size; int rstatus; read_ptr=buffer; while (len>0) { FD_ZERO(&rfds); FD_SET(data->audio_fd, &rfds); timeout.tv_sec=2; timeout.tv_usec=0; /* Select also works like time slice to OS */ bytes_read=0; selectret=select(data->audio_fd+1, &rfds, NULL, NULL, &timeout); switch (selectret) { case -1: aluHandleDisconnect(device); return ALC_INVALID_DEVICE; case 0: break; default: if (FD_ISSET(data->audio_fd, &rfds)) { bytes_read=snd_pcm_plugin_read(data->pcmHandle, read_ptr, len); break; } break; } if (bytes_read<=0) { if ((errno==EAGAIN) || (errno==EWOULDBLOCK)) { continue; } memset(&status, 0, sizeof (status)); status.channel=SND_PCM_CHANNEL_CAPTURE; snd_pcm_plugin_status(data->pcmHandle, &status); /* we need to reinitialize the sound channel if we've overrun the buffer */ if ((status.status==SND_PCM_STATUS_OVERRUN) || (status.status==SND_PCM_STATUS_READY)) { if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) { ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); aluHandleDisconnect(device); return ALC_INVALID_DEVICE; } snd_pcm_capture_go(data->pcmHandle); } } else { read_ptr+=bytes_read; len-=bytes_read; } } 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; }
static void QSA_PlayDevice(_THIS) { snd_pcm_channel_status_t cstatus; int written; int status; int towrite; void *pcmbuffer; if ((!this->enabled) || (!this->hidden)) { return; } towrite = this->spec.size; pcmbuffer = this->hidden->pcm_buf; /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ do { written = snd_pcm_plugin_write(this->hidden->audio_handle, pcmbuffer, towrite); if (written != towrite) { /* Check if samples playback got stuck somewhere in hardware or in */ /* the audio device driver */ if ((errno == EAGAIN) && (written == 0)) { if (this->hidden->timeout_on_wait != 0) { SDL_SetError("QSA: buffer playback timeout"); return; } } /* Check for errors or conditions */ if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* Let a little CPU time go by and try to write again */ SDL_Delay(1); /* if we wrote some data */ towrite -= written; pcmbuffer += written * this->spec.channels; continue; } else { if ((errno == EINVAL) || (errno == EIO)) { SDL_memset(&cstatus, 0, sizeof(cstatus)); if (!this->hidden->iscapture) { cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; } else { cstatus.channel = SND_PCM_CHANNEL_CAPTURE; } status = snd_pcm_plugin_status(this->hidden->audio_handle, &cstatus); if (status < 0) { QSA_SetError("snd_pcm_plugin_status", status); return; } if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY)) { if (!this->hidden->iscapture) { status = snd_pcm_plugin_prepare(this->hidden-> audio_handle, SND_PCM_CHANNEL_PLAYBACK); } else { status = snd_pcm_plugin_prepare(this->hidden-> audio_handle, SND_PCM_CHANNEL_CAPTURE); } if (status < 0) { QSA_SetError("snd_pcm_plugin_prepare", status); return; } } continue; } else { return; } } } else { /* we wrote all remaining data */ towrite -= written; pcmbuffer += written * this->spec.channels; } } while ((towrite > 0) && (this->enabled)); /* If we couldn't write, assume fatal error for now */ if (towrite != 0) { this->enabled = 0; } }