示例#1
0
/*****************************************************************************
 * 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 );
}
示例#2
0
/* This function waits until it is possible to write a full sound buffer */
static void NTO_WaitAudio(_THIS)
{
	int rval;
	int totalbytes,roomavail;
	/*we consider a full sound buffer to be of size pcm_len bytes */
	
#ifdef DEBUG_AUDIO
	fprintf(stderr,"NTO_WaitAudio\n");
#endif

	while(1)
	{
	memset(&cstatus, 0, sizeof(cstatus));
	 if( (rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0 )
    {
		 SDL_SetError("snd_pcm_plugin_status failed: %s\n", snd_strerror(rval));
   	    return;
	}	
	
	totalbytes = csetup.buf.block.frag_size *csetup.buf.block.frags;
	roomavail = totalbytes - cstatus.count;

#ifdef DEBUG_AUDIO
	fprintf(stderr,"NTO_WaitAudio roomavail %d pcm_len %d\n",roomavail,pcm_len);
#endif
	
	if ((roomavail >= pcm_len) || (roomavail < 0))
		return;
		
		SDL_Delay(10);	
	}	
      
}
示例#3
0
文件: qsa.c 项目: Sponk/NeoEditor
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;
}
示例#4
0
static int alsa_dsp_get_freespace(struct sysdep_dsp_struct *dsp)
{
	struct alsa_dsp_priv_data *priv = dsp->_priv;
	snd_pcm_channel_status_t status={0};	
 
 	snd_pcm_plugin_status(priv->audio_dev.m_AudioHandle, &status);
 
	return status.free / alsa_dsp_bytes_per_sample[dsp->hw_info.type];
}
/**
 * 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;
}
示例#6
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);
		}
	}
}
示例#8
0
文件: qsa.c 项目: Atom66/tain335
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;
}
示例#9
0
文件: bb10_dev.c 项目: KevinHM/pjsip
/**
 * 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, &param) == 0) {
	param.sched_priority = 18;
	pthread_setschedparam (pthread_self(), policy, &param);
    }

    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;
}
示例#10
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;
    }
}
示例#11
0
文件: qsa.c 项目: Sponk/NeoEditor
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;
}
示例#12
0
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;
}
示例#13
0
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, &param);
    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;
}
示例#14
0
/**
 * 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;
}
示例#15
0
void AudioDriverBB10::thread_func(void *p_udata) {

	AudioDriverBB10 *ad = (AudioDriverBB10 *)p_udata;

	int channels = speaker_mode;
	int frame_count = ad->sample_buf_count / channels;
	int bytes_out = frame_count * channels * 2;

	while (!ad->exit_thread) {

		if (!ad->active) {

			for (int i = 0; i < ad->sample_buf_count; i++) {

				ad->samples_out[i] = 0;
			};
		} else {

			ad->lock();

			ad->audio_server_process(frame_count, ad->samples_in);

			ad->unlock();

			for (int i = 0; i < frame_count * channels; i++) {

				ad->samples_out[i] = ad->samples_in[i] >> 16;
			}
		};

		int todo = bytes_out;
		int total = 0;

		while (todo) {

			uint8_t *src = (uint8_t *)ad->samples_out;
			int wrote = snd_pcm_plugin_write(ad->pcm_handle, (void *)(src + total), todo);
			if (wrote < 0) {
				// error?
				break;
			};
			total += wrote;
			todo -= wrote;
			if (wrote < todo) {
				if (ad->thread_exited) {
					break;
				};
				printf("pcm_write underrun %i, errno %i\n", (int)ad->thread_exited, errno);
				snd_pcm_channel_status_t status;
				zeromem(&status, sizeof(status));
				// put in non-blocking mode
				snd_pcm_nonblock_mode(ad->pcm_handle, 1);
				status.channel = SND_PCM_CHANNEL_PLAYBACK;
				int ret = snd_pcm_plugin_status(ad->pcm_handle, &status);
				//printf("status return %i, %i, %i, %i, %i\n", ret, errno, status.status, SND_PCM_STATUS_READY, SND_PCM_STATUS_UNDERRUN);
				snd_pcm_nonblock_mode(ad->pcm_handle, 0);
				if (ret < 0) {
					break;
				};
				if (status.status == SND_PCM_STATUS_READY ||
						status.status == SND_PCM_STATUS_UNDERRUN) {
					snd_pcm_plugin_prepare(ad->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
				} else {
					break;
				};
			};
		};
	};

	snd_pcm_plugin_flush(ad->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);

	ad->thread_exited = true;
	printf("**************** audio thread exit\n");
};
示例#16
0
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;
}
示例#17
0
/* public methods (static but exported through the sysdep_dsp or plugin
   struct) */
