Пример #1
0
/** Fill buffers, for starting and stopping
 * Alsa won't start playing until everything is filled up
 * This also updates mmap_pos
 *
 * Returns: Amount of periods in use so snd_pcm_avail_update
 * doesn't have to be called up to 4x in GetPosition()
 */
static snd_pcm_uframes_t CommitAll(IDsDriverBufferImpl *This)
{
    const snd_pcm_channel_area_t *areas;
    snd_pcm_uframes_t used;
    const snd_pcm_uframes_t commitahead = This->mmap_commitahead;

    used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm);
    TRACE("%p needs to commit to %lu, used: %lu\n", This, commitahead, used);
    if (used < commitahead)
    {
        snd_pcm_uframes_t done, putin = commitahead - used;
        snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
        done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
        This->mmap_pos += done;
        used += done;
        putin = commitahead - used;

        if (This->mmap_pos == This->mmap_buflen_frames && (snd_pcm_sframes_t)putin > 0)
        {
            snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
            done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
            This->mmap_pos += done;
            used += done;
        }
    }

    if (This->mmap_pos == This->mmap_buflen_frames)
        This->mmap_pos = 0;

    return used;
}
Пример #2
0
static HRESULT WINAPI IDsDriverBufferImpl_Unlock(PIDSDRIVERBUFFER iface,
        LPVOID pvAudio1,DWORD dwLen1,
        LPVOID pvAudio2,DWORD dwLen2)
{
    IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
    snd_pcm_uframes_t writepos;

    if (!dwLen1)
        return DS_OK;

    /* **** */
    EnterCriticalSection(&This->pcm_crst);

    writepos = snd_pcm_bytes_to_frames(This->pcm, (DWORD_PTR)pvAudio1 - (DWORD_PTR)This->mmap_buffer);
    if (writepos == This->mmap_pos)
    {
        const snd_pcm_channel_area_t *areas;
        snd_pcm_uframes_t writelen = snd_pcm_bytes_to_frames(This->pcm, dwLen1);
        TRACE("Committing data\n");
        This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, writelen);
        if (This->mmap_pos == This->mmap_buflen_frames)
            This->mmap_pos = 0;
        if (!This->mmap_pos && dwLen2)
        {
            writelen = snd_pcm_bytes_to_frames(This->pcm, dwLen2);
            snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &writelen);
            This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, writelen);
            assert(This->mmap_pos < This->mmap_buflen_frames);
        }
    }
    LeaveCriticalSection(&This->pcm_crst);
    /* **** */

    return DS_OK;
}
Пример #3
0
/** Fill buffers, for starting and stopping
 * Alsa won't start playing until everything is filled up
 * This also updates mmap_pos
 *
 * Returns: Amount of periods in use so snd_pcm_avail_update
 * doesn't have to be called up to 4x in GetPosition()
 */
static snd_pcm_uframes_t CommitAll(IDsDriverBufferImpl *This)
{
    const snd_pcm_channel_area_t *areas;
    snd_pcm_sframes_t used;
    const snd_pcm_uframes_t commitahead = This->mmap_commitahead;

    used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm);
    if (used < 0) used = 0;
    TRACE("%p needs to commit to %lu, used: %ld\n", This, commitahead, used);
    if (used < commitahead)
    {
        snd_pcm_sframes_t done;
        snd_pcm_uframes_t putin = commitahead - used;
        if (This->mmap)
        {
            snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
            done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
        }
        else
        {
            if (putin + This->mmap_pos > This->mmap_buflen_frames)
                putin = This->mmap_buflen_frames - This->mmap_pos;
            done = snd_pcm_writei(This->pcm, This->mmap_buffer + snd_pcm_frames_to_bytes(This->pcm, This->mmap_pos), putin);
            if (done < putin) WARN("Short write %ld/%ld\n", putin, done);
        }
        if (done < 0) done = 0;
        This->mmap_pos += done;
        used += done;
        putin = commitahead - used;

        if (This->mmap_pos == This->mmap_buflen_frames && (snd_pcm_sframes_t)putin > 0)
        {
            if (This->mmap)
            {
                snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
                done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
                This->mmap_pos += done;
            }
            else
            {
                done = snd_pcm_writei(This->pcm, This->mmap_buffer, putin);
                if (done < putin) WARN("Short write %ld/%ld\n", putin, done);
                if (done < 0) done = 0;
                This->mmap_pos = done;
            }
            used += done;
        }
    }

    if (This->mmap_pos == This->mmap_buflen_frames)
        This->mmap_pos = 0;

    return used;
}
Пример #4
0
static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface)
{
    const snd_pcm_channel_area_t *areas;
    snd_pcm_uframes_t avail;
    snd_pcm_format_t format;
    IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
    TRACE("(%p)\n",iface);

    /* **** */
    EnterCriticalSection(&This->pcm_crst);
    avail = This->mmap_buflen_frames;
    snd_pcm_drop(This->pcm);
    snd_pcm_prepare(This->pcm);
    avail = snd_pcm_avail_update(This->pcm);
    snd_pcm_hw_params_get_format(This->hw_params, &format);
    if (This->mmap)
    {
        snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &avail);
        snd_pcm_format_set_silence(format, areas->addr, This->mmap_buflen_frames);
        snd_pcm_mmap_commit(This->pcm, This->mmap_pos, 0);
    }
    else
    {
        snd_pcm_format_set_silence(format, This->mmap_buffer, This->mmap_buflen_frames);
        snd_pcm_writei(This->pcm, This->mmap_buffer, This->mmap_buflen_frames);
        This->mmap_pos = 0;
    }

    /* **** */
    LeaveCriticalSection(&This->pcm_crst);
    return DS_OK;
}
Пример #5
0
snd_pcm_sframes_t snd_pcm_generic_mmap_commit(snd_pcm_t *pcm,
        snd_pcm_uframes_t offset,
        snd_pcm_uframes_t size)
{
    snd_pcm_generic_t *generic = pcm->private_data;
    return snd_pcm_mmap_commit(generic->slave, offset, size);
}
Пример #6
0
static snd_pcm_sframes_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm,
						 const snd_pcm_channel_area_t *areas,
						 snd_pcm_uframes_t offset,
						 snd_pcm_uframes_t size)
{
	snd_pcm_uframes_t xfer = 0;

	if (snd_pcm_mmap_capture_avail(pcm) < size) {
		SNDMSG("too short avail %ld to size %ld", snd_pcm_mmap_capture_avail(pcm), size);
		return -EPIPE;
	}
	while (size > 0) {
		const snd_pcm_channel_area_t *pcm_areas;
		snd_pcm_uframes_t pcm_offset;
		snd_pcm_uframes_t frames = size;
		snd_pcm_sframes_t result;
		
		snd_pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames);
		snd_pcm_areas_copy(areas, offset,
				   pcm_areas, pcm_offset,
				   pcm->channels, 
				   frames, pcm->format);
		result = snd_pcm_mmap_commit(pcm, pcm_offset, frames);
		if (result < 0)
			return xfer > 0 ? (snd_pcm_sframes_t)xfer : result;
		offset += result;
		xfer += result;
		size -= result;
	}
	return (snd_pcm_sframes_t)xfer;
}
Пример #7
0
/**
 * \brief Finish the capture noninterleave frame update (commit data to hardware)
 * \param pcm ordinary PCM handle
 * \param frames count of updated frames
 * \return count of transferred frames on success otherwise a negative error code
 */
snd_pcm_sframes_t sndo_pcm_cio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
{
	if (frames <= 0)
		return -EINVAL;
	if (frames % pcm->transfer_block)
		return -EINVAL;
	return snd_pcm_mmap_commit(pcm->capture, pcm->c_offset, frames);
}
Пример #8
0
/**
 * \brief Finish the playback interleave frame update (commit data to hardware)
 * \param pcm ordinary PCM handle
 * \param frames count of updated frames
 * \return count of transferred frames on success otherwise a negative error code
 */
