示例#1
0
static snd_pcm_sframes_t snd_pcm_file_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
{
	snd_pcm_file_t *file = pcm->private_data;
	snd_pcm_channel_area_t areas[pcm->channels];
	snd_pcm_sframes_t n = snd_pcm_writen(file->gen.slave, bufs, size);
	if (n > 0) {
		snd_pcm_areas_from_bufs(pcm, areas, bufs);
		snd_pcm_file_add_frames(pcm, areas, 0, n);
	}
	return n;
}
示例#2
0
int SoundThread::playback_callback (snd_pcm_sframes_t nframes)
{
	int err;

	//printf ("playback callback called with %d frames\n", (int)nframes);
	void *channelsbuffer[1];
	channelsbuffer[0] = &samplebuffer;
	sndFIFO->read(samplebuffer, nframes);

	if ((err = snd_pcm_writen(playback_handle, (void **)channelsbuffer, nframes)) < 0)
	{
		fprintf (stderr, "write failed (%s)\n", snd_strerror (err));
	}

	return err;
}
TErrors SalsaStream::write(llaAudioPipe& buffer) {

	if(pcm_state_ == CLOSED) {
		LOGGER().warning(E_WRITE_STREAM, "Attempt to write to a closed stream.");
		return E_WRITE_STREAM;
	}

	TErrors err;
	if( (err = updateSettings(buffer)) != E_OK) return err;

	buffer.onSamplesReady();
	if(buffer.fail()) {
		return E_WRITE_STREAM;
	}

	char *iraw, **niraw;
	int rc;

	getRawOutputBuffers(buffer, &iraw, &niraw);

	TSize frames_to_deliver = getBufferLastWrite(buffer);
	if( frames_to_deliver <= 0 || frames_to_deliver > buffer_size_)
		frames_to_deliver = buffer.getBufferLength();

	if(organization_ == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
		rc = snd_pcm_writen(pcm_, (void**)niraw, frames_to_deliver);

	}
	else {
		rc = snd_pcm_writei(pcm_, (void*)iraw, frames_to_deliver);
	}

	if (rc == -EPIPE) {
	  /* EPIPE means underrun */
	  snd_pcm_prepare(pcm_);
	} else if (rc < 0) {
		LOGGER().warning(E_WRITE_STREAM, snd_strerror(rc));
		snd_pcm_recover(pcm_, rc, 0);
		return E_WRITE_STREAM;
	}

	return E_OK;
}
示例#4
0
    //==============================================================================
    bool writeToOutputDevice (AudioBuffer<float>& outputChannelBuffer, const int numSamples)
    {
        jassert (numChannelsRunning <= outputChannelBuffer.getNumChannels());
        float* const* const data = outputChannelBuffer.getArrayOfWritePointers();
        snd_pcm_sframes_t numDone = 0;

        if (isInterleaved)
        {
            scratch.ensureSize ((size_t) ((int) sizeof (float) * numSamples * numChannelsRunning), false);

            for (int i = 0; i < numChannelsRunning; ++i)
                converter->convertSamples (scratch.getData(), i, data[i], 0, numSamples);

            numDone = snd_pcm_writei (handle, scratch.getData(), (snd_pcm_uframes_t) numSamples);
        }
        else
        {
            for (int i = 0; i < numChannelsRunning; ++i)
                converter->convertSamples (data[i], data[i], numSamples);

            numDone = snd_pcm_writen (handle, (void**) data, (snd_pcm_uframes_t) numSamples);
        }

        if (numDone < 0)
        {
            if (numDone == -(EPIPE))
                underrunCount++;

            if (JUCE_ALSA_FAILED (snd_pcm_recover (handle, (int) numDone, 1 /* silent */)))
                return false;
        }

        if (numDone < numSamples)
            JUCE_ALSA_LOG ("Did not write all samples: numDone: " << numDone << ", numSamples: " << numSamples);

        return true;
    }
    //==============================================================================
    bool writeToOutputDevice (AudioSampleBuffer& outputChannelBuffer, const int numSamples)
    {
        jassert (numChannelsRunning <= outputChannelBuffer.getNumChannels());
        float** const data = outputChannelBuffer.getArrayOfChannels();
        snd_pcm_sframes_t numDone = 0;

        if (isInterleaved)
        {
            scratch.ensureSize (sizeof (float) * numSamples * numChannelsRunning, false);

            for (int i = 0; i < numChannelsRunning; ++i)
                converter->convertSamples (scratch.getData(), i, data[i], 0, numSamples);

            numDone = snd_pcm_writei (handle, scratch.getData(), numSamples);
        }
        else
        {
            for (int i = 0; i < numChannelsRunning; ++i)
                converter->convertSamples (data[i], data[i], numSamples);

            numDone = snd_pcm_writen (handle, (void**) data, numSamples);
        }

        if (failed (numDone))
        {
            if (numDone == -EPIPE)
            {
                if (failed (snd_pcm_prepare (handle)))
                    return false;
            }
            else if (numDone != -ESTRPIPE)
                return false;
        }

        return true;
    }