static void *alsa_dsp_create(const void *flags)
{
	int i, j;
//	audio_buf_info info;
	struct alsa_dsp_priv_data *priv = NULL;
	struct sysdep_dsp_struct *dsp = NULL;
	const struct sysdep_dsp_create_params *params = flags;
	const char *device = params->device;
	int err;
	int bytespersample;

	fprintf(stderr,"info: dsp_create called\n");
   
	/* allocate the dsp struct */
	if (!(dsp = calloc(1, sizeof(struct sysdep_dsp_struct))))
	{
		fprintf(stderr,
			"error: malloc failed for struct sysdep_dsp_struct\n");
		return NULL;
	}
   
	/* alloc private data */
	if(!(priv = calloc(1, sizeof(struct alsa_dsp_priv_data))))
	{
		fprintf(stderr,
			"error: malloc failed for struct dsp_priv_data\n");
		alsa_dsp_destroy(dsp);
		return NULL;
	}
   
	/* fill in the functions and some data */
	dsp->_priv = priv;
	dsp->get_freespace = alsa_dsp_get_freespace;
	dsp->write = alsa_dsp_write;
	dsp->destroy = alsa_dsp_destroy;
	dsp->hw_info.type = params->type;
	dsp->hw_info.samplerate = params->samplerate;

	priv->audio_dev.bMute = 0;
	priv->audio_dev.m_AudioHandle = NULL;
	priv->audio_dev.m_MixerHandle = NULL;
	priv->audio_dev.m_Acard = 0;
	priv->audio_dev.m_Adevice = 0;


	if (preferred_device)
	{	
 		if((err = snd_pcm_open_preferred(&(priv->audio_dev.m_AudioHandle), &priv->audio_dev.m_Acard,
                                       &priv->audio_dev.m_Adevice, SND_PCM_OPEN_PLAYBACK)) < 0)
    	{
			fprintf(stderr,"info: snd_pcm_open_preferred failed: %s \n", snd_strerror(err));
    	            alsa_dsp_destroy(dsp);
			return NULL;
    	}
	}
	else
	{
		fprintf(stderr,"info: audio is using primary device\n");
		if((err = snd_pcm_open(&(priv->audio_dev.m_AudioHandle), 0, 0, SND_PCM_OPEN_PLAYBACK)) < 0)
		{
			fprintf(stderr,"info: snd_pcm_open failed: %s \n", snd_strerror(err));
			alsa_dsp_destroy(dsp);
			return NULL;
		}
	}
	
	memset (&(priv->audio_dev.m_Achaninfo), 0, sizeof (priv->audio_dev.m_Achaninfo));
	priv->audio_dev.m_Achaninfo.channel = SND_PCM_CHANNEL_PLAYBACK;
	if ((err = snd_pcm_plugin_info (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Achaninfo))) < 0)
	{
		fprintf (stderr, "info: snd_pcm_plugin_info failed: %s\n", snd_strerror (err));
		alsa_dsp_destroy(dsp);
		return NULL;
	}

	//needed to enable the count status parameter, mmap plugin disables this
	if((err = snd_plugin_set_disable(priv->audio_dev.m_AudioHandle, PLUGIN_DISABLE_MMAP)) < 0)
	{
		fprintf (stderr, "info: snd_plugin_set_disable failed: %s\n", snd_strerror (err));
		alsa_dsp_destroy(dsp);
		return NULL;
	}

	/* calculate and set the fragsize & number of frags */
	/* fragsize (as power of 2) */
	i = 8;
	if (dsp->hw_info.type & SYSDEP_DSP_16BIT) i++;
	if (dsp->hw_info.type & SYSDEP_DSP_STEREO) i++;
	i += dsp->hw_info.samplerate / 22000;

	/* number of frags */
	j = ((dsp->hw_info.samplerate * alsa_dsp_bytes_per_sample[dsp->hw_info.type] *
		params->bufsize) / (0x01 << i)) + 1;

	bytespersample=1;
//	dsp->hw_info.type &= ~SYSDEP_DSP_16BIT;
//	dsp->hw_info.type &= ~SYSDEP_DSP_STEREO;
	if (dsp->hw_info.type & SYSDEP_DSP_16BIT) bytespersample++;
	if (dsp->hw_info.type & SYSDEP_DSP_STEREO) bytespersample <<= 1;
	
	memset( &(priv->audio_dev.m_Aparams), 0, sizeof(priv->audio_dev.m_Aparams));
	priv->audio_dev.m_Aparams.mode = SND_PCM_MODE_BLOCK;
	priv->audio_dev.m_Aparams.channel = SND_PCM_CHANNEL_PLAYBACK;
	priv->audio_dev.m_Aparams.start_mode = SND_PCM_START_FULL;
	priv->audio_dev.m_Aparams.stop_mode = SND_PCM_STOP_ROLLOVER;