snd_pcm_sframes_t sndo_pcm_pio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
{
	if (frames <= 0)
		return -EINVAL;
	if (frames % pcm->transfer_block)
		return -EINVAL;
	return snd_pcm_mmap_commit(pcm->playback, pcm->p_offset, frames);
}
Пример #9
0
mp_sint32 AudioDriver_ALSA::start()
{
	const snd_pcm_channel_area_t *my_areas;
	snd_pcm_uframes_t offset, frames, size;
	snd_async_handler_t *ahandler;
	int err;
	err = snd_async_add_pcm_handler(&ahandler, pcm, async_direct_callback, this);
	if (err < 0) {
		fprintf(stderr, "ALSA: Unable to register async handler (%s)\n", snd_strerror(err));
	}

	for (int count = 0; count < 2; count++) {
		size = period_size;
		while (size > 0) {
			frames = size;
			err = snd_pcm_mmap_begin(pcm, &my_areas, &offset, &frames);
			if (err < 0) {
				if ((err = snd_pcm_recover(pcm, err, 0)) < 0) {
					fprintf(stderr, "ALSA: MMAP begin error: %s\n", snd_strerror(err));
				}
			}
			// Sanity check
			if (my_areas->step != 32 && my_areas->first != 0)
				fprintf(stderr, "ALSA: Unsupported audio format.\n");

			memset(static_cast<char*> (my_areas->addr) + offset*4, 0, frames * 4);
			int commitres = snd_pcm_mmap_commit(pcm, offset, frames);
			if (err < 0 || (snd_pcm_uframes_t)commitres != frames) {
				if ((err = snd_pcm_recover(pcm, commitres >= 0 ? -EPIPE : commitres, 0)) < 0) {
					fprintf(stderr, "ALSA: MMAP commit error: %s\n", snd_strerror(err));
				}
			}
			size -= frames;
		}
	}

\
	err = snd_pcm_start(pcm);
	if (err < 0)
	{
		fprintf(stderr, "ALSA: Could not start PCM device (%s)\n", snd_strerror(err));
		return -1;
	}

	deviceHasStarted = true;
	return 0;
}
Пример #10
0
static snd_pcm_sframes_t snd_pcm_file_mmap_commit(snd_pcm_t *pcm,
					          snd_pcm_uframes_t offset,
						  snd_pcm_uframes_t size)
{
	snd_pcm_file_t *file = pcm->private_data;
	snd_pcm_uframes_t ofs;
	snd_pcm_uframes_t siz = size;
	const snd_pcm_channel_area_t *areas;
	snd_pcm_sframes_t result;

	snd_pcm_mmap_begin(file->gen.slave, &areas, &ofs, &siz);
	assert(ofs == offset && siz == size);
	result = snd_pcm_mmap_commit(file->gen.slave, ofs, siz);
	if (result > 0)
		snd_pcm_file_add_frames(pcm, areas, ofs, result);
	return result;
}
Пример #11
0
int alsa_async_direct_loop(alsa_dev_t *dev, void *ptr, void (*callback)(snd_async_handler_t *))
{
  snd_async_handler_t *ahandler;
  snd_pcm_t *phandle = dev->phandle;
  snd_pcm_t *chandle = dev->chandle;
  snd_pcm_uframes_t period_size = dev->period_size;
  pc_data_t *data = (pc_data_t *) ptr;
  PartConvMulti *pc = data->pc;

  const snd_pcm_channel_area_t *my_areas;
  snd_pcm_uframes_t offset, frames;
  snd_pcm_sframes_t avail, commitres;
  int err;

  err = snd_async_add_pcm_handler(&ahandler, phandle, callback, ptr);
  if (err < 0) {
    printf("Unable to register async handler\n");
    exit(-1);
  }
  
  do {  
    avail = snd_pcm_avail_update(phandle);
    if (avail == 0)
      break;
    
//     printf("\nADL: avail_playback == %d\n", avail);

    frames = period_size;
    err = snd_pcm_mmap_begin(phandle, &my_areas, &offset, &frames);
    if (err < 0) {
      printf("MMAP begin avail error: %s\n", snd_strerror(err));
      exit(-1);
    }
    
    if (frames != period_size)
    {
      printf("Error: [ADL] frames != period_size (%d != %d) after snd_pcm_mmap_begin()\n", (int)frames, (int)period_size);
      exit(-1);
    }

    commitres = snd_pcm_mmap_commit(phandle, offset, frames);
    if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
      printf("MMAP commit error: %s\n", snd_strerror(err));
      exit(-1);
    }
    avail = snd_pcm_avail_update(phandle);
  } while (1);

  do
  {
    avail = snd_pcm_avail_update(chandle);
    if (avail == 0)
      break;
    
//     printf("\nADL: avail_capture == %d\n", avail);

    frames = period_size;
    err = snd_pcm_mmap_begin(chandle, &my_areas, &offset, &frames);
    if (err < 0) {
	printf("MMAP begin avail error: %s\n", snd_strerror(err));
	exit(-1);
    }
    
    if (frames != period_size)
    {
      printf("Error: [ADL] frames != period_size (%d != %d) after snd_pcm_mmap_begin()\n", (int)frames, (int)period_size);
      exit(-1);
    }
    
    commitres = snd_pcm_mmap_commit(chandle, offset, frames);
    if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
	printf("MMAP commit error: %s\n", snd_strerror(err));
	exit(-1);
    }
    avail = snd_pcm_avail_update(chandle);
  } while (1);
  
  printf("About to start playback.\n");
  err = snd_pcm_start(phandle);
  if (err < 0) {
    printf("Playback start error: %s\n", snd_strerror(err));
    exit(-1);
  }  
  
  /* because all other work is done in the signal handler,
  suspend the process */
  
  if (pc->lastFrame == 0)
  {
    while(1)
    {
      printf("enter to exit: \n");
      if (getc(stdin) == '\n')
	break;
    }
  }
  else
  {
    printf("running for %d frames\n", pc->lastFrame);
    pc->doneWaiter->waitFor(1);
  }
  
  return 0;
}
Пример #12
0
static void set_params(void)
{
	snd_pcm_hw_params_t *params;
	snd_pcm_sw_params_t *swparams;
	snd_pcm_uframes_t buffer_size;
	int err;
	size_t n;
	unsigned int rate;
	snd_pcm_uframes_t start_threshold, stop_threshold;
	snd_pcm_hw_params_alloca(&params);
	snd_pcm_sw_params_alloca(&swparams);
	err = snd_pcm_hw_params_any(handle, params);
	if (err < 0) {
		error("Broken configuration for this PCM: no configurations available");
		exit(EXIT_FAILURE);
	}
	if (mmap_flag) {
		snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());
		snd_pcm_access_mask_none(mask);
		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
		err = snd_pcm_hw_params_set_access_mask(handle, params, mask);
	} else if (interleaved)
		err = snd_pcm_hw_params_set_access(handle, params,
						   SND_PCM_ACCESS_RW_INTERLEAVED);
	else
		err = snd_pcm_hw_params_set_access(handle, params,
						   SND_PCM_ACCESS_RW_NONINTERLEAVED);
	if (err < 0) {
		error("Access type not available");
		exit(EXIT_FAILURE);
	}
	err = snd_pcm_hw_params_set_format(handle, params, hwparams.format);
	if (err < 0) {
		error("Sample format non available");
		exit(EXIT_FAILURE);
	}
	err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);
	if (err < 0) {
		error("Channels count non available");
		exit(EXIT_FAILURE);
	}

#if 0
	err = snd_pcm_hw_params_set_periods_min(handle, params, 2);
	assert(err >= 0);
#endif
	rate = hwparams.rate;
	err = snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0);
	assert(err >= 0);
	if ((float)rate * 1.05 < hwparams.rate || (float)rate * 0.95 > hwparams.rate) {
		if (!quiet_mode) {
			char plugex[64];
			const char *pcmname = snd_pcm_name(handle);
			fprintf(stderr, "Warning: rate is not accurate (requested = %iHz, got = %iHz)\n", rate, hwparams.rate);
			if (! pcmname || strchr(snd_pcm_name(handle), ':'))
				*plugex = 0;
			else
				snprintf(plugex, sizeof(plugex), "(-Dplug:%s)",
					 snd_pcm_name(handle));
			fprintf(stderr, "         please, try the plug plugin %s\n",
				plugex);
		}
	}
	rate = hwparams.rate;
	if (buffer_time == 0 && buffer_frames == 0) {
		err = snd_pcm_hw_params_get_buffer_time_max(params,
							    &buffer_time, 0);
		assert(err >= 0);
		if (buffer_time > 500000)
			buffer_time = 500000;
	}
	if (period_time == 0 && period_frames == 0) {
		if (buffer_time > 0)
			period_time = buffer_time / 4;
		else
			period_frames = buffer_frames / 4;
	}
	if (period_time > 0)
		err = snd_pcm_hw_params_set_period_time_near(handle, params,
							     &period_time, 0);
	else
		err = snd_pcm_hw_params_set_period_size_near(handle, params,
							     &period_frames, 0);
	assert(err >= 0);
	if (buffer_time > 0) {
		err = snd_pcm_hw_params_set_buffer_time_near(handle, params,
							     &buffer_time, 0);
	} else {
		err = snd_pcm_hw_params_set_buffer_size_near(handle, params,
							     &buffer_frames);
	}
	assert(err >= 0);
	err = snd_pcm_hw_params(handle, params);
	if (err < 0) {
		error("Unable to install hw params:");
		snd_pcm_hw_params_dump(params, log);
		exit(EXIT_FAILURE);
	}
	snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
	snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
	if (chunk_size == buffer_size) {
		error("Can't use period equal to buffer size (%lu == %lu)",
		      chunk_size, buffer_size);
		exit(EXIT_FAILURE);
	}
	snd_pcm_sw_params_current(handle, swparams);
	if (avail_min < 0)
		n = chunk_size;
	else
		n = (double) rate * avail_min / 1000000;
	err = snd_pcm_sw_params_set_avail_min(handle, swparams, n);
	if (err < 0) {
		error("Setting sw params failed\n");
	}

	/* round up to closest transfer boundary */
	n = buffer_size;
	if (start_delay <= 0) {
		start_threshold = n + (double) rate * start_delay / 1000000;
	} else
		start_threshold = (double) rate * start_delay / 1000000;
	if (start_threshold < 1)
		start_threshold = 1;
	if (start_threshold > n)
		start_threshold = n;
	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
	assert(err >= 0);
	if (stop_delay <= 0) 
		stop_threshold = buffer_size + (double) rate * stop_delay / 1000000;
	else
		stop_threshold = (double) rate * stop_delay / 1000000;
	err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
	assert(err >= 0);

	if (snd_pcm_sw_params(handle, swparams) < 0) {
		error("unable to install sw params:");
		snd_pcm_sw_params_dump(swparams, log);
		exit(EXIT_FAILURE);
	}

	if (verbose)
		snd_pcm_dump(handle, log);

	bits_per_sample = snd_pcm_format_physical_width(hwparams.format);
	bits_per_frame = bits_per_sample * hwparams.channels;
	chunk_bytes = chunk_size * bits_per_frame / 8;
	audiobuf = realloc(audiobuf, chunk_bytes);
	if (audiobuf == NULL) {
		error("not enough memory");
		exit(EXIT_FAILURE);
	}
	// fprintf(stderr, "real chunk_size = %i, frags = %i, total = %i\n", chunk_size, setup.buf.block.frags, setup.buf.block.frags * chunk_size);

	/* stereo VU-meter isn't always available... */
	if (vumeter == VUMETER_STEREO) {
		if (hwparams.channels != 2 || !interleaved || verbose > 2)
			vumeter = VUMETER_MONO;
	}

	/* show mmap buffer arragment */
	if (mmap_flag && verbose) {
		const snd_pcm_channel_area_t *areas;
		snd_pcm_uframes_t offset;
		int i;
		err = snd_pcm_mmap_begin(handle, &areas, &offset, &chunk_size);
		if (err < 0) {
			error("snd_pcm_mmap_begin problem: %s", snd_strerror(err));
			exit(EXIT_FAILURE);
		}
		for (i = 0; i < hwparams.channels; i++)
			fprintf(stderr, "mmap_area[%i] = %p,%u,%u (%u)\n", i, areas[i].addr, areas[i].first, areas[i].step, snd_pcm_format_physical_width(hwparams.format));
		/* not required, but for sure */
		snd_pcm_mmap_commit(handle, offset, 0);
	}

	buffer_frames = buffer_size;	/* for position test */
}
Пример #13
0
/** Fill buffers, for starting and stopping
 * Alsa won't start playing until everything is filled up
 * This also updates mmap_pos
 *
 * Returns: Amount of periods in use so snd_pcm_avail_update
 * doesn't have to be called up to 4x in GetPosition()
 */