示例#6
0
snd_pcm_sframes_t snd_pcm_generic_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
{
    snd_pcm_generic_t *generic = pcm->private_data;
    return snd_pcm_writen(generic->slave, bufs, size);
}
示例#7
0
int alsa_play_play(alsa_play_t alsa_play, glc_audio_data_header_t *audio_hdr, char *data)
{
	snd_pcm_uframes_t frames, rem;
	snd_pcm_sframes_t ret = 0;
	unsigned int c;

	if (audio_hdr->id != alsa_play->id)
		return 0;

	if (!alsa_play->pcm) {
		glc_log(alsa_play->glc, GLC_ERROR, "alsa_play", "broken stream %d",
			 alsa_play->id);
		return EINVAL;
	}

	frames = snd_pcm_bytes_to_frames(alsa_play->pcm, audio_hdr->size);
	glc_utime_t time = glc_state_time(alsa_play->glc);
	glc_utime_t duration = ((glc_utime_t) 1000000000 * (glc_utime_t) frames) /
			       (glc_utime_t) alsa_play->rate;

	if (time + alsa_play->silence_threshold + duration < audio_hdr->time) {
		struct timespec ts = {
		.tv_sec = (audio_hdr->time - time - duration - alsa_play->silence_threshold)/1000000000,
		.tv_nsec = (audio_hdr->time - time - duration - alsa_play->silence_threshold)%1000000000 };
		nanosleep(&ts,NULL);
	}
	/*
	 * This condition determine what will be the initial audio packet.
	 * it is preferable to be ahead by < duration/2 than behind
	 * the video by > duration/2
	 */
	else if (time > audio_hdr->time + duration/2) {
		glc_log(alsa_play->glc, GLC_DEBUG, "alsa_play",
			"dropped packet. now %" PRId64 " ts %" PRId64,
			time, audio_hdr->time);
		return 0;
	}

	rem = frames;

	while (rem > 0) {
		/* alsa is horrible... */
		/*snd_pcm_wait(alsa_play->pcm, duration);*/

		if (alsa_play->flags & GLC_AUDIO_INTERLEAVED)
			ret = snd_pcm_writei(alsa_play->pcm,
					    &data[snd_pcm_frames_to_bytes(alsa_play->pcm, frames - rem)],
					    rem);
		else {
			for (c = 0; c < alsa_play->channels; c++)
				alsa_play->bufs[c] =
					&data[snd_pcm_samples_to_bytes(alsa_play->pcm, frames)
					      * c + snd_pcm_samples_to_bytes(alsa_play->pcm, frames - rem)];
			ret = snd_pcm_writen(alsa_play->pcm, alsa_play->bufs, rem);
		}

		if (ret == 0)
			break;

		if ((ret == -EBUSY) || (ret == -EAGAIN))
			break;
		else if (ret < 0) {
			if ((ret = alsa_play_xrun(alsa_play, ret))) {
				glc_log(alsa_play->glc, GLC_ERROR, "alsa_play",
					 "xrun recovery failed: %s", snd_strerror(-ret));
				return ret;
			}
		} else
			rem -= ret;
	}

	return 0;
}
示例#8
0
int main(void)
{
    /* Handle for the PCM device */
     snd_pcm_t *pcm_handle = NULL;

    /* Playback stream */
    snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
    
    /* This structure contains information about
     * the hardware and can be used to specify the
     * configuration to be used for the PCM stream.
     */
    snd_pcm_hw_params_t *hwparams;

    /* Name of the PCM device, like plughw:0,0 
     * The first number is the number of the soundcard,
     * the second number is the number ot the device.
     */
    char * pcm_name;

    /* Init pcm_name. Of course, later you
     * will make this configurable; 
     */
    pcm_name = strdup("plughw:0,0");

    /* Allocate the snd_pcm_hw_params_t structure on the stack.*/
    snd_pcm_hw_params_alloca(&hwparams);

    /* Open PCM. the last parameter of this function is the mode.
     * If this is set to 0, the standard mode is used. Possible
     * other values are SND_PCM_NONBLOCK AND SND_PCM_ASYNC.
     * if SND_PCM_NONBLOCK is used, read/write access to the
     * PCM device will return immediately. If SND_PCM_ASYNC is 
     * specified. SIGIO will be emitted whenever a period has
     * been completely processed by the soundcard.
     */
    if(snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0){
        fprintf(stderr, "Error opening PCM device %s\n", pcm_name);
        return (-1);
    }

    /* Init hwparams with full configuration space */
    if(snd_pcm_hw_params_any(pcm_handle, hwparams) < 0){
        fprintf(stderr, "Can not configure this PCM device.\n");
        return (-1);
    }

    int rate = 44100; /* Sample rate */
    int exact_rate;   /* Sample rate returned by snd_pcm_hw_params_set_rate_near */
    int dir;          /* exact_rate == rate --> dir = 0 */
                      /* exact_rate < rate  --> dir = -1 */
                      /* exact_rate > rate  --> dir = 1 */
    int periods = 2;  /* Number of periods */
    snd_pcm_uframes_t periodsize = 8192; /* Periodsize (bytes) */

    /* Set access type. This can be either
     * SND_PCM_ACCESS_RW_INTERLEAVED or 
     * SND_PCM_ACCESS_MMAP_NONINTERLEAVED.
     * There are also access types for MMAPed
     * access, but this is beyond the scope
     * of this introduction.
     */
    if(snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0){
        fprintf(stderr, "Error setting access.\n");
        return (-1);
    }
    
    /* Set sample format */
    if(snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0){
        fprintf(stderr, "Error setting format.\n");
        return (-1);
    }

    /* Set sample rate. If the exact rate is not supported by the hardware, use nearest possbile rate. */
    exact_rate = rate;
    if(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, 0) < 0){
        fprintf(stderr, "Error setting rate.\n");
        return (-1);
    }
    if(rate != exact_rate){
        fprintf(stderr, "The rate %d HZ is not supported by your hardware.\n ==> Using %d HZ instead.\n", rate, exact_rate);
    }

    /* Set number of channels */
    if(snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0){
        fprintf(stderr, "Error setting channels. \n");
        return (-1);
    }

    /* Set number of periods. Periods used to be called fragments. */
    if(snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0){
        fprintf(stderr, "Error setting periods.\n");
        return (-1);
    }

    /* Set buffer size (in frames). The resulting latency is given by 
     * latency = periodsize * periods / (rate * bytes_per_frame)
     */
    if(snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize * periods) >> 2) < 0){
        fprintf(stderr, "Error setting buffersize.\n");
        return (-1);
    }

    /* Apply HW parameter settins to 
     * PCM device and prepare device
     */
    if(snd_pcm_hw_params(pcm_handle, hwparams) < 0){
        fprintf(stderr, "Error setting HW params. \n");
        return (-1);
    }