#if 0
	priv->audio_dev.m_Aparams.buf.stream.queue_size = 512 * bytespersample;
	priv->audio_dev.m_Aparams.buf.stream.fill = SND_PCM_FILL_SILENCE;
	priv->audio_dev.m_Aparams.buf.stream.max_fill = 512 * bytespersample;
#endif
        priv->audio_dev.m_Aparams.format.interleave = 1;
        priv->audio_dev.m_Aparams.format.rate = dsp->hw_info.samplerate;
        priv->audio_dev.m_Aparams.format.voices = (dsp->hw_info.type & SYSDEP_DSP_STEREO) ? 2 : 1;

	priv->audio_dev.m_Aparams.buf.block.frag_size = 1000;
	priv->audio_dev.m_Aparams.buf.block.frags_min = 1;
	priv->audio_dev.m_Aparams.buf.block.frags_max = 5;

        priv->audio_dev.m_BytesPerSample = bytespersample;
        priv->audio_dev.m_Aparams.format.format = 
#ifdef LSB_FIRST
				(dsp->hw_info.type & SYSDEP_DSP_16BIT) ? SND_PCM_SFMT_S16_LE : SND_PCM_SFMT_U8; 
#else
				(dsp->hw_info.type & SYSDEP_DSP_16BIT) ? SND_PCM_SFMT_S16_BE : SND_PCM_SFMT_U8;