static snd_pcm_uframes_t CommitAll(IDsCaptureDriverBufferImpl *This, DWORD forced)
{
    const snd_pcm_channel_area_t *areas;
    snd_pcm_uframes_t used;
    const snd_pcm_uframes_t commitahead = This->mmap_buflen_frames;

    used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm);
    TRACE("%p needs to commit to %lu, used: %lu\n", This, commitahead, used);
    if (used < commitahead && (forced || This->play_looping))
    {
        snd_pcm_uframes_t done, putin = commitahead - used;
        if (This->mmap)
        {
            snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
            CopyData(This, This->mmap_pos, putin);
            done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);

            This->mmap_pos += done;
            used += done;
            putin = commitahead - used;

            if (This->mmap_pos == This->mmap_buflen_frames && (snd_pcm_sframes_t)putin > 0 && This->play_looping)
            {
                This->mmap_ofs_bytes += snd_pcm_frames_to_bytes(This->pcm, This->mmap_buflen_frames);
                This->mmap_ofs_bytes %= This->mmap_buflen_bytes;

                snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
                CopyData(This, This->mmap_pos, putin);
                done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);

                This->mmap_pos += done;
                used += done;
            }
        }
        else
        {
            DWORD pos;
            snd_pcm_sframes_t ret;

            snd_pcm_uframes_t cap = snd_pcm_bytes_to_frames(This->pcm, This->mmap_buflen_bytes);
            pos = realpos_to_fakepos(This, This->mmap_pos);
            if (This->mmap_pos + putin > cap)
                putin = cap - This->mmap_pos;
            ret = snd_pcm_readi(This->pcm, This->presented_buffer + pos, putin);
            if (ret == -EPIPE)
            {
                WARN("Underrun occurred\n");
                snd_pcm_prepare(This->pcm);
                ret = snd_pcm_readi(This->pcm, This->presented_buffer + pos, putin);
                snd_pcm_start(This->pcm);
            }
            if (ret < 0)
            {
                WARN("Committing data: %ld / %s (%ld)\n", ret, snd_strerror(ret), putin);
                ret = 0;
            }
            This->mmap_pos += ret;
            used += ret;
            /* At this point mmap_pos may be >= This->mmap_pos this is harmless
             * realpos_to_fakepos handles it well, and below it is truncated
             */

            putin = commitahead - used;
            if (putin > 0)
            {
                pos = realpos_to_fakepos(This, This->mmap_pos);
                ret = snd_pcm_readi(This->pcm, This->presented_buffer + pos, putin);
                if (ret > 0)
                {
                    This->mmap_pos += ret;
                    used += ret;
                }
            }
        }

    }

    if (This->mmap_pos >= This->mmap_buflen_frames)
    {
        This->mmap_ofs_bytes += snd_pcm_frames_to_bytes(This->pcm, This->mmap_buflen_frames);
        This->mmap_ofs_bytes %= This->mmap_buflen_bytes;
        This->mmap_pos -= This->mmap_buflen_frames;
    }

    return used;
}
Пример #14
0
int alsamm_send_dacs(void)
{

  static double timenow,timelast;

  t_sample *fpo, *fpi, *fp1, *fp2;
  int i, err, devno;

  const snd_pcm_channel_area_t *my_areas;
  snd_pcm_sframes_t size;
  snd_pcm_sframes_t commitres;
  snd_pcm_state_t state;
  snd_pcm_sframes_t ooffset, oavail;
  snd_pcm_sframes_t ioffset, iavail;

  /*
     unused channels should be zeroed out on startup (open) and stay this
  */
  int inchannels = STUFF->st_inchannels;
  int outchannels = STUFF->st_outchannels;

  timelast = sys_getrealtime();

#ifdef ALSAMM_DEBUG
  if(dac_send++ < 0)
    post("dac send called in %d, out %d, xrun %d",inchannels,outchannels, alsamm_xruns);

  if(alsamm_xruns && (alsamm_xruns % 1000) == 0)
    post("1000 xruns accoured");

  if(dac_send < WATCH_PERIODS){
    out_cm[dac_send] = -1;
    in_avail[dac_send] = out_avail[dac_send] = -1;
    in_offset[dac_send] = out_offset[dac_send] = -1;
    outaddr[dac_send] = inaddr[dac_send] = NULL;
    xruns_watch[dac_send] = alsamm_xruns;
  }
#endif

  if (!inchannels && !outchannels)
    {
      return SENDDACS_NO;
    }

  /* here we should check if in and out samples are here.
     but, the point is if out samples available also in sample should,
     so we don't make a precheck of insamples here and let outsample check be the
     the first of the forst card.
  */


  /* OUTPUT Transfer */
  fpo = STUFF->st_soundout;
  for(devno = 0;devno < alsa_noutdev;devno++){

    t_alsa_dev *dev = &alsa_outdev[devno];
    snd_pcm_t *out = dev->a_handle;
    int ochannels =dev->a_channels;



    /* how much samples available ??? */
    oavail = snd_pcm_avail_update(out);

    /* only one reason i can think about,
       the driver stopped and says broken pipe
       so this should not happen if we have enough stopthreshhold
       but if try to restart with next commit
    */
    if (oavail < 0) {

#ifdef ALSAMM_DEBUG
      broken_opipe++;
#endif
      err = xrun_recovery(out, -EPIPE);
      if (err < 0) {
        check_error(err,"otavail<0 recovery failed");
        return SENDDACS_NO;
      }
      oavail = snd_pcm_avail_update(out);
    }

    /* check if we are late and have to (able to) catch up */
    /* xruns will be ignored since you cant do anything since already happened */
    state = snd_pcm_state(out);
    if (state == SND_PCM_STATE_XRUN) {
      err = xrun_recovery(out, -EPIPE);
      if (err < 0) {
        check_error(err,"DAC XRUN recovery failed");
        return SENDDACS_NO;
      }
      oavail = snd_pcm_avail_update(out);

    } else if (state == SND_PCM_STATE_SUSPENDED) {
      err = xrun_recovery(out, -ESTRPIPE);
      if (err < 0) {
        check_error(err,"DAC SUSPEND recovery failed");
        return SENDDACS_NO;
      }
      oavail = snd_pcm_avail_update(out);
    }

#ifdef ALSAMM_DEBUG
    if(dac_send < WATCH_PERIODS){
      out_avail[dac_send] = oavail;
    }
#endif

    /* we only transfer transfersize of bytes request,
       this should only happen on first card otherwise we got a problem :-(()*/

    if(oavail < alsamm_transfersize){
      return SENDDACS_NO;
    }

    /* transfer now */
    size = alsamm_transfersize;
    fp1 = fpo;
    ooffset = 0;

    /* since this can go over a buffer boundery we maybe need two steps to
       transfer (normally when buffersize is a multiple of transfersize
       this should never happen) */

    while (size > 0) {

      int chn;
      snd_pcm_sframes_t oframes;

      oframes = size;

      err =  alsamm_get_channels(out, (unsigned long *)&oframes,
        (unsigned long *)&ooffset,ochannels,dev->a_addr);

#ifdef ALSAMM_DEBUG
      if(dac_send < WATCH_PERIODS){
        out_offset[dac_send] = ooffset;
        outaddr[dac_send] = (char *) dev->a_addr[0];
      }
#endif

      if (err < 0){
        if ((err = xrun_recovery(out, err)) < 0) {
          check_error(err,"MMAP begins avail error");
          break; /* next card please */
        }
      }

      /* transfer into memory */
      for (chn = 0; chn < ochannels; chn++) {

        t_alsa_sample32 *buf = (t_alsa_sample32 *)dev->a_addr[chn];

        /*
        osc(buf, oframes, (dac_send%1000 < 500)?-100.0:-10.0,440,&(indexes[chn]));
        */

        for (i = 0, fp2 = fp1 + chn*alsamm_transfersize; i < oframes; i++,fp2++)
          {
            float s1 = *fp2 * F32MAX;
            /* better but slower, better never clip ;-)
               buf[i]= CLIP32(s1); */
            buf[i]= ((int) s1 & 0xFFFFFF00);
            *fp2 = 0.0;
          }
      }

      commitres = snd_pcm_mmap_commit(out, ooffset, oframes);
      if (commitres < 0 || commitres != oframes) {
        if ((err = xrun_recovery(out, commitres >= 0 ? -EPIPE : commitres)) < 0) {
          check_error(err,"MMAP commit error");
          return SENDDACS_NO;
        }
      }

#ifdef ALSAMM_DEBUG
      if(dac_send < WATCH_PERIODS)
        out_cm[dac_send] = oframes;
#endif

      fp1 += oframes;
      size -= oframes;
    } /* while size */
    fpo += ochannels*alsamm_transfersize;

  }/* for devno */


  fpi = STUFF->st_soundin; /* star first card first channel */

  for(devno = 0;devno < alsa_nindev;devno++){

    t_alsa_dev *dev = &alsa_indev[devno];
    snd_pcm_t *in = dev->a_handle;
    int ichannels = dev->a_channels;

    iavail = snd_pcm_avail_update(in);

    if (iavail < 0) {
      err = xrun_recovery(in, iavail);
      if (err < 0) {
        check_error(err,"input avail update failed");
        return SENDDACS_NO;
      }
      iavail=snd_pcm_avail_update(in);
    }

    state = snd_pcm_state(in);

    if (state == SND_PCM_STATE_XRUN) {
      err = xrun_recovery(in, -EPIPE);
      if (err < 0) {
        check_error(err,"ADC XRUN recovery failed");
        return SENDDACS_NO;
      }
      iavail=snd_pcm_avail_update(in);

    } else if (state == SND_PCM_STATE_SUSPENDED) {
      err = xrun_recovery(in, -ESTRPIPE);
      if (err < 0) {
        check_error(err,"ADC SUSPEND recovery failed");
        return SENDDACS_NO;
      }
      iavail=snd_pcm_avail_update(in);
    }

    /* only transfer full transfersize or nothing */
    if(iavail < alsamm_transfersize){
      return SENDDACS_NO;
    }
    size = alsamm_transfersize;
    fp1 = fpi;
    ioffset = 0;

    /* since sysdata can go over a driver buffer boundery we maybe need two steps to
       transfer (normally when buffersize is a multiple of transfersize
       this should never happen) */

    while(size > 0){
      int chn;
      snd_pcm_sframes_t iframes = size;

      err =  alsamm_get_channels(in,
        (unsigned long *)&iframes, (unsigned long *)&ioffset,ichannels,dev->a_addr);
      if (err < 0){
        if ((err = xrun_recovery(in, err)) < 0) {
          check_error(err,"MMAP begins avail error");
          return SENDDACS_NO;
        }
      }

#ifdef ALSAMM_DEBUG
      if(dac_send < WATCH_PERIODS){
        in_avail[dac_send] = iavail;
        in_offset[dac_send] = ioffset;
        inaddr[dac_send] = dev->a_addr[0];
      }
#endif
      /* transfer into memory */

      for (chn = 0; chn < ichannels; chn++) {

        t_alsa_sample32 *buf = (t_alsa_sample32 *) dev->a_addr[chn];

        for (i = 0, fp2 = fp1 + chn*alsamm_transfersize; i < iframes; i++,fp2++)
          {
            /* mask the lowest bits, since subchannels info can make zero samples nonzero */
            *fp2 = (float) ((t_alsa_sample32) (buf[i] & 0xFFFFFF00))
              * (1.0 / (float) INT32_MAX);
          }
      }

      commitres = snd_pcm_mmap_commit(in, ioffset, iframes);
      if (commitres < 0 || commitres != iframes) {
        post("please never");
        if ((err = xrun_recovery(in, commitres >= 0 ? -EPIPE : commitres)) < 0) {
          check_error(err,"MMAP synced in commit error");
          return SENDDACS_NO;
        }
      }
      fp1 += iframes;
      size -= iframes;
    }
    fpi += ichannels*alsamm_transfersize;
  } /* for out devno < alsamm_outcards*/


  if ((timenow = sys_getrealtime()) > (timelast + sleep_time))
    {

#ifdef ALSAMM_DEBUG
      if(dac_send < 10 && sys_verbose)
        post("slept %f > %f + %f (=%f)",
             timenow,timelast,sleep_time,(timelast + sleep_time));
#endif
      return (SENDDACS_SLEPT);
    }

  return SENDDACS_YES;
}
Пример #15
0
static int alsamm_start()
{
  int err = 0;
  int devno;
  int chn,nchns;

  const snd_pcm_channel_area_t *mm_areas;

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("start audio with %d out cards and %d incards",alsamm_outcards,alsamm_incards);
#endif

  /* first prepare for in/out */
  for(devno = 0;devno < alsa_noutdev;devno++){

    snd_pcm_uframes_t offset, avail;
    t_alsa_dev *dev = &alsa_outdev[devno];

    /* snd_pcm_prepare also in xrun, but cannot harm here */
    if ((err = snd_pcm_prepare (dev->a_handle)) < 0) {
      check_error (err,"outcard prepare error for playback");
      return err;
    }

    offset = 0;
    avail = snd_pcm_avail_update(dev->a_handle);

    if (avail != (snd_pcm_uframes_t) alsamm_buffer_size) {
      check_error (avail,"full buffer not available at start");
    }

    /* cleaning out mmap buffer before start */

#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("start: set mems for avail=%d,offset=%d at buffersize=%d",
           avail,offset,alsamm_buffer_size);
#endif

    if(avail > 0){

      int comitted = 0;

      if ((err = alsamm_get_channels(dev->a_handle, &avail, &offset,
                                     dev->a_channels,dev->a_addr)) < 0) {
        check_error(err,"setting initial out channelspointer failure ?");
        continue;
      }

      for (chn = 0; chn < dev->a_channels; chn++)
        memset(dev->a_addr[chn],0,avail*ALSAMM_SAMPLEWIDTH_32);

      comitted = snd_pcm_mmap_commit (dev->a_handle, offset, avail);

      avail = snd_pcm_avail_update(dev->a_handle);

#ifdef ALSAMM_DEBUG
      if(sys_verbose)
        post("start: now channels cleared, out with avail=%d, offset=%d,comitted=%d",
             avail,offset,comitted);
#endif
    }
    /* now start, should be autostarted */
    avail = snd_pcm_avail_update(dev->a_handle);

#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("start: finish start, out with avail=%d, offset=%d",avail,offset);
#endif

    /* we have no autostart so anyway start*/
    if ((err = snd_pcm_start (dev->a_handle)) < 0) {
      check_error (err,"could not start playback");
    }
  }

  for(devno = 0;devno < alsa_nindev;devno++){

    snd_pcm_uframes_t ioffset, iavail;
    t_alsa_dev *dev = &alsa_indev[devno];

    /* if devices are synced then don't need to prepare
       hopefully dma in areas already filled correct by the card */

    if(dev->a_synced == 0){
      if ((err = snd_pcm_prepare (dev->a_handle)) < 0) {
        check_error (err,"incard prepare error for capture");
        /*      return err;*/
      }
    }

    ioffset = 0;
    iavail = snd_pcm_avail_update (dev->a_handle);

    /* cleaning out mmap buffer before start */
#ifdef ALSAMM_DEBUG
    post("start in: set in mems for avail=%d,offset=%d at buffersize=%d",
         iavail,ioffset,alsamm_buffer_size);
#endif

    if (iavail > (snd_pcm_uframes_t) 0) {

#ifdef ALSAMM_DEBUG
      post("empty buffer not available at start, since avail %d != %d buffersize",
           iavail, alsamm_buffer_size);
#endif

      if ((err = alsamm_get_channels(dev->a_handle, &iavail, &ioffset,
                                     dev->a_channels,dev->a_addr)) < 0) {
        check_error(err,"getting in channelspointer failure ????");
        continue;
      }

      snd_pcm_mmap_commit (dev->a_handle, ioffset, iavail);

      iavail = snd_pcm_avail_update (dev->a_handle);
#ifdef ALSAMM_DEBUG
      post("start in now avail=%d",iavail);
#endif
    }

#ifdef ALSAMM_DEBUG
     post("start: init inchannels with avail=%d, offset=%d",iavail,ioffset);
#endif

    /* if devices are synced then don't need to start */
    /* start with autostart , but anyway start */
    if(dev->a_synced == 0){
      if ((err = snd_pcm_start (dev->a_handle)) < 0) {
        check_error (err,"could not start capture");
        continue;
      }
    }

  }

  return err;
}
Пример #16
0
static ALuint ALSAProc(ALvoid *ptr)
{
    ALCdevice *Device = (ALCdevice*)ptr;
    alsa_data *data = (alsa_data*)Device->ExtraData;
    const snd_pcm_channel_area_t *areas = NULL;
    snd_pcm_uframes_t update_size, num_updates;
    snd_pcm_sframes_t avail, commitres;
    snd_pcm_uframes_t offset, frames;
    char *WritePtr;
    int err;

    SetRTPriority();

    update_size = Device->UpdateSize;
    num_updates = Device->NumUpdates;
    while(!data->killNow)
    {
        int state = verify_state(data->pcmHandle);
        if(state < 0)
        {
            ERR("Invalid state detected: %s\n", snd_strerror(state));
            aluHandleDisconnect(Device);
            break;
        }

        avail = snd_pcm_avail_update(data->pcmHandle);
        if(avail < 0)
        {
            ERR("available update failed: %s\n", snd_strerror(avail));
            continue;
        }

        if((snd_pcm_uframes_t)avail > update_size*(num_updates+1))
        {
            WARN("available samples exceeds the buffer size\n");
            snd_pcm_reset(data->pcmHandle);
            continue;
        }

        // make sure there's frames to process
        if((snd_pcm_uframes_t)avail < update_size)
        {
            if(state != SND_PCM_STATE_RUNNING)
            {
                err = snd_pcm_start(data->pcmHandle);
                if(err < 0)
                {
                    ERR("start failed: %s\n", snd_strerror(err));
                    continue;
                }
            }
            if(snd_pcm_wait(data->pcmHandle, 1000) == 0)
                ERR("Wait timeout... buffer size too low?\n");
            continue;
        }
        avail -= avail%update_size;

        // it is possible that contiguous areas are smaller, thus we use a loop
        while(avail > 0)
        {
            frames = avail;

            err = snd_pcm_mmap_begin(data->pcmHandle, &areas, &offset, &frames);
            if(err < 0)
            {
                ERR("mmap begin error: %s\n", snd_strerror(err));
                break;
            }

            WritePtr = (char*)areas->addr + (offset * areas->step / 8);
            aluMixData(Device, WritePtr, frames);

            commitres = snd_pcm_mmap_commit(data->pcmHandle, offset, frames);
            if(commitres < 0 || (commitres-frames) != 0)
            {
                ERR("mmap commit error: %s\n",
                    snd_strerror(commitres >= 0 ? -EPIPE : commitres));
                break;
            }

            avail -= frames;
        }
    }

    return 0;
}
Пример #17
0
int main()
{

const snd_pcm_channel_area_t *areas;
int size;
unsigned char *buffer;
char *pcm_name;
unsigned int rate = 44100;
int chan;
int rc;
unsigned int  val;
char check;
int pcmreturn;

//Set PCM stream and handle
snd_pcm_t *pcm_handle;
snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;

//Set HARDWARE parameters
snd_pcm_hw_params_t *hwparams;


//pcm_name = (char *)malloc(10);
pcm_name = "plughw:0,0";


//allocate memory for hardware
if(snd_pcm_hw_params_malloc(&hwparams)<0)
	{

		fprintf(stderr,"No memory allocated for hardware");
		return(-1);
	
	}



if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) {
      fprintf(stderr, "Error opening PCM device %s\n", pcm_name);
            return(-1);
	        }