#if 0
    /* Write num_frames frames from buffer data to
     * the PCM device pointed to by pcm_handle.
     * Returns the number of frames actually written. 
     */
    snd_pcm_sframes_t snd_pcm_writei(pcm_handle, data, num_frames);
#endif
#if 0
    /*Write num_frames frames from buffer data to 
     * the PCM device pointed to by pcm_handle.
     * Returns the number of frames actually written.
     */
    snd_pcm_sframes_t snd_pcm_writen(pcm_handle, data, num_frames);
#endif

    unsigned char *data;
    int pcmreturn, l1, l2;
    short s1, s2;
    int frames;
    int num_frames = 1024;

    data = (unsigned char *)malloc(periodsize);
    frames = periodsize >> 2;
    for(l1 = 0; l1 < 100; l1++){
        for(l2 = 0; l2 < num_frames; l2++){
            s1 = (l2 % 128) * 100 - 5000;
            s2 = (l2 % 256) * 100 - 5000;
            data[4*l2] = (unsigned char)s1;
            data[4*l2+1] = s1 >> 8;
            data[4*l2+2] = (unsigned char)s2;
            data[4*l2+3] = s2 >> 8;
        }
        while((pcmreturn = snd_pcm_writei(pcm_handle, data, frames)) < 0){
            snd_pcm_prepare(pcm_handle);
            fprintf(stderr, "<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>");
        }
    }


    /* Stop PCM device and drop pending frames */
    snd_pcm_drop(pcm_handle);

    /* Stop PCM device after pending frames have been played */
    snd_pcm_drain(pcm_handle);

    return 0;
}
示例#9
0
int playback_file(unsigned rate, uint16_t channels, int fd, uint32_t total_count)
{
    int rc;
    int size;
    uint32_t left_size;
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
	#ifdef INTEL
    int dir;
	#endif
    snd_pcm_uframes_t frames;
    char *buffer;                    /* TODO */

	/* Allocate a hardware parameters object. */
	rc = snd_pcm_hw_params_malloc(&params);
				if (rc < 0)
				{
					fprintf(stderr, "snd_pcm_hw_params_malloc: %s\n", snd_strerror(rc));
					exit(1);
   				}
	
    /* Open PCM device for playbacking. */
    rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
	//rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);
    if (rc < 0) {
        fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
        exit(1);
    }
   
   
    /* Fill it in with default values. */
    rc = snd_pcm_hw_params_any(handle, params);
				if (rc < 0)
				{
					fprintf(stderr, "snd_pcm_hw_params_any: %s\n", snd_strerror(rc));
					return 1;
				}
				
    /* Set the desired hardware parameters. */
    /* Interleaved mode */
	#ifdef INTERLEAVED
    rc = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
	#else
	rc = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_NONINTERLEAVED);
	#endif
				if (rc < 0) 
				{
					fprintf(stderr, "snd_pcm_hw_params_set_access: %d %s\n", rc, snd_strerror(rc));
					//return 1;
				}	
	

    /* Signed 16-bit little-endian format */
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);

    /* Two channels (stereo) */
    snd_pcm_hw_params_set_channels(handle, params, channels);

    /* 44100 bits/second sampling rate (CD quality) */
	#ifdef INTEL
    snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir);
	#else
	snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0);
	#endif
	

    /* Set period size to 32 frames. */
    frames = 32;
	#ifdef INTEL
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
	#else
	snd_pcm_hw_params_set_period_size_near(handle, params, &frames, 0);
	#endif

    /* Write the parameters to the driver */
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0) {
        fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
        exit(1);
    }

    /* Use a buffer large enough to hold one period */
	#ifdef INTEL
    snd_pcm_hw_params_get_period_size(params, &frames, &dir);
	#else
	snd_pcm_hw_params_get_period_size(params, &frames, 0);
	#endif
	fprintf(stderr, "get period size: %d\n", frames);
    
    size = frames * 16 / 8 * channels; /* 2 bytes/sample(16bit), 2 channels */
	
    buffer = (char *) malloc(size);
    
 //   while (left_size > 0) {
    while (1) {
        rc = read(fd, buffer, size);
		if(rc <= 0) {
			printf("at the end of file, exiting...\n");
			break;
			}
			
        totle_size += rc;                        /* totle data size */
        left_size = total_count - totle_size;
        if (rc != size)
         fprintf(stderr, "short read: read %d bytes\n", rc);
    
		#ifdef INTERLEAVED
        rc = snd_pcm_writei(handle, buffer, frames);
		#else
		void* Data[2];
		Data[0] = (void*)buffer;
		Data[1] = (void*)buffer;
		rc = snd_pcm_writen(handle, Data, frames);
		#endif
		
        if (rc == -EPIPE) {
         /* EPIPE means overrun */
         fprintf(stderr, "overrun occurred\n");
         snd_pcm_prepare(handle);
        } else if (rc < 0) {
         fprintf(stderr, "error from write: %s\n", snd_strerror(rc));
        } else if (rc != (int)frames) {
         fprintf(stderr, "short write, write %d frames\n", rc);
        }

		if(left_size <= 0){
			lseek(fd, sizeof(hdr), SEEK_SET);
			totle_size = 0;
			printf("again \n");
//			read(fd, &hdr, sizeof(hdr));				
		}
    }

	fprintf(stderr, "closing device \n");
	snd_pcm_drop(handle);
    fprintf(stderr, "4 \n");
    snd_pcm_drain(handle);
	fprintf(stderr, "3 \n");
    snd_pcm_close(handle);
	fprintf(stderr, "2 \n");
	
	if(params)
	{
		snd_pcm_hw_params_free(params);
	}
	
	fprintf(stderr, "1 \n");
    free(buffer);
	
	fprintf(stderr, "exit \n");

    return 0;
}