예제 #1
0
bool SoundProcessor::Record(){
  SetUpRecorder();
  snd_pcm_sframes_t fwdframes=snd_pcm_forwardable(handle_m);
  printf("forwarding %d\n",fwdframes);
  snd_pcm_forward(handle_m,fwdframes);
  while (true) {
    rc_m = snd_pcm_readi(handle_m, buffer_m, frames);
    if (rc_m == -EPIPE) {
      /* EPIPE means overrun */
      fprintf(stderr, "overrun occurred\n");
      snd_pcm_prepare(handle_m);
    } else if (rc_m < 0) {
      fprintf(stderr,
              "error from read: %s\n",
              snd_strerror(rc_m));
    } else if (rc_m != (int)frames) {
      fprintf(stderr, "short read, read %d frames\n", rc_m);
    }
    rc_m = write(1, buffer_m, size);
    if (rc_m != size)
      fprintf(stderr,
              "short write: wrote %d bytes\n", rc_m);
  }

  snd_pcm_drain(handle_m);
  snd_pcm_close(handle_m);
  free(buffer_m);
  return true;
}
예제 #2
0
static long long get_delay(void) {
  snd_pcm_sframes_t frames = 0;
  snd_pcm_delay(alsa_handle, &frames);

  if (frames < 0)
  {
#if SND_LIB_VERSION >= 0x000901 /* snd_pcm_forward() exists since 0.9.0rc8 */
    snd_pcm_forward(alsa_handle, -frames);
#endif
    frames = 0;
  }

  return (long long)(frames * 1000000L / device_sample_rate);
}
예제 #3
0
double CAESinkALSA::GetDelay()
{
  if (!m_pcm)
    return 0;
  snd_pcm_sframes_t frames = 0;
  snd_pcm_delay(m_pcm, &frames);

  if (frames < 0)
  {
#if SND_LIB_VERSION >= 0x000901 /* snd_pcm_forward() exists since 0.9.0rc8 */
    snd_pcm_forward(m_pcm, -frames);
#endif
    frames = 0;
  }

  return (double)frames * m_formatSampleRateMul;
}
예제 #4
0
int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int bytes)
{
    snd_pcm_uframes_t frames;
    snd_pcm_sframes_t written;

#if SND_LIB_VERSION >= 0x000901
    snd_pcm_sframes_t delay;
    if (snd_pcm_delay(ai->handle, &delay) >= 0 && delay < 0)
        /* underrun - move the application pointer forward to catch up */
        snd_pcm_forward(ai->handle, -delay);
#endif
    frames = snd_pcm_bytes_to_frames(ai->handle, bytes);
    written = snd_pcm_writei(ai->handle, buf, frames);
    if (written >= 0)
        return snd_pcm_frames_to_bytes(ai->handle, written);
    else
        return written;
}
예제 #5
0
파일: ao_alsa.c 프로젝트: C3MA/fc_mplayer
/* delay in seconds between first and last sample in buffer */
static float get_delay(void)
{
  if (alsa_handler) {
    snd_pcm_sframes_t delay;

    if (snd_pcm_delay(alsa_handler, &delay) < 0)
      return 0;

    if (delay < 0) {
      /* underrun - move the application pointer forward to catch up */
#if SND_LIB_VERSION >= 0x000901 /* snd_pcm_forward() exists since 0.9.0rc8 */
      snd_pcm_forward(alsa_handler, -delay);
#endif
      delay = 0;
    }
    return (float)delay / (float)ao_data.samplerate;
  } else {
    return 0;
  }
}
예제 #6
0
/**************************************************************************
 * 				widRecorder			[internal]
 */