//INITIALIZE HARDWARE WITH CONFIGURATION OF THE SOUNDCARD
	if(snd_pcm_hw_params_any(pcm_handle,hwparams)<0)
		{
			fprintf(stderr,"The hardware device cannot be configured\n");


		}




//SET FORMAT TO 16 BIT LITTLE ENDIAN
snd_pcm_hw_params_set_format(pcm_handle,hwparams,SND_PCM_FORMAT_S16_LE);


/* Two channels (stereo) */
 snd_pcm_hw_params_set_channels(pcm_handle,hwparams,2);

 
    /* 44100 bits/second sampling rate (CD quality) */
      
 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
       fprintf(stderr, "Error setting access.\n");
             return(-1);
	         }


//SETTING RATE ie SAMPLING FREQUENCY

snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0);


//SETTING HARDWARE PARAMETERS

	if(rc=(snd_pcm_hw_params(pcm_handle,hwparams))<0)
		{
			fprintf(stderr,"\nCannot set hardware parameters\n");
			return -1;
		}



//snd_pcm_uframes_t periodsize = 8192;


snd_pcm_uframes_t  frames,offset ;//OF TYPE UNSIGNED LONG
snd_pcm_sframes_t commitres;
frames =32;


//SETTING SOME MORE PARAMETERS