#endif

	if ((err = snd_pcm_plugin_params (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Aparams))) < 0)
	{
		fprintf (stderr, "info: snd_pcm_plugin_params failed: %s\n", snd_strerror (err));
		alsa_dsp_destroy(dsp);
		return NULL;
	}

	if ((err = snd_pcm_plugin_prepare (priv->audio_dev.m_AudioHandle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
	{
		fprintf (stderr, "warning: snd_pcm_plugin_prepare failed: %s\n", snd_strerror (err));
	}

	memset (&(priv->audio_dev.m_Asetup), 0, sizeof (priv->audio_dev.m_Asetup));
	priv->audio_dev.m_Asetup.channel = SND_PCM_CHANNEL_PLAYBACK;
	if ((err = snd_pcm_plugin_setup (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Asetup))) < 0)
	{
		fprintf (stderr, "warning: snd_pcm_plugin_setup failed: %s\n", snd_strerror (err));
		alsa_dsp_destroy(dsp);
		return NULL;
	}
	
	memset (&(priv->audio_dev.m_Astatus), 0, sizeof (priv->audio_dev.m_Astatus));
	priv->audio_dev.m_Astatus.channel = SND_PCM_CHANNEL_PLAYBACK;
	if ((err = snd_pcm_plugin_status (priv->audio_dev.m_AudioHandle, &(priv->audio_dev.m_Astatus))) < 0)
	{
		fprintf (stderr, "warning: snd_pcm_plugin_status failed: %s\n", snd_strerror (err));
        }
	dsp->hw_info.bufsize = priv->audio_dev.m_Asetup.buf.stream.queue_size  
	             		/ alsa_dsp_bytes_per_sample[dsp->hw_info.type];
#if 0
	if ((err=snd_pcm_nonblock_mode(priv->audio_dev.m_AudioHandle, 1))<0)
	{
		fprintf(stderr, "error: error with non block mode: %s\n", snd_strerror (err));
	}
#endif
	return dsp;
}
示例#18
0
文件: bb10_dev.c 项目: KevinHM/pjsip
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, &param) == 0) {
	param.sched_priority = 18;
	pthread_setschedparam (pthread_self(), policy, &param);
    }

    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;
}
示例#19
0
文件: qsa.c 项目: Sponk/NeoEditor
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, &param);
    param.sched_priority=param.sched_curpriority+1;
    SchedSet(0, 0, SCHED_NOCHANGE, &param);

    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;
}
示例#20
0
static void NTO_PlayAudio(_THIS)
{
    int written, rval;
    int towrite;
    void* pcmbuffer;

    if (!this->enabled)
    {
        return;
    }
    
    towrite = this->spec.size;
    pcmbuffer = pcm_buf;

    /* Write the audio data, checking for EAGAIN (buffer full) and underrun */
    do {
        written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite);
        if (written != towrite)
        {
            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));
                    cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
                    if ((rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0)
                    {
                        SDL_SetError("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n", snd_strerror(rval));
                        return;
                    }	
                    if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY))
                    {
                        if ((rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
                        {
                            SDL_SetError("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rval));
                            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;
    }

    return;
}
示例#21
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 *processTones(void *dummy)
{
    bool done;
    int error;
    int length;
    int index;
    Tone *tone, *nextTone;
    snd_pcm_channel_status_t status;


    //pthread_setname_np(pthread_self(), "tonegen");

    // Main loop. Wait for audio driver to need more data
    while( live ) {
        pthread_mutex_lock( &toneMutex );
        if( tone_count == 0 ) {
            // Wait for a tone command to come in
            snd_pcm_playback_flush( playback_handle );
            snd_pcm_plugin_prepare( playback_handle, SND_PCM_CHANNEL_PLAYBACK );

            pthread_cond_wait( &condvar_newtone, &toneMutex );
        }
        if( tone_count == 0 ) {
            pthread_mutex_unlock( &toneMutex );
            continue;
        }
        pthread_mutex_unlock( &toneMutex );

        // Send tone data
        FD_ZERO( &write_handles );
        FD_SET( sample_handle, &write_handles );
        error = select(sample_handle + 1, NULL, &write_handles, NULL, NULL);

        if( error < 0 ) {
            // Select failed.
            slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "processTones select failed %d (%d)\n", error, errno);
            pthread_mutex_unlock( &toneMutex );
            live = DEAD;
            break;
        }

        length = 0;

        // This should always be true
        if( FD_ISSET( sample_handle, &write_handles ) ) {
        	int active_count = 0;
        	for(tone = tones; tone != NULL; tone = tone->next) {
                done = tone->killed || (tonepos > tone->end);
    			//fprintf (stderr,"processTone::writeTone (before active check) tone %ld tone->end %ld active %d done %d tonepos %ld \n", tone, tone->end, tone->active, done, tonepos);
                if( !done ) {
                    // Write the tone
                    error = writeTone(tone, (tone != tones));
                    //error = tone->generator(tone->position, length, sample_frequency, frag_buffer, &tone->data, terminating);
                    if( error != EOK ) {
                        done = true;
                    }
                    active_count++;
                }

                tone->active &= !done;
    			//fprintf (stderr,"processTone::writeTone tone %ld tone->end %ld active %d tonepos %ld \n", tone, tone->end, tone->active, tonepos);
        	}

        	for(index = 0; index < frag_samples; index++) {
        		record_buffer[index*2  ] = stage_buffer[index] / stage_samples[index];
        		record_buffer[index*2+1] = stage_buffer[index] / stage_samples[index];
        	}

        	pthread_mutex_lock(&fillMutex);

        	if (render_buffer != NULL) {
        		memcpy(render_buffer, record_buffer, frame_size);
        	}

        	pthread_mutex_unlock(&fillMutex);

			tonepos += frag_samples;

			if (active_count > 0) {
				fprintf (stderr,"processTone tonepos %ld \n", tonepos);

				error = snd_pcm_plugin_write (playback_handle, record_buffer, frame_size);
				if( error != frame_size ) {
				   memset (&status, 0, sizeof (status));
					status.channel = SND_PCM_CHANNEL_PLAYBACK;
					if ((error = snd_pcm_plugin_status (playback_handle, &status)) < 0)
					{
						slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "retrieving audio interface status failed (%s)\n", snd_strerror (error));
					} else if (status.status == SND_PCM_STATUS_READY ||
							   status.status == SND_PCM_STATUS_UNDERRUN ||
							   status.status == SND_PCM_STATUS_CHANGE)
					{
						if ((error = snd_pcm_plugin_prepare (playback_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) {
							slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "cannot prepare audio interface for use (%s)\n", snd_strerror (error));
						}
					} else {
						slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "non-underrun write failure (%s)\n", snd_strerror (error));
					}
					// Retry now that we're prepared
					error = snd_pcm_plugin_write (playback_handle, record_buffer, frame_size);
				}
				if( error != frame_size ) {
					slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "write to audio interface failed (%s) %d\n", snd_strerror (error), error);
				}
			}

        } else {
            slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unknown file handle activated" );
        }

		pthread_mutex_lock( &toneMutex );


		//fprintf (stderr,"processTone::delete tones %lx count %d \n", tones, tone_count);

        int delete_count;
        do {
        	delete_count = 0;
			for(tone = tones; tone != NULL; tone = tone->next) {
				done = tone->killed || (tonepos > tone->end);
				if( done || !tone->active ) {
					// Remove the tone from the list
					if (tone->prev != NULL) {
						tone->prev->next = tone->next;
					} else {
						tones = tone->next;
					}
					if (tone->next != NULL) {
						tone->next->prev = tone->prev;
					}

					tone_count--;

					free(tone);

					delete_count++;

					fprintf (stderr,"processTone::delete tone %lx tones %lx count %d \n", tone, tones, tone_count);

					break;
				}
			}
        } while (delete_count > 0);

		pthread_mutex_unlock( &toneMutex );

        if (tone_count == 0) {
        	memset(record_buffer, 0, frame_size);
        }
    }

    return NULL;
}