static	DWORD	CALLBACK	widRecorder(LPVOID pmt)
{
    WORD		uDevID = (DWORD_PTR)pmt;
    WINE_WAVEDEV*	wwi = &WInDev[uDevID];
    WAVEHDR*		lpWaveHdr;
    DWORD		dwSleepTime;
    DWORD		bytesRead;
    enum win_wm_message msg;
    DWORD_PTR		param;
    HANDLE		ev;
    DWORD               frames_per_period;

    wwi->state = WINE_WS_STOPPED;
    InterlockedExchange((LONG*)&wwi->dwTotalRecorded, 0);
    wwi->lpQueuePtr = NULL;

    SetEvent(wwi->hStartUpEvent);

    /* make sleep time to be # of ms to output a period */
    dwSleepTime = (wwi->dwPeriodSize * 1000) / wwi->format.Format.nAvgBytesPerSec;
    frames_per_period = snd_pcm_bytes_to_frames(wwi->pcm, wwi->dwPeriodSize);
    TRACE("sleeptime=%d ms, total buffer length=%d ms (%d bytes)\n", dwSleepTime, wwi->dwBufferSize * 1000 / wwi->format.Format.nAvgBytesPerSec, wwi->dwBufferSize);

    for (;;) {
	/* wait for dwSleepTime or an event in thread's queue */
	if (wwi->lpQueuePtr != NULL && wwi->state == WINE_WS_PLAYING)
        {
            DWORD frames;
            DWORD bytes;
            DWORD read;

            lpWaveHdr = wwi->lpQueuePtr;
            /* read all the fragments accumulated so far */
            frames = snd_pcm_avail_update(wwi->pcm);
            bytes = snd_pcm_frames_to_bytes(wwi->pcm, frames);

            TRACE("frames = %d  bytes = %d state=%d\n", frames, bytes, snd_pcm_state(wwi->pcm));
            if (snd_pcm_state(wwi->pcm) == SND_PCM_STATE_XRUN)
            {
                FIXME("Recovering from XRUN!\n");
                snd_pcm_prepare(wwi->pcm);
                frames = snd_pcm_avail_update(wwi->pcm);
                bytes = snd_pcm_frames_to_bytes(wwi->pcm, frames);
                snd_pcm_start(wwi->pcm);
                snd_pcm_forward(wwi->pcm, frames - snd_pcm_bytes_to_frames(wwi->pcm, wwi->dwPeriodSize));
                continue;
            }
            while (frames > 0 && wwi->lpQueuePtr)
            {
                TRACE("bytes = %d\n", bytes);
                if (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded < bytes)
                {
                    bytes = lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded;
                    frames = snd_pcm_bytes_to_frames(wwi->pcm, bytes);
                }
                /* directly read fragment in wavehdr */
                read = wwi->read(wwi->pcm, lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded, frames);
                bytesRead = snd_pcm_frames_to_bytes(wwi->pcm, read);

                TRACE("bytesRead=(%d(%d)/(%d)) -> (%d/%d)\n", bytesRead, read, frames, lpWaveHdr->dwBufferLength, lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
                if (read != (DWORD) -1)
                {
                    /* update number of bytes recorded in current buffer and by this device */
                    lpWaveHdr->dwBytesRecorded += bytesRead;
                    InterlockedExchangeAdd((LONG*)&wwi->dwTotalRecorded, bytesRead);
                    frames -= read;
                    bytes -= bytesRead;

                    /* buffer is full. notify client */
                    if (!snd_pcm_bytes_to_frames(wwi->pcm, lpWaveHdr->dwBytesRecorded - lpWaveHdr->dwBufferLength))
                    {
                        /* must copy the value of next waveHdr, because we have no idea of what
                         * will be done with the content of lpWaveHdr in callback
                         */
                        LPWAVEHDR	lpNext = lpWaveHdr->lpNext;

                        lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
                        lpWaveHdr->dwFlags |=  WHDR_DONE;

                        wwi->lpQueuePtr = lpNext;
                        widNotifyClient(wwi, WIM_DATA, (DWORD_PTR)lpWaveHdr, 0);
                        lpWaveHdr = lpNext;
                    }
                } else {
                    WARN("read(%s, %p, %d) failed (%d/%s)\n", wwi->pcmname,
                        lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded,
                        frames, frames, snd_strerror(read));
                }
            }
        }

        ALSA_WaitRingMessage(&wwi->msgRing, dwSleepTime);

	while (ALSA_RetrieveRingMessage(&wwi->msgRing, &msg, &param, &ev))
	{
            TRACE("msg=%s param=0x%lx\n", ALSA_getCmdString(msg), param);
	    switch (msg) {
	    case WINE_WM_PAUSING:
		wwi->state = WINE_WS_PAUSED;
                /*FIXME("Device should stop recording\n");*/
		SetEvent(ev);
		break;
	    case WINE_WM_STARTING:
		wwi->state = WINE_WS_PLAYING;
		snd_pcm_start(wwi->pcm);
		SetEvent(ev);
		break;
	    case WINE_WM_HEADER:
		lpWaveHdr = (LPWAVEHDR)param;
		lpWaveHdr->lpNext = 0;

		/* insert buffer at the end of queue */
		{
		    LPWAVEHDR*	wh;
		    for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
		    *wh = lpWaveHdr;
		}
		break;
	    case WINE_WM_STOPPING:
		if (wwi->state != WINE_WS_STOPPED)
		{
		    snd_pcm_drain(wwi->pcm);

		    /* read any headers in queue */
		    widRecorder_ReadHeaders(wwi);

		    /* return current buffer to app */
		    lpWaveHdr = wwi->lpQueuePtr;
		    if (lpWaveHdr)
		    {
		        LPWAVEHDR	lpNext = lpWaveHdr->lpNext;
		        TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
		        lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
		        lpWaveHdr->dwFlags |= WHDR_DONE;
		        wwi->lpQueuePtr = lpNext;
		        widNotifyClient(wwi, WIM_DATA, (DWORD_PTR)lpWaveHdr, 0);
		    }
		}
		wwi->state = WINE_WS_STOPPED;
		SetEvent(ev);
		break;
	    case WINE_WM_RESETTING:
		if (wwi->state != WINE_WS_STOPPED)
		{
		    snd_pcm_drain(wwi->pcm);
		}
		wwi->state = WINE_WS_STOPPED;
		wwi->dwTotalRecorded = 0;

		/* read any headers in queue */
		widRecorder_ReadHeaders(wwi);

		/* return all buffers to the app */
		while (wwi->lpQueuePtr) {
		    lpWaveHdr = wwi->lpQueuePtr;
		    TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
                    wwi->lpQueuePtr = lpWaveHdr->lpNext;
		    lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
		    lpWaveHdr->dwFlags |= WHDR_DONE;
		    widNotifyClient(wwi, WIM_DATA, (DWORD_PTR)lpWaveHdr, 0);
		}

		SetEvent(ev);
		break;
	    case WINE_WM_CLOSING:
		wwi->hThread = 0;
		wwi->state = WINE_WS_CLOSED;
		SetEvent(ev);
		ExitThread(0);
		/* shouldn't go here */
	    default:
		FIXME("unknown message %d\n", msg);
		break;
	    }
	}
    }
    ExitThread(0);
    /* just for not generating compilation warnings... should never be executed */
    return 0;
}
예제 #7
0
파일: dsoutput.c 프로젝트: r6144/wine
static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface,
						      LPDWORD lpdwPlay, LPDWORD lpdwWrite)
{
    IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
    snd_pcm_uframes_t hw_pptr, hw_wptr;
    snd_pcm_state_t state;

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

    if (!This->pcm)
    {
        FIXME("Bad pointer for pcm: %p\n", This->pcm);
        LeaveCriticalSection(&This->pcm_crst);
        return DSERR_GENERIC;
    }

    if (!lpdwPlay && !lpdwWrite)
        CommitAll(This);

    state = snd_pcm_state(This->pcm);

    if (state != SND_PCM_STATE_PREPARED && state != SND_PCM_STATE_RUNNING)
    {
        CheckXRUN(This);
        state = snd_pcm_state(This->pcm);
    }
    if (state == SND_PCM_STATE_RUNNING)
    {
        snd_pcm_sframes_t used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm);

        if (used < 0)
        {
            WARN("Underrun: %ld / %ld\n", used, snd_pcm_avail_update(This->pcm));
            if (This->mmap)
            {
                snd_pcm_forward(This->pcm, -used);
                This->mmap_pos += -used;
                This->mmap_pos %= This->mmap_buflen_frames;
            }
            used = 0;
        }

        if (This->mmap_pos > used)
            hw_pptr = This->mmap_pos - used;
        else
            hw_pptr = This->mmap_buflen_frames + This->mmap_pos - used;
        hw_pptr %= This->mmap_buflen_frames;

        TRACE("At position: %ld (%ld) - Used %ld\n", hw_pptr, This->mmap_pos, used);
    }
    else hw_pptr = This->mmap_pos;
    hw_wptr = This->mmap_pos;

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

    if (lpdwPlay)
        *lpdwPlay = snd_pcm_frames_to_bytes(This->pcm, hw_pptr);
    if (lpdwWrite)
        *lpdwWrite = snd_pcm_frames_to_bytes(This->pcm, hw_wptr);

    TRACE("hw_pptr=0x%08x, hw_wptr=0x%08x playpos=%d, writepos=%d\n", (unsigned int)hw_pptr, (unsigned int)hw_wptr, lpdwPlay?*lpdwPlay:-1, lpdwWrite?*lpdwWrite:-1);
    return DS_OK;
}