size = frames*4;
//SETTING BUFFER SIZE

/*if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize*2)>>2) < 0) {
      fprintf(stderr, "Error setting buffersize.\n");
            return(-1);


}
*/

int first=0;;
int err;
snd_pcm_sframes_t avail = snd_pcm_avail_update(pcm_handle);
printf("\nNumber of frames available is : %d \n",(int)avail);


//-------------------------------------------------------------------------------------------------------
//<<<<<<<<<<<<<<<<<<<<<<DISPLAYING INFORMATION>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Buffer size

snd_pcm_hw_params_get_buffer_size(hwparams, (snd_pcm_uframes_t*)&val);
printf("\nThe buffer size is %d \n",val);


//Buffer time

snd_pcm_hw_params_get_buffer_time(hwparams, &val,0);
printf("\nBuffer time is : %d \n",val);


//Period size

snd_pcm_hw_params_get_period_size(hwparams,&frames,0);
printf("\nperiod size : %d \n",(int)frames);



//Periods between buffers


err=snd_pcm_mmap_begin(pcm_handle,&areas,&offset,&frames);


//Periods between buffer

snd_pcm_hw_params_get_periods(hwparams,&val,0);
printf("\n Periods between buffer is : %d \n",val);




//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.

if(err<0)
	{
	printf("\nMMAP error\n");
	return -1;

	
	
	}
else printf("\n%d\n",err);



commitres = snd_pcm_mmap_commit(pcm_handle,offset,frames);
if(commitres<0)
	{
		printf("\nFrames not committed to memory\n");
	}



int dest =  open("sample3.wav",O_RDONLY);

if(dest<0)
	{
		perror("\nFile could not be opened\n");
		return -1;
	}


//int *c = offset;
buffer = (unsigned char *)malloc(1000);



unsigned long buf = offset;
 if(read(dest,&offset,1)<0)
	{
		perror("\nNo destination for read\n");
		return -1;
	}

struct timeval tvbefore,tvafter;
gettimeofday(&tvbefore,NULL);

while(read(dest,buffer,100)!=0);
gettimeofday(&tvafter,NULL);
printf("\nTime taken by read() is %09ld \n",tvafter.tv_usec-tvbefore.tv_usec);



/*


while(1)
	{
		if(read(dest,&offset,80)!=0)
			{
				//fread(buffer,sizeof(buffer),160,f1);
				
				
					{
						if(pcmreturn = snd_pcm_mmap_writei(pcm_handle,&offset,80)<0)
							{
								snd_pcm_prepare(pcm_handle);
								printf("\n<<<<<<<Buffer Underrun>>>>>>>>\n");
								break;
							}
					}
			

		

			}
		else break;

			
	}
*/	
}
Пример #18
0
static HRESULT WINAPI IDsDriverBufferImpl_Unlock(PIDSDRIVERBUFFER iface,
						 LPVOID pvAudio1,DWORD dwLen1,
						 LPVOID pvAudio2,DWORD dwLen2)
{
    IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
    snd_pcm_uframes_t writepos;

    if (!dwLen1)
        return DS_OK;

    /* **** */
    EnterCriticalSection(&This->pcm_crst);

    writepos = snd_pcm_bytes_to_frames(This->pcm, (DWORD_PTR)pvAudio1 - (DWORD_PTR)This->mmap_buffer);
    if (writepos == This->mmap_pos)
    {
        const snd_pcm_channel_area_t *areas;
        snd_pcm_uframes_t writelen = snd_pcm_bytes_to_frames(This->pcm, dwLen1);
        TRACE("Committing data\n");
        if (This->mmap)
            This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, writelen);
        else
        {
            int ret;
            ret = snd_pcm_writei(This->pcm, pvAudio1, writelen);
            if (ret == -EPIPE)
            {
                WARN("Underrun occurred\n");
                wine_snd_pcm_recover(This->pcm, -EPIPE, 1);
                ret = snd_pcm_writei(This->pcm, pvAudio1, writelen);

                /* Advance mmap pointer a little to make dsound notice the underrun and respond to it */
                if (ret < writelen) WARN("Short write %ld/%d\n", writelen, ret);
                This->mmap_pos += This->mmap_commitahead + ret;
                This->mmap_pos %= This->mmap_buflen_frames;
            }
            else if (ret > 0)
                This->mmap_pos += ret;
            if (ret < 0)
                WARN("Committing data: %d / %s (%p %ld)\n", ret, snd_strerror(ret), pvAudio1, writelen);
        }

        if (This->mmap_pos == This->mmap_buflen_frames)
            This->mmap_pos = 0;
        if (dwLen2)
        {
            writelen = snd_pcm_bytes_to_frames(This->pcm, dwLen2);
            if (This->mmap)
            {
                snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &writelen);
                This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, writelen);
            }
            else
            {
                int ret;
                ret = snd_pcm_writei(This->pcm, pvAudio2, writelen);
                if (ret < writelen) WARN("Short write %ld/%d\n", writelen, ret);
                This->mmap_pos = ret > 0 ? ret : 0;
            }
            assert(This->mmap_pos < This->mmap_buflen_frames);
        }
    }
    LeaveCriticalSection(&This->pcm_crst);
    /* **** */

    return DS_OK;
}
Пример #19
0
int main()
{
char *filename = "44k.wav";
 SF_INFO sfinfo;
  SNDFILE *f;
  f = sf_open(filename,SFM_READ, &sfinfo);
 printf("\nCHECK RATE %d \n",sfinfo.samplerate);
printf("\nCHECK CHANNELS %d \n",sfinfo.channels);
printf("\nNumber of frames %ld \n",sfinfo.frames);

int j; 


snd_pcm_t *pcm_handle;
char *pcm_name;
unsigned int err;
//pcm_name = "default";
pcm_name = "plughw:0,0";
snd_pcm_hw_params_t *hwparams;
unsigned int rate = sfinfo.samplerate;


unsigned int channels = sfinfo.channels;
unsigned int exact_rate;


 snd_pcm_uframes_t frames, offset;
 snd_pcm_sframes_t commitres, avail,size=170;
 const snd_pcm_channel_area_t *areas;
 unsigned char *ptr[2];
 
snd_pcm_format_t stream = SND_PCM_FORMAT_S16_LE;


err=snd_pcm_open(&pcm_handle,pcm_name,SND_PCM_STREAM_PLAYBACK,0);
         
         if(err<0)       
                 {       
                         perror("\nCannot open PCM device\n");
                         exit(0);
           	}


if(snd_pcm_hw_params_malloc(&hwparams)<0)
	{
		perror("\nMemory cannot be allocated\n");
		exit(0);
	}


if(snd_pcm_hw_params_any(pcm_handle,hwparams)<0)
	{
		perror("\nUnable to set any HW configuration to device\n");
		exit(0);
	}

exact_rate = rate;

if(snd_pcm_hw_params_set_rate_near(pcm_handle,  hwparams,  &exact_rate, 0)<0)
	{
		printf("\nUnable to set rate %u instead rate used is %u \n",rate,exact_rate);
	}
rate = exact_rate;
printf("\nExact rate is %u \n",rate);


if(snd_pcm_hw_params_set_channels(pcm_handle,  hwparams,  channels),0)
	{
		perror("\nUnable to set channels\n");
		exit(0);
	}
if(snd_pcm_hw_params_set_format(pcm_handle,  hwparams,  stream)<0)
	{
		perror("\nUnable to set format\n");
		exit(0);
	}

if(snd_pcm_hw_params_set_access(pcm_handle,  hwparams,  SND_PCM_ACCESS_MMAP_INTERLEAVED)<0)
	{
		perror("\nUnable to set access\n");
		exit(0);
	}



snd_pcm_sframes_t period_size;

snd_pcm_hw_params_get_period_size(hwparams, &period_size,0);
	
printf("\nPeriod size is %ld \n",period_size);



err = snd_pcm_hw_params(pcm_handle,hwparams);
if(err<0)
	{
		perror("\nHW params cannot be set\n");
		exit(0);
	}


snd_pcm_hw_params_get_period_size(hwparams,&period_size,0);
printf("\nObtained Period size = %ld \n",period_size);

size = period_size;

snd_pcm_hw_params_get_buffer_size(hwparams,&frames);
printf("\nObtained buffer size is %ld \n",frames);


int ret = open(filename,O_RDONLY);
if(ret<0)
	{
		perror("\nFile cannot be opened\n");
		exit(0);
	}



int k=0;
int i;

while(1)
	{
	k++;
	if(k==2)
		{
			err = snd_pcm_start(pcm_handle);
			if(err<0)
				{
					perror("\nError starting PCM device\n");
					exit(1);
				}
		}
 
		
	avail = snd_pcm_avail_update(pcm_handle);
		if(avail<frames)
			{
				err = snd_pcm_prepare(pcm_handle);
				if(err<0)
					{
						perror("\nNo frames available\n");
						exit(0);
					}
		}
//	printf("\nFrames available %ld\n",avail);

	
	size=period_size;


	while(size>0)
		{
			

			frames = size;

			err = snd_pcm_mmap_begin(pcm_handle,  &areas,  &offset,  &frames);
						
			 if(err<0)
				{
					perror("\nMMAP cannot assign areas\n");
					exit(0);
				}
			

			for(i=0;i<1;i++)
			{
			ptr[i] = (unsigned char *)areas[i].addr + areas[i].first/8 + offset*(areas[i].step/8) ;
		//	printf("\nCheck\n");


				if(ptr[i]==NULL)
					{
						perror("\nPointer cannot point to memory\n");
						exit(0);
					}

			}


			for(i=0;i<1;i++)
			if(read(ret, ptr[i], frames*4)>0)
				{
					
				
				}
			else 
				{
					perror("\nFile cannot be opened\n");
					exit(0);
				}

				      commitres = snd_pcm_mmap_commit(pcm_handle,  offset,  frames);
 
                                         if(commitres<0)
                                                 {
                                                         err = snd_pcm_prepare(pcm_handle);
 
                                                         if(err<0)
                                                                 {
                                                                 perror("\nFrames cannot be committed\n");
                                                                exit(0);
                                                                }
						
						}

				else size-=frames;
			snd_pcm_wait(pcm_handle,1000);


		}//END OF "while(size>0)" LOOP

		}//END OF OUTER WHILE LOOP

}
Пример #20
0
int main(int argc, char *argv[])
{
	int err;
	struct sniffer_state sts;

	sts.pcm_name = strdup("plughw:0,0");
	sts.stream = SND_PCM_STREAM_PLAYBACK;
	sts.format = SND_PCM_FORMAT_A_LAW;
	sts.rate = 8000;
//	sts.exact_rate;
	sts.periods = 2;
	sts.buffer_time = 25000;
	sts.period_time = 12500;

	snd_pcm_hw_params_alloca(&sts.hwparams);

	if (snd_pcm_open(&sts.pcm, sts.pcm_name, sts.stream, 0) < 0) {
		fprintf(stderr, "Error opening PCM device %s\n", sts.pcm_name);
		return(-1);
	}

	if (snd_pcm_hw_params_any(sts.pcm, sts.hwparams) < 0) {
		fprintf(stderr, "Can not configure this PCM device.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_access(sts.pcm, sts.hwparams,
			SND_PCM_ACCESS_MMAP_NONINTERLEAVED) < 0) {
		fprintf(stderr, "Error setting access.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_format(sts.pcm, sts.hwparams,
			sts.format) < 0) {
		fprintf(stderr, "Error setting format.\n");
		return(-1);
	}

	sts.exact_rate = sts.rate;
	if (snd_pcm_hw_params_set_rate_near(sts.pcm, sts.hwparams,
			&sts.exact_rate, 0) < 0) {
		fprintf(stderr, "Error setting rate.\n");
		return(-1);
	}

printf("rate: %d\n", sts.exact_rate);

	if (sts.rate != sts.exact_rate) {
		fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n"
			"==> Using %d Hz instead.\n", sts.rate, sts.exact_rate);
	}

	if (snd_pcm_hw_params_set_channels(sts.pcm, sts.hwparams, 1) < 0) {
		fprintf(stderr, "Error setting channels.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_periods(sts.pcm, sts.hwparams, sts.periods, 0) < 0) {
		fprintf(stderr, "Error setting periods.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_buffer_time_near(sts.pcm, sts.hwparams,
			&sts.buffer_time, &sts.dir) < 0) {
		fprintf(stderr, "Error setting buffersize.\n");
		return(-1);
	}

printf("buffer_time set to %d\n", sts.buffer_time);

	err = snd_pcm_hw_params_get_period_size(sts.hwparams, &sts.period_size, &sts.dir);
	if (err < 0) {
		printf("Unable to get period size for playback: %s\n", snd_strerror(err));
		return err;
	}

printf("period_size = %d\n", (int)sts.period_size);

	if (snd_pcm_hw_params(sts.pcm, sts.hwparams) < 0) {
		fprintf(stderr, "Error setting HW params.\n");
		return(-1);
	}

	setvbuf(stdout, (char *)NULL, _IONBF, 0);

	int router_control_fd = open("/dev/visdn/router-control", O_RDWR);
	if (router_control_fd < 0) {
		perror("Unable to open router-control");
		return 1;
	}

	int fd;
	fd = open("/dev/visdn/streamport", O_RDWR);
	if (fd < 0) {
		perror("cannot open /dev/visdn/streamport");
		return 1;
	}

	struct vsp_ctl vsp_ctl;
	if (ioctl(fd, VISDN_SP_GET_NODEID, (caddr_t)&vsp_ctl) < 0) {
		perror("ioctl(VISDN_SP_GET_NODEID)");
		return 1;
	}

	char node_id[80];
	snprintf(node_id, sizeof(node_id), "/sys/%s", vsp_ctl.node_id);

	struct visdn_connect vc;
	memset(&vc, 0, sizeof(vc));
	strncpy(vc.from_endpoint, argv[1],
				sizeof(vc.from_endpoint));
	strncpy(vc.to_endpoint, node_id,
				sizeof(vc.to_endpoint));

printf("Connect: %s => %s\n", vc.from_endpoint, vc.to_endpoint);

	if (ioctl(router_control_fd, VISDN_IOC_CONNECT, (caddr_t) &vc) < 0) {
		perror("ioctl(VISDN_CONNECT, br=>sp)");
		return 1;
	}

	int pipeline_id = vc.pipeline_id;

	memset(&vc, 0, sizeof(vc));
	vc.pipeline_id = pipeline_id;
	if (ioctl(router_control_fd, VISDN_IOC_PIPELINE_OPEN,
						(caddr_t)&vc) < 0) {
		perror("ioctl(VISDN_PIPELINE_OPEN, br=>sp)");
		return 1;
	}

	memset(&vc, 0, sizeof(vc));
	vc.pipeline_id = pipeline_id;
	if (ioctl(router_control_fd, VISDN_IOC_PIPELINE_START,
						(caddr_t)&vc) < 0) {
		perror("ioctl(VISDN_PIPELINE_START, br=>sp)");
		return 1;
	}






	//double phase = 0;
	const snd_pcm_channel_area_t *my_areas;
	snd_pcm_uframes_t offset, frames, size;
	snd_pcm_sframes_t avail, commitres;
	snd_pcm_state_t state;
	int first = 1;

	while (1) {
		state = snd_pcm_state(sts.pcm);

		if (state == SND_PCM_STATE_XRUN) {
			err = xrun_recovery(sts.pcm, -EPIPE);
			if (err < 0) {
				printf("XRUN recovery failed: %s\n", snd_strerror(err));
				return err;
			}
			first = 1;
		} else if (state == SND_PCM_STATE_SUSPENDED) {
			err = xrun_recovery(sts.pcm, -ESTRPIPE);
			if (err < 0) {
				printf("SUSPEND recovery failed: %s\n", snd_strerror(err));
				return err;
			}
		}

		avail = snd_pcm_avail_update(sts.pcm);
		if (avail < 0) {
			err = xrun_recovery(sts.pcm, avail);
			if (err < 0) {
				printf("avail update failed: %s\n", snd_strerror(err));
				return err;
			}
			first = 1;
			continue;
		}

		if (avail < sts.period_size) {
			if (first) {
				first = 0;
				err = snd_pcm_start(sts.pcm);
				if (err < 0) {
					printf("Start error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}
			} else {
				err = snd_pcm_wait(sts.pcm, -1);
				if (err < 0) {
					if ((err = xrun_recovery(sts.pcm, err)) < 0) {
						printf("snd_pcm_wait error: %s\n", snd_strerror(err));
						exit(EXIT_FAILURE);
					}
					first = 1;
				}
			}
			continue;
		}

		size = sts.period_size;
		while (size > 0) {
			frames = size;
			err = snd_pcm_mmap_begin(sts.pcm, &my_areas, &offset, &frames);
			if (err < 0) {
				if ((err = xrun_recovery(sts.pcm, err)) < 0) {
					printf("MMAP begin avail error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}

				first = 1;
			}

			int r = read(fd, my_areas[0].addr + offset, frames);
			printf("%d %d %d: ", (int)offset, (int)frames, r);

			int i;
			for (i=0; i<r; i++)
				printf("%02x", *(__u8 *)(my_areas[0].addr + i));

			printf("\n");

			commitres = snd_pcm_mmap_commit(sts.pcm, offset, frames);
			if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
				if ((err = xrun_recovery(sts.pcm, commitres >= 0 ? -EPIPE : commitres)) < 0) {
					printf("MMAP commit error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}
				first = 1;
			}
			size -= frames;
		}
	}

	return 0;
}
Пример #21
0
/**
 * Allocate the memory-mapped buffer for direct sound, and set up the
 * callback.
 */
static int DSDB_CreateMMAP(IDsDriverBufferImpl* pdbi)
{
    snd_pcm_t *pcm = pdbi->pcm;
    snd_pcm_format_t format;
    snd_pcm_uframes_t frames, ofs, avail, psize, boundary;
    unsigned int channels, bits_per_sample, bits_per_frame;
    int err, mmap_mode;
    const snd_pcm_channel_area_t *areas;
    snd_pcm_hw_params_t *hw_params = pdbi->hw_params;
    snd_pcm_sw_params_t *sw_params = pdbi->sw_params;
    void *buf;

    mmap_mode = snd_pcm_type(pcm);

    if (mmap_mode == SND_PCM_TYPE_HW)
        TRACE("mmap'd buffer is a direct hardware buffer.\n");
    else if (mmap_mode == SND_PCM_TYPE_DMIX)
        TRACE("mmap'd buffer is an ALSA dmix buffer\n");
    else
        TRACE("mmap'd buffer is an ALSA type %d buffer\n", mmap_mode);

    err = snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL);

    err = snd_pcm_hw_params_get_format(hw_params, &format);
    err = snd_pcm_hw_params_get_buffer_size(hw_params, &frames);
    err = snd_pcm_hw_params_get_channels(hw_params, &channels);
    bits_per_sample = snd_pcm_format_physical_width(format);
    bits_per_frame = bits_per_sample * channels;

    if (TRACE_ON(dsalsa))
        ALSA_TraceParameters(hw_params, NULL, FALSE);

    TRACE("format=%s  frames=%ld  channels=%d  bits_per_sample=%d  bits_per_frame=%d\n",
          snd_pcm_format_name(format), frames, channels, bits_per_sample, bits_per_frame);

    pdbi->mmap_buflen_frames = frames;
    pdbi->mmap_buflen_bytes = snd_pcm_frames_to_bytes( pcm, frames );

    snd_pcm_sw_params_current(pcm, sw_params);
    snd_pcm_sw_params_set_start_threshold(pcm, sw_params, 0);
    snd_pcm_sw_params_get_boundary(sw_params, &boundary);
    snd_pcm_sw_params_set_stop_threshold(pcm, sw_params, boundary);
    snd_pcm_sw_params_set_silence_threshold(pcm, sw_params, boundary);
    snd_pcm_sw_params_set_silence_size(pcm, sw_params, 0);
    snd_pcm_sw_params_set_avail_min(pcm, sw_params, 0);
    err = snd_pcm_sw_params(pcm, sw_params);

    avail = snd_pcm_avail_update(pcm);
    if ((snd_pcm_sframes_t)avail < 0)
    {
        ERR("No buffer is available: %s.\n", snd_strerror(avail));
        return DSERR_GENERIC;
    }

    if (!pdbi->mmap)
    {
        buf = pdbi->mmap_buffer = HeapAlloc(GetProcessHeap(), 0, pdbi->mmap_buflen_bytes);
        if (!buf)
            return DSERR_OUTOFMEMORY;

        snd_pcm_format_set_silence(format, buf, pdbi->mmap_buflen_frames);
        pdbi->mmap_pos = 0;
    }
    else
    {
        err = snd_pcm_mmap_begin(pcm, &areas, &ofs, &avail);
        if ( err < 0 )
        {
            ERR("Can't map sound device for direct access: %s/%d\n", snd_strerror(err), err);
            return DSERR_GENERIC;
        }
        snd_pcm_format_set_silence(format, areas->addr, pdbi->mmap_buflen_frames);
        pdbi->mmap_pos = ofs + snd_pcm_mmap_commit(pcm, ofs, 0);
        pdbi->mmap_buffer = areas->addr;
    }

    TRACE("created mmap buffer of %ld frames (%d bytes) at %p\n",
        frames, pdbi->mmap_buflen_bytes, pdbi->mmap_buffer);

    return DS_OK;
}
Пример #22
0
int main()
{

const snd_pcm_channel_area_t *areas;
int size;
unsigned char *buffer;
char *pcm_name;
unsigned int rate = 8000;
int chan;
int rc;
unsigned int  val;
char check;
int pcmreturn;

//Set PCM stream and handle
snd_pcm_t *pcm_handle;
snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;

//Set HARDWARE parameters
snd_pcm_hw_params_t *hwparams;


//pcm_name = (char *)malloc(10);
pcm_name = "plughw:0,0";


//allocate memory for hardware
if(snd_pcm_hw_params_malloc(&hwparams)<0)
	{

		fprintf(stderr,"No memory allocated for hardware");
		return(-1);
	
	}



if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) {
      fprintf(stderr, "Error opening PCM device %s\n", pcm_name);
            return(-1);
	        }

//INITIALIZE HARDWARE WITH CONFIGURATION OF THE SOUNDCARD
	if(snd_pcm_hw_params_any(pcm_handle,hwparams)<0)
		{
			fprintf(stderr,"The hardware device cannot be configured\n");


		}




//SET FORMAT TO 16 BIT LITTLE ENDIAN
snd_pcm_hw_params_set_format(pcm_handle,hwparams,SND_PCM_FORMAT_S16_LE);


/* Two channels (stereo) */
 snd_pcm_hw_params_set_channels(pcm_handle,hwparams,2);

 
    /* 44100 bits/second sampling rate (CD quality) */
      
 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
       fprintf(stderr, "Error setting access.\n");
             return(-1);
	         }


//SETTING RATE ie SAMPLING FREQUENCY

snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0);


//SETTING HARDWARE PARAMETERS

	if(rc=(snd_pcm_hw_params(pcm_handle,hwparams))<0)
		{
			fprintf(stderr,"\nCannot set hardware parameters\n");
			return -1;
		}



//snd_pcm_uframes_t periodsize = 8192;


snd_pcm_uframes_t  frames,offset ;//OF TYPE UNSIGNED LONG
snd_pcm_sframes_t commitres;
//frames =32;


//SETTING SOME MORE PARAMETERS

//size = frames*4;
//SETTING BUFFER SIZE

/*if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize*2)>>2) < 0) {
      fprintf(stderr, "Error setting buffersize.\n");
            return(-1);


}
*/

int first=0;;
int err;
snd_pcm_sframes_t avail = snd_pcm_avail_update(pcm_handle);
printf("\nNumber of frames available is : %d \n",(int)avail);


//-------------------------------------------------------------------------------------------------------
//<<<<<<<<<<<<<<<<<<<<<<DISPLAYING INFORMATION>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Buffer size

snd_pcm_hw_params_get_buffer_size(hwparams, (snd_pcm_uframes_t*)&val);
printf("\nThe buffer size is %d \n",val);


//Buffer time

snd_pcm_hw_params_get_buffer_time(hwparams, &val,0);
printf("\nBuffer time is : %d \n",val);


//Period size

snd_pcm_hw_params_get_period_size(hwparams,&frames,0);
printf("\nperiod size : %d \n",(int)frames);



////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
//<<<<<<<<<<<<<mmap_begin>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


err=snd_pcm_mmap_begin(pcm_handle,&areas,&offset,&frames);


//Periods between buffer

snd_pcm_hw_params_get_periods(hwparams,&val,0);
printf("\n Periods between buffer is : %d \n",val);




//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.

if(err<0)
	{
	printf("\nMMAP error\n");
	return -1;

	
	
	}
else printf("\n%d\n",err);


/*
commitres = snd_pcm_mmap_commit(pcm_handle,offset,frames);
if(commitres<0)
	{
		printf("\nFrames not committed to memory\n");
	}

*/

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<               >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,OPENING FILE>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>....



int dest =  open("sample3.wav",O_RDONLY);

if(dest<0)
	{
		perror("\nFile could not be opened\n");
		return -1;
	}



//buffer = (unsigned char *)malloc(1000);

/*

unsigned long buf = offset;
 if(read(dest,&offset,1)<0)
	{
		perror("\nNo destination for read\n");
		return -1;
	}
*/


/*
avail=snd_pcm_avail_update(pcm_handle);
printf("\nAvailable frames = %d \n\n",(int)avail);
struct timeval tvbefore,tvafter;
gettimeofday(&tvbefore,NULL);
*/
unsigned char *ptr[2];



int i;
//unsigned int steps=0;

for(i=0;i<2;i++)
 ptr[i] = (unsigned char*)areas[i].addr  + (areas[i].first/8) + offset*(areas[i].step/8);

printf("\nOffset of the first sample : %u \n",areas[0].first);
printf("\n\nOffset of the memory map is : %u \n",areas[0].step/8);
printf("\nAreas start address is : %u \n",areas[0].addr);
printf("\nNumber of frames ; %u \n",frames);

printf("\n\nPointer before ; %u \n",ptr[0]);


long pl;
for(pl=0;pl<100000;pl++);

if(ptr[1]==NULL)
printf("\nNull pointer 1  allocated\n");
if(ptr[0]==NULL)
printf("\nNull pointer 0 allocated \n");




int check2=1;

snd_pcm_sframes_t size2 =30;
while(1)
	{
		for(i=0;i<2;i++)
		{
		//ptr[i] = (unsigned char*)areas[i].addr + (areas[i].first/8) + offset*(areas[i].step/8);
		
		if(read(dest,ptr[i],120)!=0)
			{
				
				
					if(ptr[i]!=NULL)
					{
						 	
						if(pcmreturn = snd_pcm_mmap_writei(pcm_handle,ptr[i],size2)<0)
							{
								snd_pcm_prepare(pcm_handle);
								printf("\n<<<<<<<Buffer Underrun>>>>>>>>\n");
								break;
							}
					
			

						//	printf("\n%d\n",pcmreturn);
						ptr[i]+=0;
						printf("\n%lu\n",ptr[i]);


					}
											

			}
			else {
				check2=0;
				break;
				}
		}
		
		

		if(check2==0)
		break;
		

			
		
	//	l:break;

	}

	commitres = snd_pcm_mmap_commit(pcm_handle,offset,frames);
	 if(commitres<0)
	         {
	                 printf("\nFrames not committed to memory\n");
	         }

	
}
Пример #23
0
static void async_direct_callback(snd_async_handler_t *ahandler)
{
	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
	struct sniffer_state *sns = snd_async_handler_get_callback_private(ahandler);

	const snd_pcm_channel_area_t *my_areas;
	snd_pcm_uframes_t offset, frames, size;
	snd_pcm_sframes_t avail, commitres;
	snd_pcm_state_t state;
	int first = 0, err;

	while (1) {
		state = snd_pcm_state(handle);
		if (state == SND_PCM_STATE_XRUN) {
			err = xrun_recovery(handle, -EPIPE);
			if (err < 0) {
				printf("XRUN recovery failed: %s\n", snd_strerror(err));
				exit(EXIT_FAILURE);
			}

			first = 1;

		} else if (state == SND_PCM_STATE_SUSPENDED) {

			err = xrun_recovery(handle, -ESTRPIPE);

			if (err < 0) {
				printf("SUSPEND recovery failed: %s\n", snd_strerror(err));
				exit(EXIT_FAILURE);
			}
		}

		avail = snd_pcm_avail_update(handle);

		if (avail < 0) {
			err = xrun_recovery(handle, avail);
			if (err < 0) {
				printf("avail update failed: %s\n", snd_strerror(err));
				exit(EXIT_FAILURE);
			}
			first = 1;
			continue;
		}

		if (avail < sns->period_size) {
			if (first) {

				first = 0;

				err = snd_pcm_start(handle);
				if (err < 0) {
					printf("Start error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}
			} else {
				break;
			}

			continue;
		}

		size = sns->period_size;
		while (size > 0) {
			frames = size;
			err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames);
			if (err < 0) {
				if ((err = xrun_recovery(handle, err)) < 0) {
					printf("MMAP begin avail error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}
				first = 1;
			}

	printf("Callback %d %d\n", (int)offset, (int)frames);

			int i;
			for(i=0; i<frames; i++)
				*(__u8 *)(my_areas[0].addr + offset + i)=i%64;

			//generate_sine(my_areas, offset, frames, &sns->phase);

			commitres = snd_pcm_mmap_commit(handle, offset, frames);
			if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
				if ((err = xrun_recovery(handle, commitres >= 0 ? -EPIPE : commitres)) < 0) {
					printf("MMAP commit error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}
				first = 1;
			}
			size -= frames;
		}
	}
}
Пример #24
0
void AudioDriver_ALSA::async_direct_callback(snd_async_handler_t *ahandler)
{
	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
	AudioDriver_ALSA* audioDriver = (AudioDriver_ALSA*) snd_async_handler_get_callback_private(ahandler);
	const snd_pcm_channel_area_t *my_areas;
	snd_pcm_uframes_t offset, frames, size;
	snd_pcm_sframes_t avail, commitres;
	snd_pcm_state_t state;
	int first = 0, err;

	while (1) {
		state = snd_pcm_state(handle);
		if (state == SND_PCM_STATE_XRUN) {
			err = snd_pcm_recover(handle, -EPIPE, 0);
			if (err < 0) {
				fprintf(stderr, "ALSA: XRUN recovery failed: %s\n", snd_strerror(err));
			}
			first = 1;
		} else if (state == SND_PCM_STATE_SUSPENDED) {
			err = snd_pcm_recover(handle, ESTRPIPE, 0);
			if (err < 0) {
				fprintf(stderr, "ALSA: SUSPEND recovery failed: %s\n", snd_strerror(err));
			}
		}
		avail = snd_pcm_avail_update(handle);
		if (avail < 0) {
			err = snd_pcm_recover(handle, avail, 0);
			if (err < 0) {
				fprintf(stderr, "ALSA: avail update failed: %s\n", snd_strerror(err));
			}
			first = 1;
			continue;
		}
		if (avail < audioDriver->period_size) {
			if (first) {
				first = 0;
				err = snd_pcm_start(handle);
				if (err < 0) {
					fprintf(stderr, "ALSA: Start error: %s\n", snd_strerror(err));
				}
			} else {
				break;
			}
			continue;
		}

		frames = audioDriver->period_size;
		err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames);
		if (err < 0) {
			if ((err = snd_pcm_recover(handle, err, 0)) < 0) {
				fprintf(stderr, "ALSA: MMAP begin avail error: %s\n", snd_strerror(err));
			}
			first = 1;
		}

		if(frames != audioDriver->period_size)
			fprintf(stderr, "ALSA: Invalid buffer size: %lu (should be %lu), skipping..\n", frames, audioDriver->period_size);
			// Certain audio drivers will periodically request buffers of less than one period when
			// soft-resampling (ie, not running at native frequency).  Milkytracker can't handle this,
			// and bad things happen - so best to warn the user and not process.
			// PS - I've disabled soft-resampling for now (see below) so this shouldn't happen.
			// PPS - The downside is that if the user has the wrong mixer rate, they will get an error
			//       dialog - hopefully they'll read the message on stderr...
		else
			audioDriver->fillAudioWithCompensation(static_cast<char*> (my_areas->addr) + offset*4, frames * 2);

		commitres = snd_pcm_mmap_commit(handle, offset, frames);
		if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
			if ((err = snd_pcm_recover(handle, commitres >= 0 ? -EPIPE : commitres, 0)) < 0) {
				fprintf(stderr, "ALSA: MMAP commit error: %s\n", snd_strerror(err));
				// What now?
//				exit(1);
			}
			first = 1;
		}
	}
}
Пример #25
0
void *CallbackThread( void *userData )
{
    PaAlsaStream *stream = (PaAlsaStream*)userData;
    pthread_cleanup_push( &Stop, stream );   // Execute Stop on exit

    if( stream->pcm_playback )
        snd_pcm_start( stream->pcm_playback );
    else if( stream->pcm_capture )
        snd_pcm_start( stream->pcm_capture );

    while(1)
    {
        int frames_avail;
        int frames_got;

        PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* IMPLEMENT ME */
        int callbackResult;
        int framesProcessed;

        pthread_testcancel();
        {
            /* calculate time info */
            snd_timestamp_t capture_timestamp;
            snd_timestamp_t playback_timestamp;
            snd_pcm_status_t *capture_status;
            snd_pcm_status_t *playback_status;
            snd_pcm_status_alloca( &capture_status );
            snd_pcm_status_alloca( &playback_status );

            if( stream->pcm_capture )
            {
                snd_pcm_status( stream->pcm_capture, capture_status );
                snd_pcm_status_get_tstamp( capture_status, &capture_timestamp );
            }
            if( stream->pcm_playback )
            {
                snd_pcm_status( stream->pcm_playback, playback_status );
                snd_pcm_status_get_tstamp( playback_status, &playback_timestamp );
            }

            /* Hmm, we potentially have both a playback and a capture timestamp.
             * Hopefully they are the same... */
            if( stream->pcm_capture && stream->pcm_playback )
            {
                float capture_time = capture_timestamp.tv_sec +
                                     ((float)capture_timestamp.tv_usec/1000000);
                float playback_time= playback_timestamp.tv_sec +
                                     ((float)playback_timestamp.tv_usec/1000000);
                if( fabsf(capture_time-playback_time) > 0.01 )
                    PA_DEBUG(("Capture time and playback time differ by %f\n", fabsf(capture_time-playback_time)));
                timeInfo.currentTime = capture_time;
            }
            else if( stream->pcm_playback )
            {
                timeInfo.currentTime = playback_timestamp.tv_sec +
                                       ((float)playback_timestamp.tv_usec/1000000);
            }
            else
            {
                timeInfo.currentTime = capture_timestamp.tv_sec +
                                       ((float)capture_timestamp.tv_usec/1000000);
            }

            if( stream->pcm_capture )
            {
                snd_pcm_sframes_t capture_delay = snd_pcm_status_get_delay( capture_status );
                timeInfo.inputBufferAdcTime = timeInfo.currentTime -
                    (float)capture_delay / stream->streamRepresentation.streamInfo.sampleRate;
            }

            if( stream->pcm_playback )
            {
                snd_pcm_sframes_t playback_delay = snd_pcm_status_get_delay( playback_status );
                timeInfo.outputBufferDacTime = timeInfo.currentTime +
                    (float)playback_delay / stream->streamRepresentation.streamInfo.sampleRate;
            }
        }


        /*
            IMPLEMENT ME:
                - handle buffer slips
        */

        /*
            depending on whether the host buffers are interleaved, non-interleaved
            or a mixture, you will want to call PaUtil_ProcessInterleavedBuffers(),
            PaUtil_ProcessNonInterleavedBuffers() or PaUtil_ProcessBuffers() here.
        */

        framesProcessed = frames_avail = wait( stream );

        while( frames_avail > 0 )
        {
            //PA_DEBUG(( "%d frames available\n", frames_avail ));

            /* Now we know the soundcard is ready to produce/receive at least
             * one period.  We just need to get the buffers for the client
             * to read/write. */
            PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo,
                    0 /* @todo pass underflow/overflow flags when necessary */ );

            frames_got = setup_buffers( stream, frames_avail );


            PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );

            callbackResult = paContinue;

            /* this calls the callback */

            framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor,
                                                          &callbackResult );

            PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );

            /* inform ALSA how many frames we wrote */

            if( stream->pcm_capture )
                snd_pcm_mmap_commit( stream->pcm_capture, stream->capture_offset, frames_got );

            if( stream->pcm_playback )
                snd_pcm_mmap_commit( stream->pcm_playback, stream->playback_offset, frames_got );

            if( callbackResult != paContinue )
                break;

            frames_avail -= frames_got;
        }


        /*
            If you need to byte swap outputBuffer, you can do it here using
            routines in pa_byteswappers.h
        */

        if( callbackResult != paContinue )
        {
            stream->callback_finished = 1;
            stream->callbackAbort = (callbackResult == paAbort);

            pthread_exit( NULL );
        }
    }

    /* This code is unreachable, but important to include regardless because it
     * is possibly a macro with a closing brace to match the opening brace in
     * pthread_cleanup_push() above.  The documentation states that they must
     * always occur in pairs. */

    pthread_cleanup_pop( 1 );
}
Пример #26
0
bool
AlsaSource::WriteMmap ()
{
	snd_pcm_channel_area_t *areas = NULL;
	snd_pcm_uframes_t offset = 0;
	snd_pcm_uframes_t frames;
	snd_pcm_sframes_t available_samples;
	snd_pcm_sframes_t commitres = 0;
	guint32 channels = GetChannels ();
	int err = 0;
	AudioData *data [channels + 1];
	
	if (GetState () != AudioPlaying) {
		LOG_ALSA ("AlsaSource::WriteMmap (): trying to write when we're not playing (state: %i)\n", GetState ());
		return false;
	}

	if (!PreparePcm (&available_samples))
		return false;
	
	if (GetFlag (AudioEnded)) {
		Underflowed ();
		return false;
	}
	
	LOG_ALSA_EX ("AlsaSource::WriteMmap (): entering play loop, avail: %" G_GINT64_FORMAT ", sample size: %i\n", (gint64) available_samples, (int) period_size);
	
	frames = available_samples;
	
	mutex.Lock ();
	if (!initialized)
		goto cleanup;
		
	err = snd_pcm_mmap_begin (pcm, (const snd_pcm_channel_area_t** ) &areas, &offset, &frames);
	if (err < 0) {
		if (!XrunRecovery (err)) {
			LOG_AUDIO ("AudioPlayer: could not get mmapped memory: %s\n", snd_strerror (err));
			goto cleanup;
		}
		started = false;
	}
	
	LOG_ALSA_EX ("AlsaSource::WriteMmap (): can write %lu frames, avail: %lu\n", frames, available_samples);
	
	for (guint32 channel = 0; channel < channels; channel++) {
		data [channel] = (AudioData *) g_malloc (sizeof (AudioData));
		// pointer to the first sample to write to
		data [channel]->dest = ((gint8 *) areas [channel].addr) + (areas [channel].first / 8) + offset * areas [channel].step / 8;
		// distance (in bytes) between samples
		data [channel]->distance = areas [channel].step / 8;
	}
	data [channels] = NULL;
	
	frames = WriteFull (data, frames);
	
	for (guint32 channel = 0; channel < channels; channel++) {
		g_free (data [channel]);
	}
	
	commitres = snd_pcm_mmap_commit (pcm, offset, frames);
	
	LOG_ALSA_EX ("AlsaSource::WriteMmap (): played %i samples, of %i available samples, result: %i.\n", (int) frames, (int) 0, (int) commitres);
	
	if (commitres < 0 || (snd_pcm_uframes_t) commitres != frames) {
		if (!XrunRecovery (commitres >= 0 ? -EPIPE : commitres)) {
			LOG_AUDIO ("AudioPlayer: could not commit mmapped memory: %s\n", snd_strerror(err));
			commitres = 0; // so that we end up returning false
			goto cleanup;
		}
		started = false;
	}

cleanup:

	mutex.Unlock ();

	return commitres > 0;
}